summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/current.txt117
-rw-r--r--api/system-current.txt7
-rw-r--r--cmds/incidentd/Android.mk2
-rw-r--r--cmds/statsd/src/atoms.proto19
-rw-r--r--cmds/statsd/src/stats_log.proto124
-rw-r--r--cmds/statsd/src/statsd_config.proto337
-rw-r--r--cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java1
-rw-r--r--core/java/android/app/ApplicationPackageManager.java13
-rw-r--r--core/java/android/app/PendingIntent.java19
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java41
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--core/java/android/app/slice/Slice.java31
-rw-r--r--core/java/android/app/slice/SliceItem.java12
-rw-r--r--core/java/android/app/slice/SliceProvider.java1
-rw-r--r--core/java/android/app/timezone/RulesState.java3
-rw-r--r--core/java/android/content/Intent.java8
-rw-r--r--core/java/android/content/pm/PackageManager.java15
-rw-r--r--core/java/android/content/pm/PackageParser.java149
-rw-r--r--core/java/android/os/Process.java2
-rw-r--r--core/java/android/provider/Settings.java23
-rw-r--r--core/java/android/security/keymaster/KeymasterDefs.java3
-rw-r--r--core/java/android/security/keystore/BackwardsCompat.java127
-rw-r--r--core/java/android/security/keystore/KeyDerivationParams.java2
-rw-r--r--core/java/android/security/keystore/RecoveryController.java30
-rw-r--r--core/java/android/security/keystore/recovery/BadCertificateFormatException.java28
-rw-r--r--core/java/android/security/keystore/recovery/DecryptionFailedException.java30
-rw-r--r--core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java35
-rw-r--r--core/java/android/security/keystore/recovery/KeyDerivationParams.aidl (renamed from core/java/android/security/keystore/KeyDerivationParams.aidl)2
-rw-r--r--core/java/android/security/keystore/recovery/KeyDerivationParams.java116
-rw-r--r--core/java/android/security/keystore/recovery/KeychainProtectionParams.aidl (renamed from core/java/android/security/keystore/KeychainProtectionParams.aidl)2
-rw-r--r--core/java/android/security/keystore/recovery/KeychainProtectionParams.java289
-rw-r--r--core/java/android/security/keystore/recovery/KeychainSnapshot.aidl (renamed from core/java/android/security/keystore/KeychainSnapshot.aidl)2
-rw-r--r--core/java/android/security/keystore/recovery/KeychainSnapshot.java300
-rw-r--r--core/java/android/security/keystore/recovery/LockScreenRequiredException.java30
-rw-r--r--core/java/android/security/keystore/recovery/RecoveryClaim.java54
-rw-r--r--core/java/android/security/keystore/recovery/RecoveryController.java535
-rw-r--r--core/java/android/security/keystore/recovery/RecoveryControllerException.java36
-rw-r--r--core/java/android/security/keystore/recovery/RecoverySession.java71
-rw-r--r--core/java/android/security/keystore/recovery/SessionExpiredException.java28
-rw-r--r--core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl (renamed from core/java/android/security/keystore/WrappedApplicationKey.aidl)2
-rw-r--r--core/java/android/security/keystore/recovery/WrappedApplicationKey.java145
-rw-r--r--core/java/android/util/apk/ApkSignatureVerifier.java44
-rw-r--r--core/java/android/view/Window.java27
-rw-r--r--core/java/android/view/animation/AnimationUtils.java2
-rw-r--r--core/java/android/view/animation/ClipRectAnimation.java111
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java4
-rw-r--r--core/java/com/android/internal/policy/PhoneWindow.java13
-rw-r--r--core/java/com/android/internal/widget/ILockSettings.aidl6
-rw-r--r--core/jni/android_database_SQLiteCommon.cpp4
-rw-r--r--core/res/res/anim/activity_close_enter.xml18
-rw-r--r--core/res/res/anim/activity_close_exit.xml34
-rw-r--r--core/res/res/anim/activity_open_enter.xml31
-rw-r--r--core/res/res/anim/activity_open_exit.xml19
-rw-r--r--core/res/res/anim/task_close_enter.xml68
-rw-r--r--core/res/res/anim/task_close_exit.xml51
-rw-r--r--core/res/res/anim/task_open_enter.xml64
-rw-r--r--core/res/res/anim/task_open_enter_cross_profile_apps.xml67
-rw-r--r--core/res/res/anim/task_open_exit.xml55
-rw-r--r--core/res/res/interpolator/activity_close_dim.xml22
-rw-r--r--core/res/res/values/attrs.xml14
-rw-r--r--core/res/res/values/locale_config.xml31
-rw-r--r--core/res/res/values/strings.xml2
-rw-r--r--data/etc/platform.xml2
-rw-r--r--keystore/java/android/security/KeyStore.java13
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java298
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java10
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java2
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java6
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreProvider.java5
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreSpi.java30
-rw-r--r--keystore/java/android/security/keystore/KeyGenParameterSpec.java25
-rw-r--r--keystore/java/android/security/keystore/KeyProperties.java29
-rw-r--r--keystore/java/android/security/keystore/KeyProtection.java2
-rw-r--r--keystore/java/android/security/keystore/StrongBoxUnavailableException.java28
-rw-r--r--keystore/java/android/security/keystore/WrappedKeyEntry.java56
-rw-r--r--libs/androidfw/ResourceTypes.cpp85
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h10
-rw-r--r--libs/androidfw/tests/ConfigLocale_test.cpp53
-rw-r--r--media/java/android/media/MediaDrm.java230
-rw-r--r--media/jni/android_media_MediaDrm.cpp292
-rw-r--r--packages/SettingsLib/res/drawable/btn_borderless_rect.xml31
-rw-r--r--packages/SettingsLib/res/drawable/ic_minus.xml24
-rw-r--r--packages/SettingsLib/res/drawable/ic_plus.xml24
-rw-r--r--packages/SettingsLib/res/layout/zen_mode_condition.xml84
-rw-r--r--packages/SettingsLib/res/layout/zen_mode_radio_button.xml29
-rw-r--r--packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml46
-rw-r--r--packages/SettingsLib/res/values-af/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-am/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ar/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-az/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-be/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-bs/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-cs/strings.xml4
-rw-r--r--packages/SettingsLib/res/values-da/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-el/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rCA/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-en-rXC/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-et/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-eu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fa/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-fr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-gl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-gu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-hy/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-in/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-is/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-iw/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ka/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-kk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-km/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-kn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ko/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ky/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-lo/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ml/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mn/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-mr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ms/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-my/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ne/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-nl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pa/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-si/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sq/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sv/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-sw/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ta/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-te/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-th/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-tl/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-ur/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-uz/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-vi/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zh-rHK/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/SettingsLib/res/values-zu/strings.xml2
-rw-r--r--packages/SettingsLib/res/values/dimens.xml9
-rw-r--r--packages/SettingsLib/res/values/strings.xml5
-rw-r--r--packages/SettingsLib/res/values/styles.xml6
-rw-r--r--packages/SettingsLib/src/com/android/settingslib/notification/ZenRadioLayout.java (renamed from packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java)6
-rw-r--r--packages/SystemUI/AndroidManifest.xml2
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_close_animation.xml20
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml24
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml23
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml23
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml24
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_open_animation.xml20
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml24
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml24
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml24
-rw-r--r--packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml33
-rw-r--r--packages/SystemUI/res/drawable/car_ic_arrow.xml2
-rw-r--r--packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml24
-rw-r--r--packages/SystemUI/res/layout/car_fullscreen_user_pod.xml31
-rw-r--r--packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml4
-rw-r--r--packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml2
-rw-r--r--packages/SystemUI/res/layout/car_qs_footer.xml15
-rw-r--r--packages/SystemUI/res/layout/car_qs_panel.xml33
-rw-r--r--packages/SystemUI/res/layout/zen_mode_panel.xml4
-rw-r--r--packages/SystemUI/res/values/dimens_car.xml17
-rw-r--r--packages/SystemUI/res/values/integers_car.xml1
-rw-r--r--packages/SystemUI/res/values/strings.xml9
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java5
-rw-r--r--packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java14
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java157
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java84
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java208
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java50
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java53
-rw-r--r--proto/src/metrics_constants.proto5
-rw-r--r--services/core/Android.bp1
-rw-r--r--services/core/java/com/android/server/IpSecService.java21
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java76
-rw-r--r--services/core/java/com/android/server/am/ActivityStackSupervisor.java74
-rw-r--r--services/core/java/com/android/server/am/ActivityStartController.java37
-rw-r--r--services/core/java/com/android/server/am/ActivityStarter.java80
-rw-r--r--services/core/java/com/android/server/am/AppErrors.java8
-rw-r--r--services/core/java/com/android/server/am/AppTaskImpl.java9
-rw-r--r--services/core/java/com/android/server/am/PendingIntentRecord.java35
-rw-r--r--services/core/java/com/android/server/am/SafeActivityOptions.java232
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java1
-rw-r--r--services/core/java/com/android/server/display/PersistentDataStore.java18
-rw-r--r--services/core/java/com/android/server/job/controllers/JobStatus.java8
-rw-r--r--services/core/java/com/android/server/locksettings/LockSettingsService.java32
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java6
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java10
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java8
-rw-r--r--services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java2
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyLogger.java10
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java19
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java100
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerServiceImpl.java9
-rw-r--r--services/core/java/com/android/server/om/OverlayManagerSettings.java2
-rw-r--r--services/core/java/com/android/server/pm/LauncherAppsService.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java63
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java26
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java2
-rw-r--r--services/core/java/com/android/server/pm/PackageSignatures.java264
-rw-r--r--services/core/java/com/android/server/pm/Settings.java8
-rw-r--r--services/core/java/com/android/server/timezone/RulesManagerService.java41
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java11
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java109
-rw-r--r--services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java6
-rw-r--r--services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java46
-rw-r--r--services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java5
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java55
-rw-r--r--services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java17
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java25
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java48
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java14
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java10
-rw-r--r--services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java2
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java4
-rw-r--r--services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java15
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java1
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java8
-rw-r--r--telephony/java/android/telephony/SubscriptionPlan.java1
-rw-r--r--telephony/java/android/telephony/data/DataService.java81
-rw-r--r--telephony/java/android/telephony/data/IDataService.aidl5
-rw-r--r--test-mock/src/android/test/mock/MockPackageManager.java6
-rw-r--r--tests/net/java/com/android/server/IpSecServiceParameterizedTest.java25
265 files changed, 6457 insertions, 1379 deletions
diff --git a/api/current.txt b/api/current.txt
index 812134f1a280..bef160cc977e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -6420,6 +6420,7 @@ package android.app.admin {
method public android.content.ComponentName getMandatoryBackupTransport();
method public int getMaximumFailedPasswordsForWipe(android.content.ComponentName);
method public long getMaximumTimeToLock(android.content.ComponentName);
+ method public java.util.List<java.lang.String> getMeteredDataDisabled(android.content.ComponentName);
method public int getOrganizationColor(android.content.ComponentName);
method public java.lang.CharSequence getOrganizationName(android.content.ComponentName);
method public android.app.admin.DevicePolicyManager getParentProfileInstance(android.content.ComponentName);
@@ -6524,6 +6525,7 @@ package android.app.admin {
method public void setMasterVolumeMuted(android.content.ComponentName, boolean);
method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
method public void setMaximumTimeToLock(android.content.ComponentName, long);
+ method public java.util.List<java.lang.String> setMeteredDataDisabled(android.content.ComponentName, java.util.List<java.lang.String>);
method public void setNetworkLoggingEnabled(android.content.ComponentName, boolean);
method public void setOrganizationColor(android.content.ComponentName, int);
method public void setOrganizationName(android.content.ComponentName, java.lang.CharSequence);
@@ -7100,6 +7102,7 @@ package android.app.slice {
field public static final android.os.Parcelable.Creator<android.app.slice.Slice> CREATOR;
field public static final java.lang.String EXTRA_TOGGLE_STATE = "android.app.slice.extra.TOGGLE_STATE";
field public static final java.lang.String HINT_ACTIONS = "actions";
+ field public static final java.lang.String HINT_CALLER_NEEDED = "caller_needed";
field public static final java.lang.String HINT_HORIZONTAL = "horizontal";
field public static final java.lang.String HINT_LARGE = "large";
field public static final java.lang.String HINT_LIST = "list";
@@ -7128,8 +7131,6 @@ package android.app.slice {
method public android.app.slice.Slice.Builder addAction(android.app.PendingIntent, android.app.slice.Slice, java.lang.String);
method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.lang.String...);
method public android.app.slice.Slice.Builder addBundle(android.os.Bundle, java.lang.String, java.util.List<java.lang.String>);
- method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.lang.String...);
- method public deprecated android.app.slice.Slice.Builder addColor(int, java.lang.String, java.util.List<java.lang.String>);
method public android.app.slice.Slice.Builder addHints(java.lang.String...);
method public android.app.slice.Slice.Builder addHints(java.util.List<java.lang.String>);
method public android.app.slice.Slice.Builder addIcon(android.graphics.drawable.Icon, java.lang.String, java.lang.String...);
@@ -7152,7 +7153,6 @@ package android.app.slice {
method public int describeContents();
method public android.app.PendingIntent getAction();
method public android.os.Bundle getBundle();
- method public deprecated int getColor();
method public java.lang.String getFormat();
method public java.util.List<java.lang.String> getHints();
method public android.graphics.drawable.Icon getIcon();
@@ -7167,7 +7167,6 @@ package android.app.slice {
field public static final android.os.Parcelable.Creator<android.app.slice.SliceItem> CREATOR;
field public static final java.lang.String FORMAT_ACTION = "action";
field public static final java.lang.String FORMAT_BUNDLE = "bundle";
- field public static final deprecated java.lang.String FORMAT_COLOR = "color";
field public static final java.lang.String FORMAT_IMAGE = "image";
field public static final java.lang.String FORMAT_INT = "int";
field public static final java.lang.String FORMAT_REMOTE_INPUT = "input";
@@ -7197,6 +7196,7 @@ package android.app.slice {
public abstract class SliceProvider extends android.content.ContentProvider {
ctor public SliceProvider();
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
+ method public final java.lang.String getBindingPackage();
method public final java.lang.String getType(android.net.Uri);
method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
method public android.app.slice.Slice onBindSlice(android.net.Uri, java.util.List<android.app.slice.SliceSpec>);
@@ -11533,15 +11533,15 @@ package android.content.res {
public final class AssetManager implements java.lang.AutoCloseable {
method public void close();
- method public final java.lang.String[] getLocales();
- method public final java.lang.String[] list(java.lang.String) throws java.io.IOException;
- method public final java.io.InputStream open(java.lang.String) throws java.io.IOException;
- method public final java.io.InputStream open(java.lang.String, int) throws java.io.IOException;
- method public final android.content.res.AssetFileDescriptor openFd(java.lang.String) throws java.io.IOException;
- method public final android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String) throws java.io.IOException;
- method public final android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String) throws java.io.IOException;
- method public final android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String) throws java.io.IOException;
- method public final android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String) throws java.io.IOException;
+ method public java.lang.String[] getLocales();
+ method public java.lang.String[] list(java.lang.String) throws java.io.IOException;
+ method public java.io.InputStream open(java.lang.String) throws java.io.IOException;
+ method public java.io.InputStream open(java.lang.String, int) throws java.io.IOException;
+ method public android.content.res.AssetFileDescriptor openFd(java.lang.String) throws java.io.IOException;
+ method public android.content.res.AssetFileDescriptor openNonAssetFd(java.lang.String) throws java.io.IOException;
+ method public android.content.res.AssetFileDescriptor openNonAssetFd(int, java.lang.String) throws java.io.IOException;
+ method public android.content.res.XmlResourceParser openXmlResourceParser(java.lang.String) throws java.io.IOException;
+ method public android.content.res.XmlResourceParser openXmlResourceParser(int, java.lang.String) throws java.io.IOException;
field public static final int ACCESS_BUFFER = 3; // 0x3
field public static final int ACCESS_RANDOM = 1; // 0x1
field public static final int ACCESS_STREAMING = 2; // 0x2
@@ -23137,24 +23137,29 @@ package android.media {
method public android.media.MediaDescription.Builder setTitle(java.lang.CharSequence);
}
- public final class MediaDrm {
+ public final class MediaDrm implements java.lang.AutoCloseable {
ctor public MediaDrm(java.util.UUID) throws android.media.UnsupportedSchemeException;
+ method public void close();
method public void closeSession(byte[]);
- method protected void finalize();
+ method public int getConnectedHdcpLevel();
method public android.media.MediaDrm.CryptoSession getCryptoSession(byte[], java.lang.String, java.lang.String);
method public android.media.MediaDrm.KeyRequest getKeyRequest(byte[], byte[], java.lang.String, int, java.util.HashMap<java.lang.String, java.lang.String>) throws android.media.NotProvisionedException;
+ method public int getMaxHdcpLevel();
+ method public int getMaxSessionCount();
+ method public int getOpenSessionCount();
method public byte[] getPropertyByteArray(java.lang.String);
method public java.lang.String getPropertyString(java.lang.String);
method public android.media.MediaDrm.ProvisionRequest getProvisionRequest();
method public byte[] getSecureStop(byte[]);
method public java.util.List<byte[]> getSecureStops();
+ method public int getSecurityLevel(byte[]);
method public static final boolean isCryptoSchemeSupported(java.util.UUID);
method public static final boolean isCryptoSchemeSupported(java.util.UUID, java.lang.String);
method public byte[] openSession() throws android.media.NotProvisionedException, android.media.ResourceBusyException;
method public byte[] provideKeyResponse(byte[], byte[]) throws android.media.DeniedByServerException, android.media.NotProvisionedException;
method public void provideProvisionResponse(byte[]) throws android.media.DeniedByServerException;
method public java.util.HashMap<java.lang.String, java.lang.String> queryKeyStatus(byte[]);
- method public final void release();
+ method public deprecated void release();
method public void releaseAllSecureStops();
method public void releaseSecureStops(byte[]);
method public void removeKeys(byte[]);
@@ -23164,11 +23169,22 @@ package android.media {
method public void setOnKeyStatusChangeListener(android.media.MediaDrm.OnKeyStatusChangeListener, android.os.Handler);
method public void setPropertyByteArray(java.lang.String, byte[]);
method public void setPropertyString(java.lang.String, java.lang.String);
+ method public void setSecurityLevel(byte[], int);
field public static final deprecated int EVENT_KEY_EXPIRED = 3; // 0x3
field public static final int EVENT_KEY_REQUIRED = 2; // 0x2
field public static final deprecated int EVENT_PROVISION_REQUIRED = 1; // 0x1
field public static final int EVENT_SESSION_RECLAIMED = 5; // 0x5
field public static final int EVENT_VENDOR_DEFINED = 4; // 0x4
+ field public static final int HDCP_LEVEL_UNKNOWN = 0; // 0x0
+ field public static final int HDCP_NONE = 1; // 0x1
+ field public static final int HDCP_NO_DIGITAL_OUTPUT = 2147483647; // 0x7fffffff
+ field public static final int HDCP_V1 = 2; // 0x2
+ field public static final int HDCP_V2 = 3; // 0x3
+ field public static final int HDCP_V2_1 = 4; // 0x4
+ field public static final int HDCP_V2_2 = 5; // 0x5
+ field public static final int HW_SECURE_ALL = 5; // 0x5
+ field public static final int HW_SECURE_CRYPTO = 3; // 0x3
+ field public static final int HW_SECURE_DECODE = 4; // 0x4
field public static final int KEY_TYPE_OFFLINE = 2; // 0x2
field public static final int KEY_TYPE_RELEASE = 3; // 0x3
field public static final int KEY_TYPE_STREAMING = 1; // 0x1
@@ -23177,6 +23193,9 @@ package android.media {
field public static final java.lang.String PROPERTY_DEVICE_UNIQUE_ID = "deviceUniqueId";
field public static final java.lang.String PROPERTY_VENDOR = "vendor";
field public static final java.lang.String PROPERTY_VERSION = "version";
+ field public static final int SECURITY_LEVEL_UNKNOWN = 0; // 0x0
+ field public static final int SW_SECURE_CRYPTO = 1; // 0x1
+ field public static final int SW_SECURE_DECODE = 2; // 0x2
}
public final class MediaDrm.CryptoSession {
@@ -23186,6 +23205,9 @@ package android.media {
method public boolean verify(byte[], byte[], byte[]);
}
+ public static abstract class MediaDrm.HdcpLevel implements java.lang.annotation.Annotation {
+ }
+
public static final class MediaDrm.KeyRequest {
method public byte[] getData();
method public java.lang.String getDefaultUrl();
@@ -23226,6 +23248,9 @@ package android.media {
method public java.lang.String getDefaultUrl();
}
+ public static abstract class MediaDrm.SecurityLevel implements java.lang.annotation.Annotation {
+ }
+
public class MediaDrmException extends java.lang.Exception {
ctor public MediaDrmException(java.lang.String);
}
@@ -35838,7 +35863,6 @@ package android.provider {
field public static final java.lang.String ACTION_BLUETOOTH_SETTINGS = "android.settings.BLUETOOTH_SETTINGS";
field public static final java.lang.String ACTION_CAPTIONING_SETTINGS = "android.settings.CAPTIONING_SETTINGS";
field public static final java.lang.String ACTION_CAST_SETTINGS = "android.settings.CAST_SETTINGS";
- field public static final java.lang.String ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_GROUP_NOTIFICATION_SETTINGS";
field public static final java.lang.String ACTION_CHANNEL_NOTIFICATION_SETTINGS = "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
field public static final java.lang.String ACTION_DATA_ROAMING_SETTINGS = "android.settings.DATA_ROAMING_SETTINGS";
field public static final java.lang.String ACTION_DATE_SETTINGS = "android.settings.DATE_SETTINGS";
@@ -35899,7 +35923,6 @@ package android.provider {
field public static final java.lang.String EXTRA_APP_PACKAGE = "android.provider.extra.APP_PACKAGE";
field public static final java.lang.String EXTRA_AUTHORITIES = "authorities";
field public static final java.lang.String EXTRA_BATTERY_SAVER_MODE_ENABLED = "android.settings.extra.battery_saver_mode_enabled";
- field public static final java.lang.String EXTRA_CHANNEL_GROUP_ID = "android.provider.extra.CHANNEL_GROUP_ID";
field public static final java.lang.String EXTRA_CHANNEL_ID = "android.provider.extra.CHANNEL_ID";
field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_ENABLED = "android.settings.extra.do_not_disturb_mode_enabled";
field public static final java.lang.String EXTRA_DO_NOT_DISTURB_MODE_MINUTES = "android.settings.extra.do_not_disturb_mode_minutes";
@@ -37833,6 +37856,7 @@ package android.security.keystore {
method public boolean isDigestsSpecified();
method public boolean isInvalidatedByBiometricEnrollment();
method public boolean isRandomizedEncryptionRequired();
+ method public boolean isStrongBoxBacked();
method public boolean isUserAuthenticationRequired();
method public boolean isUserAuthenticationValidWhileOnBody();
}
@@ -37850,6 +37874,7 @@ package android.security.keystore {
method public android.security.keystore.KeyGenParameterSpec.Builder setDigests(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setEncryptionPaddings(java.lang.String...);
method public android.security.keystore.KeyGenParameterSpec.Builder setInvalidatedByBiometricEnrollment(boolean);
+ method public android.security.keystore.KeyGenParameterSpec.Builder setIsStrongBoxBacked(boolean);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeySize(int);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityEnd(java.util.Date);
method public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
@@ -37910,6 +37935,7 @@ package android.security.keystore {
field public static final java.lang.String ENCRYPTION_PADDING_PKCS7 = "PKCS7Padding";
field public static final java.lang.String ENCRYPTION_PADDING_RSA_OAEP = "OAEPPadding";
field public static final java.lang.String ENCRYPTION_PADDING_RSA_PKCS1 = "PKCS1Padding";
+ field public static final deprecated java.lang.String KEY_ALGORITHM_3DES = "DESede";
field public static final java.lang.String KEY_ALGORITHM_AES = "AES";
field public static final java.lang.String KEY_ALGORITHM_EC = "EC";
field public static final java.lang.String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1";
@@ -37920,11 +37946,13 @@ package android.security.keystore {
field public static final java.lang.String KEY_ALGORITHM_RSA = "RSA";
field public static final int ORIGIN_GENERATED = 1; // 0x1
field public static final int ORIGIN_IMPORTED = 2; // 0x2
+ field public static final int ORIGIN_SECURELY_IMPORTED = 8; // 0x8
field public static final int ORIGIN_UNKNOWN = 4; // 0x4
field public static final int PURPOSE_DECRYPT = 2; // 0x2
field public static final int PURPOSE_ENCRYPT = 1; // 0x1
field public static final int PURPOSE_SIGN = 4; // 0x4
field public static final int PURPOSE_VERIFY = 8; // 0x8
+ field public static final int PURPOSE_WRAP_KEY = 32; // 0x20
field public static final java.lang.String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
field public static final java.lang.String SIGNATURE_PADDING_RSA_PSS = "PSS";
}
@@ -37964,12 +37992,24 @@ package android.security.keystore {
method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
}
+ public class StrongBoxUnavailableException extends java.security.ProviderException {
+ ctor public StrongBoxUnavailableException();
+ }
+
public class UserNotAuthenticatedException extends java.security.InvalidKeyException {
ctor public UserNotAuthenticatedException();
ctor public UserNotAuthenticatedException(java.lang.String);
ctor public UserNotAuthenticatedException(java.lang.String, java.lang.Throwable);
}
+ public class WrappedKeyEntry implements java.security.KeyStore.Entry {
+ ctor public WrappedKeyEntry(byte[], java.lang.String, java.lang.String, java.security.spec.AlgorithmParameterSpec);
+ method public java.security.spec.AlgorithmParameterSpec getAlgorithmParameterSpec();
+ method public java.lang.String getTransformation();
+ method public byte[] getWrappedKeyBytes();
+ method public java.lang.String getWrappingKeyAlias();
+ }
+
}
package android.service.autofill {
@@ -40861,6 +40901,7 @@ package android.telephony {
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_EXTRA_VAL_STRING = "ci_action_on_sys_update_extra_val_string";
field public static final java.lang.String KEY_CI_ACTION_ON_SYS_UPDATE_INTENT_STRING = "ci_action_on_sys_update_intent_string";
field public static final java.lang.String KEY_CONFIG_IMS_PACKAGE_OVERRIDE_STRING = "config_ims_package_override_string";
+ field public static final java.lang.String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING = "config_plans_package_override_string";
field public static final java.lang.String KEY_CONFIG_TELEPHONY_USE_OWN_NUMBER_FOR_VOICEMAIL_BOOL = "config_telephony_use_own_number_for_voicemail_bool";
field public static final java.lang.String KEY_CSP_ENABLED_BOOL = "csp_enabled_bool";
field public static final java.lang.String KEY_DATA_LIMIT_THRESHOLD_BYTES_LONG = "data_limit_threshold_bytes_long";
@@ -41554,10 +41595,16 @@ package android.telephony {
method public static int getDefaultSmsSubscriptionId();
method public static int getDefaultSubscriptionId();
method public static int getDefaultVoiceSubscriptionId();
+ method public java.util.List<android.telephony.SubscriptionPlan> getSubscriptionPlans(int);
method public boolean isNetworkRoaming(int);
method public void removeOnSubscriptionsChangedListener(android.telephony.SubscriptionManager.OnSubscriptionsChangedListener);
+ method public void setSubscriptionOverrideCongested(int, boolean, long);
+ method public void setSubscriptionOverrideUnmetered(int, boolean, long);
+ method public void setSubscriptionPlans(int, java.util.List<android.telephony.SubscriptionPlan>);
field public static final java.lang.String ACTION_DEFAULT_SMS_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SMS_SUBSCRIPTION_CHANGED";
field public static final java.lang.String ACTION_DEFAULT_SUBSCRIPTION_CHANGED = "android.telephony.action.DEFAULT_SUBSCRIPTION_CHANGED";
+ field public static final java.lang.String ACTION_MANAGE_SUBSCRIPTION_PLANS = "android.telephony.action.MANAGE_SUBSCRIPTION_PLANS";
+ field public static final java.lang.String ACTION_REFRESH_SUBSCRIPTION_PLANS = "android.telephony.action.REFRESH_SUBSCRIPTION_PLANS";
field public static final int DATA_ROAMING_DISABLE = 0; // 0x0
field public static final int DATA_ROAMING_ENABLE = 1; // 0x1
field public static final java.lang.String EXTRA_SUBSCRIPTION_INDEX = "android.telephony.extra.SUBSCRIPTION_INDEX";
@@ -41569,6 +41616,38 @@ package android.telephony {
method public void onSubscriptionsChanged();
}
+ public final class SubscriptionPlan implements android.os.Parcelable {
+ method public java.util.Iterator<android.util.Pair<java.time.ZonedDateTime, java.time.ZonedDateTime>> cycleIterator();
+ method public int describeContents();
+ method public int getDataLimitBehavior();
+ method public long getDataLimitBytes();
+ method public long getDataUsageBytes();
+ method public long getDataUsageTime();
+ method public java.lang.CharSequence getSummary();
+ method public java.lang.CharSequence getTitle();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final long BYTES_UNKNOWN = -1L; // 0xffffffffffffffffL
+ field public static final long BYTES_UNLIMITED = 9223372036854775807L; // 0x7fffffffffffffffL
+ field public static final android.os.Parcelable.Creator<android.telephony.SubscriptionPlan> CREATOR;
+ field public static final int LIMIT_BEHAVIOR_BILLED = 1; // 0x1
+ field public static final int LIMIT_BEHAVIOR_DISABLED = 0; // 0x0
+ field public static final int LIMIT_BEHAVIOR_THROTTLED = 2; // 0x2
+ field public static final int LIMIT_BEHAVIOR_UNKNOWN = -1; // 0xffffffff
+ field public static final long TIME_UNKNOWN = -1L; // 0xffffffffffffffffL
+ }
+
+ public static class SubscriptionPlan.Builder {
+ method public android.telephony.SubscriptionPlan build();
+ method public static android.telephony.SubscriptionPlan.Builder createNonrecurring(java.time.ZonedDateTime, java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringDaily(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringMonthly(java.time.ZonedDateTime);
+ method public static android.telephony.SubscriptionPlan.Builder createRecurringWeekly(java.time.ZonedDateTime);
+ method public android.telephony.SubscriptionPlan.Builder setDataLimit(long, int);
+ method public android.telephony.SubscriptionPlan.Builder setDataUsage(long, long);
+ method public android.telephony.SubscriptionPlan.Builder setSummary(java.lang.CharSequence);
+ method public android.telephony.SubscriptionPlan.Builder setTitle(java.lang.CharSequence);
+ }
+
public class TelephonyManager {
method public boolean canChangeDtmfToneLength();
method public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
@@ -47832,6 +47911,7 @@ package android.view {
method protected final int getLocalFeatures();
method public android.media.session.MediaController getMediaController();
method public abstract int getNavigationBarColor();
+ method public int getNavigationBarDividerColor();
method public android.transition.Transition getReenterTransition();
method public android.transition.Transition getReturnTransition();
method public android.transition.Transition getSharedElementEnterTransition();
@@ -47900,6 +47980,7 @@ package android.view {
method public void setLogo(int);
method public void setMediaController(android.media.session.MediaController);
method public abstract void setNavigationBarColor(int);
+ method public void setNavigationBarDividerColor(int);
method public void setReenterTransition(android.transition.Transition);
method public abstract void setResizingCaptionDrawable(android.graphics.drawable.Drawable);
method public final void setRestrictedCaptionAreaListener(android.view.Window.OnRestrictedCaptionAreaChangedListener);
diff --git a/api/system-current.txt b/api/system-current.txt
index 97f82e99fe6e..bfe44c9198a4 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4605,18 +4605,21 @@ package android.telephony.data {
method public abstract android.telephony.data.DataService.DataServiceProvider createDataServiceProvider(int);
field public static final java.lang.String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
field public static final java.lang.String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
+ field public static final int REQUEST_REASON_HANDOVER = 3; // 0x3
+ field public static final int REQUEST_REASON_NORMAL = 1; // 0x1
+ field public static final int REQUEST_REASON_SHUTDOWN = 2; // 0x2
}
public class DataService.DataServiceProvider {
ctor public DataService.DataServiceProvider(int);
- method public void deactivateDataCall(int, boolean, boolean, android.telephony.data.DataServiceCallback);
+ method public void deactivateDataCall(int, int, android.telephony.data.DataServiceCallback);
method public void getDataCallList(android.telephony.data.DataServiceCallback);
method public final int getSlotId();
method public final void notifyDataCallListChanged(java.util.List<android.telephony.data.DataCallResponse>);
method protected void onDestroy();
method public void setDataProfile(java.util.List<android.telephony.data.DataProfile>, boolean, android.telephony.data.DataServiceCallback);
method public void setInitialAttachApn(android.telephony.data.DataProfile, boolean, android.telephony.data.DataServiceCallback);
- method public void setupDataCall(int, android.telephony.data.DataProfile, boolean, boolean, boolean, android.net.LinkProperties, android.telephony.data.DataServiceCallback);
+ method public void setupDataCall(int, android.telephony.data.DataProfile, boolean, boolean, int, android.net.LinkProperties, android.telephony.data.DataServiceCallback);
}
public class DataServiceCallback {
diff --git a/cmds/incidentd/Android.mk b/cmds/incidentd/Android.mk
index 368a70bc3898..2b00d9e6a596 100644
--- a/cmds/incidentd/Android.mk
+++ b/cmds/incidentd/Android.mk
@@ -91,9 +91,7 @@ GEN_PROTO:=
gen_src_dir:=
-ifeq ($(BUILD_WITH_INCIDENTD_RC), true)
LOCAL_INIT_RC := incidentd.rc
-endif
include $(BUILD_EXECUTABLE)
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index 7a9588d1a2c4..7f0ebb45e2d7 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -86,6 +86,7 @@ message Atom {
AppStartFullyDrawnChanged app_start_fully_drawn_changed = 50;
LmkEventOccurred lmk_event_occurred = 51;
PictureInPictureStateChanged picture_in_picture_state_changed = 52;
+ WifiMulticastLockStateChanged wifi_multicast_lock_state_changed = 53;
// TODO: Reorder the numbering so that the most frequent occur events occur in the first 15.
}
@@ -707,6 +708,22 @@ message WifiScanStateChanged {
}
/**
+ * Logs wifi multicast locks held by an app
+ *
+ * Logged from:
+ * frameworks/base/core/java/com/android/internal/os/BatteryStatsImpl.java
+ */
+message WifiMulticastLockStateChanged {
+ repeated AttributionNode attribution_node = 1;
+
+ enum State {
+ OFF = 0;
+ ON = 1;
+ }
+ optional State state = 2;
+}
+
+/**
* Logs phone signal strength changes.
*
* Logged from:
@@ -1322,4 +1339,4 @@ message SystemUptime {
// for external input).
// It is not affected by clock scaling, idle, or other power saving mechanisms.
optional uint64 uptime_ms = 1;
-} \ No newline at end of file
+}
diff --git a/cmds/statsd/src/stats_log.proto b/cmds/statsd/src/stats_log.proto
index bb2193fb442b..f73c4a5303cf 100644
--- a/cmds/statsd/src/stats_log.proto
+++ b/cmds/statsd/src/stats_log.proto
@@ -188,78 +188,78 @@ message ConfigMetricsReportList {
}
message StatsdStatsReport {
- optional int32 stats_begin_time_sec = 1;
+ optional int32 stats_begin_time_sec = 1;
- optional int32 stats_end_time_sec = 2;
+ optional int32 stats_end_time_sec = 2;
- message MatcherStats {
- optional int64 id = 1;
- optional int32 matched_times = 2;
- }
+ message MatcherStats {
+ optional int64 id = 1;
+ optional int32 matched_times = 2;
+ }
- message ConditionStats {
- optional int64 id = 1;
- optional int32 max_tuple_counts = 2;
- }
+ message ConditionStats {
+ optional int64 id = 1;
+ optional int32 max_tuple_counts = 2;
+ }
- message MetricStats {
- optional int64 id = 1;
- optional int32 max_tuple_counts = 2;
- }
+ message MetricStats {
+ optional int64 id = 1;
+ optional int32 max_tuple_counts = 2;
+ }
- message AlertStats {
- optional int64 id = 1;
- optional int32 alerted_times = 2;
- }
+ message AlertStats {
+ optional int64 id = 1;
+ optional int32 alerted_times = 2;
+ }
- message ConfigStats {
- optional int32 uid = 1;
- optional int64 id = 2;
- optional int32 creation_time_sec = 3;
- optional int32 deletion_time_sec = 4;
- optional int32 metric_count = 5;
- optional int32 condition_count = 6;
- optional int32 matcher_count = 7;
- optional int32 alert_count = 8;
- optional bool is_valid = 9;
-
- repeated int32 broadcast_sent_time_sec = 10;
- repeated int32 data_drop_time_sec = 11;
- repeated int32 dump_report_time_sec = 12;
- repeated MatcherStats matcher_stats = 13;
- repeated ConditionStats condition_stats = 14;
- repeated MetricStats metric_stats = 15;
- repeated AlertStats alert_stats = 16;
- }
+ message ConfigStats {
+ optional int32 uid = 1;
+ optional int64 id = 2;
+ optional int32 creation_time_sec = 3;
+ optional int32 deletion_time_sec = 4;
+ optional int32 metric_count = 5;
+ optional int32 condition_count = 6;
+ optional int32 matcher_count = 7;
+ optional int32 alert_count = 8;
+ optional bool is_valid = 9;
+
+ repeated int32 broadcast_sent_time_sec = 10;
+ repeated int32 data_drop_time_sec = 11;
+ repeated int32 dump_report_time_sec = 12;
+ repeated MatcherStats matcher_stats = 13;
+ repeated ConditionStats condition_stats = 14;
+ repeated MetricStats metric_stats = 15;
+ repeated AlertStats alert_stats = 16;
+ }
- repeated ConfigStats config_stats = 3;
+ repeated ConfigStats config_stats = 3;
- message AtomStats {
- optional int32 tag = 1;
- optional int32 count = 2;
- }
+ message AtomStats {
+ optional int32 tag = 1;
+ optional int32 count = 2;
+ }
- repeated AtomStats atom_stats = 7;
+ repeated AtomStats atom_stats = 7;
- message UidMapStats {
- optional int32 snapshots = 1;
- optional int32 changes = 2;
- optional int32 bytes_used = 3;
- optional int32 dropped_snapshots = 4;
- optional int32 dropped_changes = 5;
- }
- optional UidMapStats uidmap_stats = 8;
+ message UidMapStats {
+ optional int32 snapshots = 1;
+ optional int32 changes = 2;
+ optional int32 bytes_used = 3;
+ optional int32 dropped_snapshots = 4;
+ optional int32 dropped_changes = 5;
+ }
+ optional UidMapStats uidmap_stats = 8;
- message AnomalyAlarmStats {
- optional int32 alarms_registered = 1;
- }
- optional AnomalyAlarmStats anomaly_alarm_stats = 9;
+ message AnomalyAlarmStats {
+ optional int32 alarms_registered = 1;
+ }
+ optional AnomalyAlarmStats anomaly_alarm_stats = 9;
- message PulledAtomStats {
- optional int32 atom_id = 1;
- optional int64 total_pull = 2;
- optional int64 total_pull_from_cache = 3;
- optional int64 min_pull_interval_sec = 4;
- }
- repeated PulledAtomStats pulled_atom_stats = 10;
+ message PulledAtomStats {
+ optional int32 atom_id = 1;
+ optional int64 total_pull = 2;
+ optional int64 total_pull_from_cache = 3;
+ optional int64 min_pull_interval_sec = 4;
+ }
+ repeated PulledAtomStats pulled_atom_stats = 10;
} \ No newline at end of file
diff --git a/cmds/statsd/src/statsd_config.proto b/cmds/statsd/src/statsd_config.proto
index cd60ee74e3ad..07bbcb2190e8 100644
--- a/cmds/statsd/src/statsd_config.proto
+++ b/cmds/statsd/src/statsd_config.proto
@@ -25,300 +25,303 @@ option java_outer_classname = "StatsdConfigProto";
import "frameworks/base/cmds/statsd/src/perfetto/perfetto_config.proto";
enum Position {
- POSITION_UNKNOWN = 0;
- FIRST = 1;
- LAST = 2;
- ANY = 3;
+ POSITION_UNKNOWN = 0;
+
+ FIRST = 1;
+
+ LAST = 2;
+
+ ANY = 3;
}
enum TimeUnit {
- TIME_UNIT_UNSPECIFIED = 0;
- ONE_MINUTE = 1;
- FIVE_MINUTES = 2;
- TEN_MINUTES = 3;
- THIRTY_MINUTES = 4;
- ONE_HOUR = 5;
- THREE_HOURS = 6;
- SIX_HOURS = 7;
- TWELVE_HOURS = 8;
- ONE_DAY = 9;
- CTS = 1000;
+ TIME_UNIT_UNSPECIFIED = 0;
+ ONE_MINUTE = 1;
+ FIVE_MINUTES = 2;
+ TEN_MINUTES = 3;
+ THIRTY_MINUTES = 4;
+ ONE_HOUR = 5;
+ THREE_HOURS = 6;
+ SIX_HOURS = 7;
+ TWELVE_HOURS = 8;
+ ONE_DAY = 9;
+ CTS = 1000;
}
message FieldMatcher {
- optional int32 field = 1;
+ optional int32 field = 1;
- optional Position position = 2;
+ optional Position position = 2;
- repeated FieldMatcher child = 3;
+ repeated FieldMatcher child = 3;
}
message FieldValueMatcher {
- // Field id, as specified in the atom proto message.
- optional int32 field = 1;
-
- // For repeated fields, specifies the position in the array.
- // FIRST and LAST mean that if the values are found at the first
- // or last position, it's a match. ANY means that if the values are found
- // anywhere in the array, then it's a match.
- optional Position position = 2;
-
- oneof value_matcher {
- bool eq_bool = 3;
- string eq_string = 4;
- int32 eq_int = 5;
-
- int64 lt_int = 6;
- int64 gt_int = 7;
- float lt_float = 8;
- float gt_float = 9;
-
- int64 lte_int = 10;
- int64 gte_int = 11;
-
- MessageMatcher matches_tuple = 12;
- }
+ optional int32 field = 1;
+
+ optional Position position = 2;
+
+ oneof value_matcher {
+ bool eq_bool = 3;
+ string eq_string = 4;
+ int32 eq_int = 5;
+
+ int64 lt_int = 6;
+ int64 gt_int = 7;
+ float lt_float = 8;
+ float gt_float = 9;
+
+ int64 lte_int = 10;
+ int64 gte_int = 11;
+
+ MessageMatcher matches_tuple = 12;
+ }
}
message MessageMatcher {
- repeated FieldValueMatcher field_value_matcher = 1;
+ repeated FieldValueMatcher field_value_matcher = 1;
}
enum LogicalOperation {
- LOGICAL_OPERATION_UNSPECIFIED = 0;
- AND = 1;
- OR = 2;
- NOT = 3;
- NAND = 4;
- NOR = 5;
+ LOGICAL_OPERATION_UNSPECIFIED = 0;
+ AND = 1;
+ OR = 2;
+ NOT = 3;
+ NAND = 4;
+ NOR = 5;
}
message SimpleAtomMatcher {
- optional int32 atom_id = 1;
+ optional int32 atom_id = 1;
- repeated FieldValueMatcher field_value_matcher = 2;
+ repeated FieldValueMatcher field_value_matcher = 2;
}
message AtomMatcher {
- optional int64 id = 1;
+ optional int64 id = 1;
- message Combination {
- optional LogicalOperation operation = 1;
+ message Combination {
+ optional LogicalOperation operation = 1;
- repeated int64 matcher = 2;
- }
- oneof contents {
- SimpleAtomMatcher simple_atom_matcher = 2;
- Combination combination = 3;
- }
+ repeated int64 matcher = 2;
+ }
+ oneof contents {
+ SimpleAtomMatcher simple_atom_matcher = 2;
+ Combination combination = 3;
+ }
}
message SimplePredicate {
- optional int64 start = 1;
+ optional int64 start = 1;
- optional int64 stop = 2;
+ optional int64 stop = 2;
- optional bool count_nesting = 3 [default = true];
+ optional bool count_nesting = 3 [default = true];
- optional int64 stop_all = 4;
+ optional int64 stop_all = 4;
- enum InitialValue {
- UNKNOWN = 0;
- FALSE = 1;
- }
- optional InitialValue initial_value = 5 [default = FALSE];
+ enum InitialValue {
+ UNKNOWN = 0;
+ FALSE = 1;
+ }
+ optional InitialValue initial_value = 5 [default = FALSE];
- optional FieldMatcher dimensions = 6;
+ optional FieldMatcher dimensions = 6;
}
message Predicate {
- optional int64 id = 1;
+ optional int64 id = 1;
- message Combination {
- optional LogicalOperation operation = 1;
+ message Combination {
+ optional LogicalOperation operation = 1;
- repeated int64 predicate = 2;
- }
+ repeated int64 predicate = 2;
+ }
- oneof contents {
- SimplePredicate simple_predicate = 2;
- Combination combination = 3;
- }
-}
-
-message Bucket {
- optional int64 bucket_size_millis = 1;
+ oneof contents {
+ SimplePredicate simple_predicate = 2;
+ Combination combination = 3;
+ }
}
message MetricConditionLink {
- optional int64 condition = 1;
+ optional int64 condition = 1;
- optional FieldMatcher fields_in_what = 2;
+ optional FieldMatcher fields_in_what = 2;
- optional FieldMatcher fields_in_condition = 3;
+ optional FieldMatcher fields_in_condition = 3;
}
message FieldFilter {
- optional bool include_all = 1 [default = false];
- optional FieldMatcher fields = 2;
+ optional bool include_all = 1 [default = false];
+ optional FieldMatcher fields = 2;
}
message EventMetric {
- optional int64 id = 1;
+ optional int64 id = 1;
- optional int64 what = 2;
+ optional int64 what = 2;
- optional int64 condition = 3;
+ optional int64 condition = 3;
- repeated MetricConditionLink links = 4;
+ repeated MetricConditionLink links = 4;
}
message CountMetric {
- optional int64 id = 1;
+ optional int64 id = 1;
- optional int64 what = 2;
+ optional int64 what = 2;
- optional int64 condition = 3;
+ optional int64 condition = 3;
- optional FieldMatcher dimensions_in_what = 4;
+ optional FieldMatcher dimensions_in_what = 4;
- optional FieldMatcher dimensions_in_condition = 7;
+ optional FieldMatcher dimensions_in_condition = 7;
- optional TimeUnit bucket = 5;
+ optional TimeUnit bucket = 5;
- repeated MetricConditionLink links = 6;
+ repeated MetricConditionLink links = 6;
}
message DurationMetric {
- optional int64 id = 1;
+ optional int64 id = 1;
- optional int64 what = 2;
+ optional int64 what = 2;
- optional int64 condition = 3;
+ optional int64 condition = 3;
- repeated MetricConditionLink links = 4;
+ repeated MetricConditionLink links = 4;
- enum AggregationType {
- SUM = 1;
+ enum AggregationType {
+ SUM = 1;
- MAX_SPARSE = 2;
- }
- optional AggregationType aggregation_type = 5 [default = SUM];
+ MAX_SPARSE = 2;
+ }
+ optional AggregationType aggregation_type = 5 [default = SUM];
- optional FieldMatcher dimensions_in_what = 6;
+ optional FieldMatcher dimensions_in_what = 6;
- optional FieldMatcher dimensions_in_condition = 8;
+ optional FieldMatcher dimensions_in_condition = 8;
- optional TimeUnit bucket = 7;
+ optional TimeUnit bucket = 7;
}
message GaugeMetric {
- optional int64 id = 1;
+ optional int64 id = 1;
- optional int64 what = 2;
+ optional int64 what = 2;
- optional FieldFilter gauge_fields_filter = 3;
+ optional FieldFilter gauge_fields_filter = 3;
- optional int64 condition = 4;
+ optional int64 condition = 4;
- optional FieldMatcher dimensions_in_what = 5;
+ optional FieldMatcher dimensions_in_what = 5;
- optional FieldMatcher dimensions_in_condition = 8;
+ optional FieldMatcher dimensions_in_condition = 8;
- optional TimeUnit bucket = 6;
+ optional TimeUnit bucket = 6;
- repeated MetricConditionLink links = 7;
+ repeated MetricConditionLink links = 7;
}
message ValueMetric {
- optional int64 id = 1;
+ optional int64 id = 1;
- optional int64 what = 2;
+ optional int64 what = 2;
- optional FieldMatcher value_field = 3;
+ optional FieldMatcher value_field = 3;
- optional int64 condition = 4;
+ optional int64 condition = 4;
- optional FieldMatcher dimensions_in_what = 5;
+ optional FieldMatcher dimensions_in_what = 5;
- optional FieldMatcher dimensions_in_condition = 9;
+ optional FieldMatcher dimensions_in_condition = 9;
- optional TimeUnit bucket = 6;
+ optional TimeUnit bucket = 6;
- repeated MetricConditionLink links = 7;
+ repeated MetricConditionLink links = 7;
- enum AggregationType { SUM = 1; }
- optional AggregationType aggregation_type = 8 [default = SUM];
+ enum AggregationType {
+ SUM = 1;
+ }
+ optional AggregationType aggregation_type = 8 [default = SUM];
}
message Alert {
- optional int64 id = 1;
+ optional int64 id = 1;
- optional int64 metric_id = 2;
+ optional int64 metric_id = 2;
- optional int32 num_buckets = 3;
+ optional int32 num_buckets = 3;
- optional int32 refractory_period_secs = 4;
+ optional int32 refractory_period_secs = 4;
- optional double trigger_if_sum_gt = 5;
+ optional double trigger_if_sum_gt = 5;
}
message Alarm {
- optional int64 id = 1;
- optional int64 offset_millis = 2;
- optional int64 period_millis = 3;
+ optional int64 id = 1;
+
+ optional int64 offset_millis = 2;
+
+ optional int64 period_millis = 3;
}
message IncidentdDetails {
- repeated int32 section = 1;
+ repeated int32 section = 1;
}
message PerfettoDetails {
- optional perfetto.protos.TraceConfig trace_config = 1;
+ optional perfetto.protos.TraceConfig trace_config = 1;
}
-message Subscription {
- optional int64 id = 1;
-
- enum RuleType {
- RULE_TYPE_UNSPECIFIED = 0;
- ALARM = 1;
- ALERT = 2;
- }
- optional RuleType rule_type = 2;
-
- optional int64 rule_id = 3;
+message BroadcastSubscriberDetails {
+ optional int64 subscriber_id = 1;
+}
- oneof subscriber_information {
- IncidentdDetails incidentd_details = 4;
- PerfettoDetails perfetto_details = 5;
- }
+message Subscription {
+ optional int64 id = 1;
+
+ enum RuleType {
+ RULE_TYPE_UNSPECIFIED = 0;
+ ALARM = 1;
+ ALERT = 2;
+ }
+ optional RuleType rule_type = 2;
+
+ optional int64 rule_id = 3;
+
+ oneof subscriber_information {
+ IncidentdDetails incidentd_details = 4;
+ PerfettoDetails perfetto_details = 5;
+ BroadcastSubscriberDetails broadcast_subscriber_details = 6;
+ }
}
message StatsdConfig {
- optional int64 id = 1;
+ optional int64 id = 1;
- repeated EventMetric event_metric = 2;
+ repeated EventMetric event_metric = 2;
- repeated CountMetric count_metric = 3;
+ repeated CountMetric count_metric = 3;
- repeated ValueMetric value_metric = 4;
+ repeated ValueMetric value_metric = 4;
- repeated GaugeMetric gauge_metric = 5;
+ repeated GaugeMetric gauge_metric = 5;
- repeated DurationMetric duration_metric = 6;
+ repeated DurationMetric duration_metric = 6;
- repeated AtomMatcher atom_matcher = 7;
+ repeated AtomMatcher atom_matcher = 7;
- repeated Predicate predicate = 8;
+ repeated Predicate predicate = 8;
- repeated Alert alert = 9;
+ repeated Alert alert = 9;
- repeated Alarm alarm = 10;
+ repeated Alarm alarm = 10;
- repeated Subscription subscription = 11;
+ repeated Subscription subscription = 11;
- repeated string allowed_log_source = 12;
+ repeated string allowed_log_source = 12;
- repeated int64 no_report_metric = 13;
+ repeated int64 no_report_metric = 13;
}
diff --git a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java
index 843b1e5f90ac..2e0161be8096 100644
--- a/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java
+++ b/cmds/statsd/tools/loadtest/src/com/android/statsd/loadtest/ConfigFactory.java
@@ -19,7 +19,6 @@ import android.content.Context;
import android.content.res.Resources;
import android.util.Log;
-import com.android.internal.os.StatsdConfigProto.Bucket;
import com.android.internal.os.StatsdConfigProto.Predicate;
import com.android.internal.os.StatsdConfigProto.CountMetric;
import com.android.internal.os.StatsdConfigProto.DurationMetric;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 4048e6596cfc..49d522440fc4 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -222,9 +222,18 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public Intent getLeanbackLaunchIntentForPackage(String packageName) {
- // Try to find a main leanback_launcher activity.
+ return getLaunchIntentForPackageAndCategory(packageName, Intent.CATEGORY_LEANBACK_LAUNCHER);
+ }
+
+ @Override
+ public Intent getCarLaunchIntentForPackage(String packageName) {
+ return getLaunchIntentForPackageAndCategory(packageName, Intent.CATEGORY_CAR_LAUNCHER);
+ }
+
+ private Intent getLaunchIntentForPackageAndCategory(String packageName, String category) {
+ // Try to find a main launcher activity for the given categories.
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
- intentToResolve.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
+ intentToResolve.addCategory(category);
intentToResolve.setPackage(packageName);
List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
diff --git a/core/java/android/app/PendingIntent.java b/core/java/android/app/PendingIntent.java
index 8b76cc7c966b..d6429ae9e540 100644
--- a/core/java/android/app/PendingIntent.java
+++ b/core/java/android/app/PendingIntent.java
@@ -867,19 +867,30 @@ public final class PendingIntent implements Parcelable {
@Nullable OnFinished onFinished, @Nullable Handler handler,
@Nullable String requiredPermission, @Nullable Bundle options)
throws CanceledException {
+ if (sendAndReturnResult(context, code, intent, onFinished, handler, requiredPermission,
+ options) < 0) {
+ throw new CanceledException();
+ }
+ }
+
+ /**
+ * Like {@link #send}, but returns the result
+ * @hide
+ */
+ public int sendAndReturnResult(Context context, int code, @Nullable Intent intent,
+ @Nullable OnFinished onFinished, @Nullable Handler handler,
+ @Nullable String requiredPermission, @Nullable Bundle options)
+ throws CanceledException {
try {
String resolvedType = intent != null ?
intent.resolveTypeIfNeeded(context.getContentResolver())
: null;
- int res = ActivityManager.getService().sendIntentSender(
+ return ActivityManager.getService().sendIntentSender(
mTarget, mWhitelistToken, code, intent, resolvedType,
onFinished != null
? new FinishedDispatcher(this, onFinished, handler)
: null,
requiredPermission, options);
- if (res < 0) {
- throw new CanceledException();
- }
} catch (RemoteException e) {
throw new CanceledException(e);
}
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 7fccda8c04e3..bad19e3bbb97 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -8228,6 +8228,47 @@ public class DevicePolicyManager {
}
/**
+ * Called by a device or profile owner to restrict packages from accessing metered data.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @param packageNames the list of package names to be restricted.
+ * @return a list of package names which could not be restricted.
+ * @throws SecurityException if {@code admin} is not a device or profile owner.
+ */
+ public @NonNull List<String> setMeteredDataDisabled(@NonNull ComponentName admin,
+ @NonNull List<String> packageNames) {
+ throwIfParentInstance("setMeteredDataDisabled");
+ if (mService != null) {
+ try {
+ return mService.setMeteredDataDisabled(admin, packageNames);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return packageNames;
+ }
+
+ /**
+ * Called by a device or profile owner to retrieve the list of packages which are restricted
+ * by the admin from accessing metered data.
+ *
+ * @param admin which {@link DeviceAdminReceiver} this request is associated with.
+ * @return the list of restricted package names.
+ * @throws SecurityException if {@code admin} is not a device or profile owner.
+ */
+ public @NonNull List<String> getMeteredDataDisabled(@NonNull ComponentName admin) {
+ throwIfParentInstance("getMeteredDataDisabled");
+ if (mService != null) {
+ try {
+ return mService.getMeteredDataDisabled(admin);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+ return new ArrayList<>();
+ }
+
+ /**
* Called by device owners to retrieve device logs from before the device's last reboot.
* <p>
* <strong> This API is not supported on all devices. Calling this API on unsupported devices
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index d2a2be7bbcb5..514dca92c816 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -400,4 +400,7 @@ interface IDevicePolicyManager {
void setPrintingEnabled(in ComponentName admin, boolean enabled);
boolean isPrintingEnabled();
CharSequence getPrintingDisabledReason();
+
+ List<String> setMeteredDataDisabled(in ComponentName admin, in List<String> packageNames);
+ List<String> getMeteredDataDisabled(in ComponentName admin);
}
diff --git a/core/java/android/app/slice/Slice.java b/core/java/android/app/slice/Slice.java
index 5bd3440d09f8..5808f8b510d9 100644
--- a/core/java/android/app/slice/Slice.java
+++ b/core/java/android/app/slice/Slice.java
@@ -156,10 +156,11 @@ public final class Slice implements Parcelable {
*/
public static final String HINT_SEE_MORE = "see_more";
/**
- * A hint to tell the system that this slice cares about the return value of
- * {@link SliceProvider#getBindingPackage} and should not cache the result
- * for multiple apps.
- * @hide
+ * A hint used when implementing app-specific slice permissions.
+ * Tells the system that for this slice the return value of
+ * {@link SliceProvider#onBindSlice(Uri, List)} may be different depending on
+ * {@link SliceProvider#getBindingPackage} and should not be cached for multiple
+ * apps.
*/
public static final String HINT_CALLER_NEEDED = "caller_needed";
/**
@@ -429,28 +430,6 @@ public final class Slice implements Parcelable {
* Add a color to the slice being constructed
* @param subType Optional template-specific type information
* @see {@link SliceItem#getSubType()}
- * @deprecated will be removed once supportlib updates
- */
- public Builder addColor(int color, @Nullable String subType, @SliceHint String... hints) {
- mItems.add(new SliceItem(color, SliceItem.FORMAT_INT, subType, hints));
- return this;
- }
-
- /**
- * Add a color to the slice being constructed
- * @param subType Optional template-specific type information
- * @see {@link SliceItem#getSubType()}
- * @deprecated will be removed once supportlib updates
- */
- public Builder addColor(int color, @Nullable String subType,
- @SliceHint List<String> hints) {
- return addColor(color, subType, hints.toArray(new String[hints.size()]));
- }
-
- /**
- * Add a color to the slice being constructed
- * @param subType Optional template-specific type information
- * @see {@link SliceItem#getSubType()}
*/
public Builder addInt(int value, @Nullable String subType, @SliceHint String... hints) {
mItems.add(new SliceItem(value, SliceItem.FORMAT_INT, subType, hints));
diff --git a/core/java/android/app/slice/SliceItem.java b/core/java/android/app/slice/SliceItem.java
index bcfd413fb823..9eb2bb896356 100644
--- a/core/java/android/app/slice/SliceItem.java
+++ b/core/java/android/app/slice/SliceItem.java
@@ -98,11 +98,6 @@ public final class SliceItem implements Parcelable {
*/
public static final String FORMAT_INT = "int";
/**
- * A {@link SliceItem} that contains an int.
- * @deprecated to be removed
- */
- public static final String FORMAT_COLOR = "color";
- /**
* A {@link SliceItem} that contains a timestamp.
*/
public static final String FORMAT_TIMESTAMP = "timestamp";
@@ -231,13 +226,6 @@ public final class SliceItem implements Parcelable {
}
/**
- * @deprecated to be removed.
- */
- public int getColor() {
- return (Integer) mObj;
- }
-
- /**
* @return The slice held by this {@link #FORMAT_ACTION} or {@link #FORMAT_SLICE} SliceItem
*/
public Slice getSlice() {
diff --git a/core/java/android/app/slice/SliceProvider.java b/core/java/android/app/slice/SliceProvider.java
index bd4103f60ac6..00e8ccad0f5f 100644
--- a/core/java/android/app/slice/SliceProvider.java
+++ b/core/java/android/app/slice/SliceProvider.java
@@ -158,7 +158,6 @@ public abstract class SliceProvider extends ContentProvider {
* currently happening. The returned package will have been
* verified to belong to the calling UID. Returns {@code null} if not
* currently performing an {@link #onBindSlice(Uri, List)}.
- * @hide
*/
public final @Nullable String getBindingPackage() {
return mBindingPkg;
diff --git a/core/java/android/app/timezone/RulesState.java b/core/java/android/app/timezone/RulesState.java
index 16309fab0924..e86d348a85fa 100644
--- a/core/java/android/app/timezone/RulesState.java
+++ b/core/java/android/app/timezone/RulesState.java
@@ -126,9 +126,6 @@ public final class RulesState implements Parcelable {
mStagedOperationType == STAGED_OPERATION_INSTALL /* requireNotNull */,
"stagedDistroRulesVersion", stagedDistroRulesVersion);
- if (operationInProgress && distroStatus != DISTRO_STATUS_UNKNOWN) {
- throw new IllegalArgumentException("distroInstalled != DISTRO_STATUS_UNKNOWN");
- }
this.mDistroStatus = validateDistroStatus(distroStatus);
this.mInstalledDistroRulesVersion = validateConditionalNull(
mDistroStatus == DISTRO_STATUS_INSTALLED/* requireNotNull */,
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index ef1bcb0dcf9a..acbdf142c62d 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -3930,6 +3930,14 @@ public class Intent implements Parcelable, Cloneable {
@SdkConstant(SdkConstantType.INTENT_CATEGORY)
public static final String CATEGORY_LEANBACK_LAUNCHER = "android.intent.category.LEANBACK_LAUNCHER";
/**
+ * Indicates the preferred entry-point activity when an application is launched from a Car
+ * launcher. If not present, Car launcher can optionally use {@link #CATEGORY_LAUNCHER} as a
+ * fallback, or exclude the application entirely.
+ * @hide
+ */
+ @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+ public static final String CATEGORY_CAR_LAUNCHER = "android.intent.category.CAR_LAUNCHER";
+ /**
* Indicates a Leanback settings activity to be displayed in the Leanback launcher.
* @hide
*/
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index bcf80eeaaee7..b81267ab46f9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3044,6 +3044,21 @@ public abstract class PackageManager {
public abstract @Nullable Intent getLeanbackLaunchIntentForPackage(@NonNull String packageName);
/**
+ * Return a "good" intent to launch a front-door Car activity in a
+ * package, for use for example to implement an "open" button when browsing
+ * through packages. The current implementation will look for a main
+ * activity in the category {@link Intent#CATEGORY_CAR_LAUNCHER}, or
+ * return null if no main car activities are found.
+ *
+ * @param packageName The name of the package to inspect.
+ * @return Returns either a fully-qualified Intent that can be used to launch
+ * the main Car activity in the package, or null if the package
+ * does not contain such an activity.
+ * @hide
+ */
+ public abstract @Nullable Intent getCarLaunchIntentForPackage(@NonNull String packageName);
+
+ /**
* Return an array of all of the POSIX secondary group IDs that have been
* assigned to the given package.
* <p>
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4a71467f4b36..4efd08134065 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -5684,23 +5684,74 @@ public class PackageParser {
@Nullable
public final ArraySet<PublicKey> publicKeys;
+ /**
+ * Collection of {@code Signature} objects, each of which is formed from a former signing
+ * certificate of this APK before it was changed by signing certificate rotation.
+ */
+ @Nullable
+ public final Signature[] pastSigningCertificates;
+
+ /**
+ * Flags for the {@code pastSigningCertificates} collection, which indicate the capabilities
+ * the including APK wishes to grant to its past signing certificates.
+ */
+ @Nullable
+ public final int[] pastSigningCertificatesFlags;
+
/** A representation of unknown signing details. Use instead of null. */
public static final SigningDetails UNKNOWN =
- new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null);
+ new SigningDetails(null, SignatureSchemeVersion.UNKNOWN, null, null, null);
@VisibleForTesting
public SigningDetails(Signature[] signatures,
@SignatureSchemeVersion int signatureSchemeVersion,
- ArraySet<PublicKey> keys) {
+ ArraySet<PublicKey> keys, Signature[] pastSigningCertificates,
+ int[] pastSigningCertificatesFlags) {
this.signatures = signatures;
this.signatureSchemeVersion = signatureSchemeVersion;
this.publicKeys = keys;
+ this.pastSigningCertificates = pastSigningCertificates;
+ this.pastSigningCertificatesFlags = pastSigningCertificatesFlags;
+ }
+
+ public SigningDetails(Signature[] signatures,
+ @SignatureSchemeVersion int signatureSchemeVersion,
+ Signature[] pastSigningCertificates, int[] pastSigningCertificatesFlags)
+ throws CertificateException {
+ this(signatures, signatureSchemeVersion, toSigningKeys(signatures),
+ pastSigningCertificates, pastSigningCertificatesFlags);
}
public SigningDetails(Signature[] signatures,
@SignatureSchemeVersion int signatureSchemeVersion)
throws CertificateException {
- this(signatures, signatureSchemeVersion, toSigningKeys(signatures));
+ this(signatures, signatureSchemeVersion,
+ null, null);
+ }
+
+ public SigningDetails(SigningDetails orig) {
+ if (orig != null) {
+ if (orig.signatures != null) {
+ this.signatures = orig.signatures.clone();
+ } else {
+ this.signatures = null;
+ }
+ this.signatureSchemeVersion = orig.signatureSchemeVersion;
+ this.publicKeys = new ArraySet<>(orig.publicKeys);
+ if (orig.pastSigningCertificates != null) {
+ this.pastSigningCertificates = orig.pastSigningCertificates.clone();
+ this.pastSigningCertificatesFlags = orig.pastSigningCertificatesFlags.clone();
+ } else {
+ this.pastSigningCertificates = null;
+ this.pastSigningCertificatesFlags = null;
+ }
+ } else {
+ this.signatures = null;
+ this.signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
+ this.publicKeys = null;
+ this.pastSigningCertificates = null;
+ this.pastSigningCertificatesFlags = null;
+ }
}
/** Returns true if the signing details have one or more signatures. */
@@ -5728,6 +5779,8 @@ public class PackageParser {
dest.writeTypedArray(this.signatures, flags);
dest.writeInt(this.signatureSchemeVersion);
dest.writeArraySet(this.publicKeys);
+ dest.writeTypedArray(this.pastSigningCertificates, flags);
+ dest.writeIntArray(this.pastSigningCertificatesFlags);
}
protected SigningDetails(Parcel in) {
@@ -5735,6 +5788,8 @@ public class PackageParser {
this.signatures = in.createTypedArray(Signature.CREATOR);
this.signatureSchemeVersion = in.readInt();
this.publicKeys = (ArraySet<PublicKey>) in.readArraySet(boot);
+ this.pastSigningCertificates = in.createTypedArray(Signature.CREATOR);
+ this.pastSigningCertificatesFlags = in.createIntArray();
}
public static final Creator<SigningDetails> CREATOR = new Creator<SigningDetails>() {
@@ -5761,8 +5816,23 @@ public class PackageParser {
if (signatureSchemeVersion != that.signatureSchemeVersion) return false;
if (!Signature.areExactMatch(signatures, that.signatures)) return false;
- return publicKeys != null ? publicKeys.equals(that.publicKeys)
- : that.publicKeys == null;
+ if (publicKeys != null) {
+ if (!publicKeys.equals((that.publicKeys))) {
+ return false;
+ }
+ } else if (that.publicKeys != null) {
+ return false;
+ }
+
+ // can't use Signature.areExactMatch() because order matters with the past signing certs
+ if (!Arrays.equals(pastSigningCertificates, that.pastSigningCertificates)) {
+ return false;
+ }
+ if (!Arrays.equals(pastSigningCertificatesFlags, that.pastSigningCertificatesFlags)) {
+ return false;
+ }
+
+ return true;
}
@Override
@@ -5770,8 +5840,77 @@ public class PackageParser {
int result = +Arrays.hashCode(signatures);
result = 31 * result + signatureSchemeVersion;
result = 31 * result + (publicKeys != null ? publicKeys.hashCode() : 0);
+ result = 31 * result + Arrays.hashCode(pastSigningCertificates);
+ result = 31 * result + Arrays.hashCode(pastSigningCertificatesFlags);
return result;
}
+
+ /**
+ * Builder of {@code SigningDetails} instances.
+ */
+ public static class Builder {
+ private Signature[] mSignatures;
+ private int mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
+ private Signature[] mPastSigningCertificates;
+ private int[] mPastSigningCertificatesFlags;
+
+ public Builder() {
+ }
+
+ /** get signing certificates used to sign the current APK */
+ public Builder setSignatures(Signature[] signatures) {
+ mSignatures = signatures;
+ return this;
+ }
+
+ /** set the signature scheme version used to sign the APK */
+ public Builder setSignatureSchemeVersion(int signatureSchemeVersion) {
+ mSignatureSchemeVersion = signatureSchemeVersion;
+ return this;
+ }
+
+ /** set the signing certificates by which the APK proved it can be authenticated */
+ public Builder setPastSigningCertificates(Signature[] pastSigningCertificates) {
+ mPastSigningCertificates = pastSigningCertificates;
+ return this;
+ }
+
+ /** set the flags for the {@code pastSigningCertificates} */
+ public Builder setPastSigningCertificatesFlags(int[] pastSigningCertificatesFlags) {
+ mPastSigningCertificatesFlags = pastSigningCertificatesFlags;
+ return this;
+ }
+
+ private void checkInvariants() {
+ // must have signatures and scheme version set
+ if (mSignatures == null) {
+ throw new IllegalStateException("SigningDetails requires the current signing"
+ + " certificates.");
+ }
+
+ // pastSigningCerts and flags must match up
+ boolean pastMismatch = false;
+ if (mPastSigningCertificates != null && mPastSigningCertificatesFlags != null) {
+ if (mPastSigningCertificates.length != mPastSigningCertificatesFlags.length) {
+ pastMismatch = true;
+ }
+ } else if (!(mPastSigningCertificates == null
+ && mPastSigningCertificatesFlags == null)) {
+ pastMismatch = true;
+ }
+ if (pastMismatch) {
+ throw new IllegalStateException("SigningDetails must have a one to one mapping "
+ + "between pastSigningCertificates and pastSigningCertificatesFlags");
+ }
+ }
+ /** build a {@code SigningDetails} object */
+ public SigningDetails build()
+ throws CertificateException {
+ checkInvariants();
+ return new SigningDetails(mSignatures, mSignatureSchemeVersion,
+ mPastSigningCertificates, mPastSigningCertificatesFlags);
+ }
+ }
}
/**
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 7654e9b6ee22..76838807acc5 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -143,7 +143,7 @@ public class Process {
* Defines the UID/GID for the WebView zygote process.
* @hide
*/
- public static final int WEBVIEW_ZYGOTE_UID = 1051;
+ public static final int WEBVIEW_ZYGOTE_UID = 1053;
/**
* Defines the UID used for resource tracking for OTA updates.
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 0e323f8570a0..228a86d40463 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -41,7 +41,6 @@ import android.app.ActivityThread;
import android.app.AppOpsManager;
import android.app.Application;
import android.app.NotificationChannel;
-import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.SearchManager;
import android.app.WallpaperManager;
@@ -75,7 +74,6 @@ import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.provider.SettingsValidators;
import android.provider.SettingsValidators.Validator;
import android.speech.tts.TextToSpeech;
import android.telephony.SubscriptionManager;
@@ -1345,18 +1343,6 @@ public final class Settings {
= "android.settings.CHANNEL_NOTIFICATION_SETTINGS";
/**
- * Activity Action: Show notification settings for a single {@link NotificationChannelGroup}.
- * <p>
- * Input: {@link #EXTRA_APP_PACKAGE}, the package containing the channel group to display.
- * Input: {@link #EXTRA_CHANNEL_GROUP_ID}, the id of the channel group to display.
- * <p>
- * Output: Nothing.
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS =
- "android.settings.CHANNEL_GROUP_NOTIFICATION_SETTINGS";
-
- /**
* Activity Extra: The package owner of the notification channel settings to display.
* <p>
* This must be passed as an extra field to the {@link #ACTION_CHANNEL_NOTIFICATION_SETTINGS}.
@@ -1372,15 +1358,6 @@ public final class Settings {
public static final String EXTRA_CHANNEL_ID = "android.provider.extra.CHANNEL_ID";
/**
- * Activity Extra: The {@link NotificationChannelGroup#getId()} of the notification channel
- * group settings to display.
- * <p>
- * This must be passed as an extra field to the
- * {@link #ACTION_CHANNEL_GROUP_NOTIFICATION_SETTINGS}.
- */
- public static final String EXTRA_CHANNEL_GROUP_ID = "android.provider.extra.CHANNEL_GROUP_ID";
-
- /**
* Activity Action: Show notification redaction settings.
*
* @hide
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java
index 72afbb8414f6..346437032845 100644
--- a/core/java/android/security/keymaster/KeymasterDefs.java
+++ b/core/java/android/security/keymaster/KeymasterDefs.java
@@ -102,6 +102,7 @@ public final class KeymasterDefs {
public static final int KM_ALGORITHM_RSA = 1;
public static final int KM_ALGORITHM_EC = 3;
public static final int KM_ALGORITHM_AES = 32;
+ public static final int KM_ALGORITHM_3DES = 33;
public static final int KM_ALGORITHM_HMAC = 128;
// Block modes.
@@ -131,6 +132,7 @@ public final class KeymasterDefs {
public static final int KM_ORIGIN_GENERATED = 0;
public static final int KM_ORIGIN_IMPORTED = 2;
public static final int KM_ORIGIN_UNKNOWN = 3;
+ public static final int KM_ORIGIN_SECURELY_IMPORTED = 4;
// Key usability requirements.
public static final int KM_BLOB_STANDALONE = 0;
@@ -141,6 +143,7 @@ public final class KeymasterDefs {
public static final int KM_PURPOSE_DECRYPT = 1;
public static final int KM_PURPOSE_SIGN = 2;
public static final int KM_PURPOSE_VERIFY = 3;
+ public static final int KM_PURPOSE_WRAP = 5;
// Key formats.
public static final int KM_KEY_FORMAT_X509 = 0;
diff --git a/core/java/android/security/keystore/BackwardsCompat.java b/core/java/android/security/keystore/BackwardsCompat.java
new file mode 100644
index 000000000000..24921f03f136
--- /dev/null
+++ b/core/java/android/security/keystore/BackwardsCompat.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2018 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.security.keystore;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Function;
+
+/**
+ * Helpers for converting classes between old and new API, so we can preserve backwards
+ * compatibility while teamfooding. This will be removed soon.
+ *
+ * @hide
+ */
+class BackwardsCompat {
+
+
+ static KeychainProtectionParams toLegacyKeychainProtectionParams(
+ android.security.keystore.recovery.KeychainProtectionParams keychainProtectionParams
+ ) {
+ return new KeychainProtectionParams.Builder()
+ .setUserSecretType(keychainProtectionParams.getUserSecretType())
+ .setSecret(keychainProtectionParams.getSecret())
+ .setLockScreenUiFormat(keychainProtectionParams.getLockScreenUiFormat())
+ .setKeyDerivationParams(
+ toLegacyKeyDerivationParams(
+ keychainProtectionParams.getKeyDerivationParams()))
+ .build();
+ }
+
+ static KeyDerivationParams toLegacyKeyDerivationParams(
+ android.security.keystore.recovery.KeyDerivationParams keyDerivationParams
+ ) {
+ return new KeyDerivationParams(
+ keyDerivationParams.getAlgorithm(), keyDerivationParams.getSalt());
+ }
+
+ static WrappedApplicationKey toLegacyWrappedApplicationKey(
+ android.security.keystore.recovery.WrappedApplicationKey wrappedApplicationKey
+ ) {
+ return new WrappedApplicationKey.Builder()
+ .setAlias(wrappedApplicationKey.getAlias())
+ .setEncryptedKeyMaterial(wrappedApplicationKey.getEncryptedKeyMaterial())
+ .build();
+ }
+
+ static android.security.keystore.recovery.KeyDerivationParams fromLegacyKeyDerivationParams(
+ KeyDerivationParams keyDerivationParams
+ ) {
+ return new android.security.keystore.recovery.KeyDerivationParams(
+ keyDerivationParams.getAlgorithm(), keyDerivationParams.getSalt());
+ }
+
+ static android.security.keystore.recovery.WrappedApplicationKey fromLegacyWrappedApplicationKey(
+ WrappedApplicationKey wrappedApplicationKey
+ ) {
+ return new android.security.keystore.recovery.WrappedApplicationKey.Builder()
+ .setAlias(wrappedApplicationKey.getAlias())
+ .setEncryptedKeyMaterial(wrappedApplicationKey.getEncryptedKeyMaterial())
+ .build();
+ }
+
+ static List<android.security.keystore.recovery.WrappedApplicationKey>
+ fromLegacyWrappedApplicationKeys(List<WrappedApplicationKey> wrappedApplicationKeys
+ ) {
+ return map(wrappedApplicationKeys, BackwardsCompat::fromLegacyWrappedApplicationKey);
+ }
+
+ static List<android.security.keystore.recovery.KeychainProtectionParams>
+ fromLegacyKeychainProtectionParams(
+ List<KeychainProtectionParams> keychainProtectionParams) {
+ return map(keychainProtectionParams, BackwardsCompat::fromLegacyKeychainProtectionParam);
+ }
+
+ static android.security.keystore.recovery.KeychainProtectionParams
+ fromLegacyKeychainProtectionParam(KeychainProtectionParams keychainProtectionParams) {
+ return new android.security.keystore.recovery.KeychainProtectionParams.Builder()
+ .setUserSecretType(keychainProtectionParams.getUserSecretType())
+ .setSecret(keychainProtectionParams.getSecret())
+ .setLockScreenUiFormat(keychainProtectionParams.getLockScreenUiFormat())
+ .setKeyDerivationParams(
+ fromLegacyKeyDerivationParams(
+ keychainProtectionParams.getKeyDerivationParams()))
+ .build();
+ }
+
+ static KeychainSnapshot toLegacyKeychainSnapshot(
+ android.security.keystore.recovery.KeychainSnapshot keychainSnapshot
+ ) {
+ return new KeychainSnapshot.Builder()
+ .setCounterId(keychainSnapshot.getCounterId())
+ .setEncryptedRecoveryKeyBlob(keychainSnapshot.getEncryptedRecoveryKeyBlob())
+ .setTrustedHardwarePublicKey(keychainSnapshot.getTrustedHardwarePublicKey())
+ .setSnapshotVersion(keychainSnapshot.getSnapshotVersion())
+ .setMaxAttempts(keychainSnapshot.getMaxAttempts())
+ .setServerParams(keychainSnapshot.getServerParams())
+ .setKeychainProtectionParams(
+ map(keychainSnapshot.getKeychainProtectionParams(),
+ BackwardsCompat::toLegacyKeychainProtectionParams))
+ .setWrappedApplicationKeys(
+ map(keychainSnapshot.getWrappedApplicationKeys(),
+ BackwardsCompat::toLegacyWrappedApplicationKey))
+ .build();
+ }
+
+ static <A, B> List<B> map(List<A> as, Function<A, B> f) {
+ ArrayList<B> bs = new ArrayList<>(as.size());
+ for (A a : as) {
+ bs.add(f.apply(a));
+ }
+ return bs;
+ }
+}
diff --git a/core/java/android/security/keystore/KeyDerivationParams.java b/core/java/android/security/keystore/KeyDerivationParams.java
index b702accffba1..b19cee2d31a4 100644
--- a/core/java/android/security/keystore/KeyDerivationParams.java
+++ b/core/java/android/security/keystore/KeyDerivationParams.java
@@ -61,7 +61,7 @@ public final class KeyDerivationParams implements Parcelable {
return new KeyDerivationParams(ALGORITHM_SHA256, salt);
}
- private KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) {
+ KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) {
mAlgorithm = algorithm;
mSalt = Preconditions.checkNotNull(salt);
}
diff --git a/core/java/android/security/keystore/RecoveryController.java b/core/java/android/security/keystore/RecoveryController.java
index 87283cbd75ab..8be6d5263c53 100644
--- a/core/java/android/security/keystore/RecoveryController.java
+++ b/core/java/android/security/keystore/RecoveryController.java
@@ -167,7 +167,7 @@ public class RecoveryController {
public @NonNull KeychainSnapshot getRecoveryData(@NonNull byte[] account)
throws InternalRecoveryServiceException {
try {
- return mBinder.getRecoveryData(account);
+ return BackwardsCompat.toLegacyKeychainSnapshot(mBinder.getRecoveryData(account));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
@@ -360,28 +360,6 @@ public class RecoveryController {
}
/**
- * Method notifies KeyStore that a user-generated secret is available. This method generates a
- * symmetric session key which a trusted remote device can use to return a recovery key. Caller
- * should use {@link KeychainProtectionParams#clearSecret} to override the secret value in
- * memory.
- *
- * @param recoverySecret user generated secret together with parameters necessary to regenerate
- * it on a new device.
- * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
- * service.
- */
- public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret)
- throws InternalRecoveryServiceException {
- try {
- mBinder.recoverySecretAvailable(recoverySecret);
- } catch (RemoteException e) {
- throw e.rethrowFromSystemServer();
- } catch (ServiceSpecificException e) {
- throw wrapUnexpectedServiceSpecificException(e);
- }
- }
-
- /**
* Initializes recovery session and returns a blob with proof of recovery secrets possession.
* The method generates symmetric key for a session, which trusted remote device can use to
* return recovery key.
@@ -417,7 +395,7 @@ public class RecoveryController {
verifierPublicKey,
vaultParams,
vaultChallenge,
- secrets);
+ BackwardsCompat.fromLegacyKeychainProtectionParams(secrets));
return new RecoveryClaim(recoverySession, recoveryClaim);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -451,7 +429,9 @@ public class RecoveryController {
InternalRecoveryServiceException {
try {
return (Map<String, byte[]>) mBinder.recoverKeys(
- session.getSessionId(), recoveryKeyBlob, applicationKeys);
+ session.getSessionId(),
+ recoveryKeyBlob,
+ BackwardsCompat.fromLegacyWrappedApplicationKeys(applicationKeys));
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
} catch (ServiceSpecificException e) {
diff --git a/core/java/android/security/keystore/recovery/BadCertificateFormatException.java b/core/java/android/security/keystore/recovery/BadCertificateFormatException.java
new file mode 100644
index 000000000000..fda3387bb63b
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/BadCertificateFormatException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+/**
+ * Error thrown when the recovery agent supplies an invalid X509 certificate.
+ *
+ * @hide
+ */
+public class BadCertificateFormatException extends RecoveryControllerException {
+ public BadCertificateFormatException(String msg) {
+ super(msg);
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/DecryptionFailedException.java b/core/java/android/security/keystore/recovery/DecryptionFailedException.java
new file mode 100644
index 000000000000..b414dc59834b
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/DecryptionFailedException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+/**
+ * Error thrown when decryption failed, due to an agent error. i.e., using the incorrect key,
+ * trying to decrypt garbage data, trying to decrypt data that has somehow been corrupted, etc.
+ *
+ * @hide
+ */
+public class DecryptionFailedException extends RecoveryControllerException {
+
+ public DecryptionFailedException(String msg) {
+ super(msg);
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java b/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java
new file mode 100644
index 000000000000..07a540ceea25
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/InternalRecoveryServiceException.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+/**
+ * An error thrown when something went wrong internally in the recovery service.
+ *
+ * <p>This is an unexpected error, and indicates a problem with the service itself, rather than the
+ * caller having performed some kind of illegal action.
+ *
+ * @hide
+ */
+public class InternalRecoveryServiceException extends RecoveryControllerException {
+ public InternalRecoveryServiceException(String msg) {
+ super(msg);
+ }
+
+ public InternalRecoveryServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/core/java/android/security/keystore/KeyDerivationParams.aidl b/core/java/android/security/keystore/recovery/KeyDerivationParams.aidl
index f39aa047adee..2b1bbbe35f1a 100644
--- a/core/java/android/security/keystore/KeyDerivationParams.aidl
+++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.security.keystore;
+package android.security.keystore.recovery;
/* @hide */
parcelable KeyDerivationParams;
diff --git a/core/java/android/security/keystore/recovery/KeyDerivationParams.java b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
new file mode 100644
index 000000000000..90613952ae9b
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/KeyDerivationParams.java
@@ -0,0 +1,116 @@
+/*
+ * 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.security.keystore.recovery;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Collection of parameters which define a key derivation function.
+ * Currently only supports salted SHA-256
+ *
+ * @hide
+ */
+public final class KeyDerivationParams implements Parcelable {
+ private final int mAlgorithm;
+ private byte[] mSalt;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef(prefix = {"ALGORITHM_"}, value = {ALGORITHM_SHA256, ALGORITHM_ARGON2ID})
+ public @interface KeyDerivationAlgorithm {
+ }
+
+ /**
+ * Salted SHA256
+ */
+ public static final int ALGORITHM_SHA256 = 1;
+
+ /**
+ * Argon2ID
+ * @hide
+ */
+ // TODO: add Argon2ID support.
+ public static final int ALGORITHM_ARGON2ID = 2;
+
+ /**
+ * Creates instance of the class to to derive key using salted SHA256 hash.
+ */
+ public static KeyDerivationParams createSha256Params(@NonNull byte[] salt) {
+ return new KeyDerivationParams(ALGORITHM_SHA256, salt);
+ }
+
+ // TODO: Make private once legacy API is removed
+ public KeyDerivationParams(@KeyDerivationAlgorithm int algorithm, @NonNull byte[] salt) {
+ mAlgorithm = algorithm;
+ mSalt = Preconditions.checkNotNull(salt);
+ }
+
+ /**
+ * Gets algorithm.
+ */
+ public @KeyDerivationAlgorithm int getAlgorithm() {
+ return mAlgorithm;
+ }
+
+ /**
+ * Gets salt.
+ */
+ public @NonNull byte[] getSalt() {
+ return mSalt;
+ }
+
+ public static final Creator<KeyDerivationParams> CREATOR =
+ new Creator<KeyDerivationParams>() {
+ public KeyDerivationParams createFromParcel(Parcel in) {
+ return new KeyDerivationParams(in);
+ }
+
+ public KeyDerivationParams[] newArray(int length) {
+ return new KeyDerivationParams[length];
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mAlgorithm);
+ out.writeByteArray(mSalt);
+ }
+
+ /**
+ * @hide
+ */
+ protected KeyDerivationParams(Parcel in) {
+ mAlgorithm = in.readInt();
+ mSalt = in.createByteArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/security/keystore/KeychainProtectionParams.aidl b/core/java/android/security/keystore/recovery/KeychainProtectionParams.aidl
index 0341223b081a..538573847b00 100644
--- a/core/java/android/security/keystore/KeychainProtectionParams.aidl
+++ b/core/java/android/security/keystore/recovery/KeychainProtectionParams.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.security.keystore;
+package android.security.keystore.recovery;
/* @hide */
parcelable KeychainProtectionParams;
diff --git a/core/java/android/security/keystore/recovery/KeychainProtectionParams.java b/core/java/android/security/keystore/recovery/KeychainProtectionParams.java
new file mode 100644
index 000000000000..445815b48e7c
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/KeychainProtectionParams.java
@@ -0,0 +1,289 @@
+/*
+ * 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.security.keystore.recovery;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Arrays;
+
+/**
+ * A {@link KeychainSnapshot} is protected with a key derived from the user's lock screen. This
+ * class wraps all the data necessary to derive the same key on a recovering device:
+ *
+ * <ul>
+ * <li>UI parameters for the user's lock screen - so that if e.g., the user was using a pattern,
+ * the recovering device can display the pattern UI to the user when asking them to enter
+ * the lock screen from their previous device.
+ * <li>The algorithm used to derive a key from the user's lock screen, e.g. SHA-256 with a salt.
+ * </ul>
+ *
+ * <p>As such, this data is sent along with the {@link KeychainSnapshot} when syncing the current
+ * version of the keychain.
+ *
+ * <p>For now, the recoverable keychain only supports a single layer of protection, which is the
+ * user's lock screen. In the future, the keychain will support multiple layers of protection
+ * (e.g. an additional keychain password, along with the lock screen).
+ *
+ * @hide
+ */
+public final class KeychainProtectionParams implements Parcelable {
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({TYPE_LOCKSCREEN, TYPE_CUSTOM_PASSWORD})
+ public @interface UserSecretType {
+ }
+
+ /**
+ * Lockscreen secret is required to recover KeyStore.
+ */
+ public static final int TYPE_LOCKSCREEN = 100;
+
+ /**
+ * Custom passphrase, unrelated to lock screen, is required to recover KeyStore.
+ */
+ public static final int TYPE_CUSTOM_PASSWORD = 101;
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({TYPE_PIN, TYPE_PASSWORD, TYPE_PATTERN})
+ public @interface LockScreenUiFormat {
+ }
+
+ /**
+ * Pin with digits only.
+ */
+ public static final int TYPE_PIN = 1;
+
+ /**
+ * Password. String with latin-1 characters only.
+ */
+ public static final int TYPE_PASSWORD = 2;
+
+ /**
+ * Pattern with 3 by 3 grid.
+ */
+ public static final int TYPE_PATTERN = 3;
+
+ @UserSecretType
+ private Integer mUserSecretType;
+
+ @LockScreenUiFormat
+ private Integer mLockScreenUiFormat;
+
+ /**
+ * Parameters of the key derivation function, including algorithm, difficulty, salt.
+ */
+ private KeyDerivationParams mKeyDerivationParams;
+ private byte[] mSecret; // Derived from user secret. The field must have limited visibility.
+
+ /**
+ * @param secret Constructor creates a reference to the secret. Caller must use
+ * @link {#clearSecret} to overwrite its value in memory.
+ * @hide
+ */
+ public KeychainProtectionParams(@UserSecretType int userSecretType,
+ @LockScreenUiFormat int lockScreenUiFormat,
+ @NonNull KeyDerivationParams keyDerivationParams,
+ @NonNull byte[] secret) {
+ mUserSecretType = userSecretType;
+ mLockScreenUiFormat = lockScreenUiFormat;
+ mKeyDerivationParams = Preconditions.checkNotNull(keyDerivationParams);
+ mSecret = Preconditions.checkNotNull(secret);
+ }
+
+ private KeychainProtectionParams() {
+
+ }
+
+ /**
+ * @see TYPE_LOCKSCREEN
+ * @see TYPE_CUSTOM_PASSWORD
+ */
+ public @UserSecretType int getUserSecretType() {
+ return mUserSecretType;
+ }
+
+ /**
+ * Specifies UX shown to user during recovery.
+ * Default value is {@code TYPE_LOCKSCREEN}
+ *
+ * @see TYPE_PIN
+ * @see TYPE_PASSWORD
+ * @see TYPE_PATTERN
+ */
+ public @LockScreenUiFormat int getLockScreenUiFormat() {
+ return mLockScreenUiFormat;
+ }
+
+ /**
+ * Specifies function used to derive symmetric key from user input
+ * Format is defined in separate util class.
+ */
+ @NonNull public KeyDerivationParams getKeyDerivationParams() {
+ return mKeyDerivationParams;
+ }
+
+ /**
+ * Secret derived from user input.
+ * Default value is empty array
+ *
+ * @return secret or empty array
+ */
+ public @NonNull byte[] getSecret() {
+ return mSecret;
+ }
+
+ /**
+ * Builder for creating {@link KeychainProtectionParams}.
+ */
+ public static class Builder {
+ private KeychainProtectionParams
+ mInstance = new KeychainProtectionParams();
+
+ /**
+ * Sets user secret type.
+ *
+ * @see TYPE_LOCKSCREEN
+ * @see TYPE_CUSTOM_PASSWORD
+ * @param userSecretType The secret type
+ * @return This builder.
+ */
+ public Builder setUserSecretType(@UserSecretType int userSecretType) {
+ mInstance.mUserSecretType = userSecretType;
+ return this;
+ }
+
+ /**
+ * Sets UI format.
+ *
+ * @see TYPE_PIN
+ * @see TYPE_PASSWORD
+ * @see TYPE_PATTERN
+ * @param lockScreenUiFormat The UI format
+ * @return This builder.
+ */
+ public Builder setLockScreenUiFormat(@LockScreenUiFormat int lockScreenUiFormat) {
+ mInstance.mLockScreenUiFormat = lockScreenUiFormat;
+ return this;
+ }
+
+ /**
+ * Sets parameters of the key derivation function.
+ *
+ * @param keyDerivationParams Key derivation Params
+ * @return This builder.
+ */
+ public Builder setKeyDerivationParams(@NonNull KeyDerivationParams
+ keyDerivationParams) {
+ mInstance.mKeyDerivationParams = keyDerivationParams;
+ return this;
+ }
+
+ /**
+ * Secret derived from user input, or empty array.
+ *
+ * @param secret The secret.
+ * @return This builder.
+ */
+ public Builder setSecret(@NonNull byte[] secret) {
+ mInstance.mSecret = secret;
+ return this;
+ }
+
+
+ /**
+ * Creates a new {@link KeychainProtectionParams} instance.
+ * The instance will include default values, if {@link setSecret}
+ * or {@link setUserSecretType} were not called.
+ *
+ * @return new instance
+ * @throws NullPointerException if some required fields were not set.
+ */
+ @NonNull public KeychainProtectionParams build() {
+ if (mInstance.mUserSecretType == null) {
+ mInstance.mUserSecretType = TYPE_LOCKSCREEN;
+ }
+ Preconditions.checkNotNull(mInstance.mLockScreenUiFormat);
+ Preconditions.checkNotNull(mInstance.mKeyDerivationParams);
+ if (mInstance.mSecret == null) {
+ mInstance.mSecret = new byte[]{};
+ }
+ return mInstance;
+ }
+ }
+
+ /**
+ * Removes secret from memory than object is no longer used.
+ * Since finalizer call is not reliable, please use @link {#clearSecret} directly.
+ */
+ @Override
+ protected void finalize() throws Throwable {
+ clearSecret();
+ super.finalize();
+ }
+
+ /**
+ * Fills mSecret with zeroes.
+ */
+ public void clearSecret() {
+ Arrays.fill(mSecret, (byte) 0);
+ }
+
+ public static final Creator<KeychainProtectionParams> CREATOR =
+ new Creator<KeychainProtectionParams>() {
+ public KeychainProtectionParams createFromParcel(Parcel in) {
+ return new KeychainProtectionParams(in);
+ }
+
+ public KeychainProtectionParams[] newArray(int length) {
+ return new KeychainProtectionParams[length];
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mUserSecretType);
+ out.writeInt(mLockScreenUiFormat);
+ out.writeTypedObject(mKeyDerivationParams, flags);
+ out.writeByteArray(mSecret);
+ }
+
+ /**
+ * @hide
+ */
+ protected KeychainProtectionParams(Parcel in) {
+ mUserSecretType = in.readInt();
+ mLockScreenUiFormat = in.readInt();
+ mKeyDerivationParams = in.readTypedObject(KeyDerivationParams.CREATOR);
+ mSecret = in.createByteArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/security/keystore/KeychainSnapshot.aidl b/core/java/android/security/keystore/recovery/KeychainSnapshot.aidl
index b35713f329d6..7822f39bf269 100644
--- a/core/java/android/security/keystore/KeychainSnapshot.aidl
+++ b/core/java/android/security/keystore/recovery/KeychainSnapshot.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.security.keystore;
+package android.security.keystore.recovery;
/* @hide */
parcelable KeychainSnapshot;
diff --git a/core/java/android/security/keystore/recovery/KeychainSnapshot.java b/core/java/android/security/keystore/recovery/KeychainSnapshot.java
new file mode 100644
index 000000000000..a8e2725c0339
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/KeychainSnapshot.java
@@ -0,0 +1,300 @@
+/*
+ * 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.security.keystore.recovery;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+
+/**
+ * A snapshot of a version of the keystore. Two events can trigger the generation of a new snapshot:
+ *
+ * <ul>
+ * <li>The user's lock screen changes. (A key derived from the user's lock screen is used to
+ * protected the keychain, which is why this forces a new snapshot.)
+ * <li>A key is added to or removed from the recoverable keychain.
+ * </ul>
+ *
+ * <p>The snapshot data is also encrypted with the remote trusted hardware's public key, so even
+ * the recovery agent itself should not be able to decipher the data. The recovery agent sends an
+ * instance of this to the remote trusted hardware whenever a new snapshot is generated. During a
+ * recovery flow, the recovery agent retrieves a snapshot from the remote trusted hardware. It then
+ * sends it to the framework, where it is decrypted using the user's lock screen from their previous
+ * device.
+ *
+ * @hide
+ */
+public final class KeychainSnapshot implements Parcelable {
+ private static final int DEFAULT_MAX_ATTEMPTS = 10;
+ private static final long DEFAULT_COUNTER_ID = 1L;
+
+ private int mSnapshotVersion;
+ private int mMaxAttempts = DEFAULT_MAX_ATTEMPTS;
+ private long mCounterId = DEFAULT_COUNTER_ID;
+ private byte[] mServerParams;
+ private byte[] mPublicKey;
+ private List<KeychainProtectionParams> mKeychainProtectionParams;
+ private List<WrappedApplicationKey> mEntryRecoveryData;
+ private byte[] mEncryptedRecoveryKeyBlob;
+
+ /**
+ * @hide
+ * Deprecated, consider using builder.
+ */
+ public KeychainSnapshot(
+ int snapshotVersion,
+ @NonNull List<KeychainProtectionParams> keychainProtectionParams,
+ @NonNull List<WrappedApplicationKey> wrappedApplicationKeys,
+ @NonNull byte[] encryptedRecoveryKeyBlob) {
+ mSnapshotVersion = snapshotVersion;
+ mKeychainProtectionParams =
+ Preconditions.checkCollectionElementsNotNull(keychainProtectionParams,
+ "keychainProtectionParams");
+ mEntryRecoveryData = Preconditions.checkCollectionElementsNotNull(wrappedApplicationKeys,
+ "wrappedApplicationKeys");
+ mEncryptedRecoveryKeyBlob = Preconditions.checkNotNull(encryptedRecoveryKeyBlob);
+ }
+
+ private KeychainSnapshot() {
+
+ }
+
+ /**
+ * Snapshot version for given account. It is incremented when user secret or list of application
+ * keys changes.
+ */
+ public int getSnapshotVersion() {
+ return mSnapshotVersion;
+ }
+
+ /**
+ * Number of user secret guesses allowed during Keychain recovery.
+ */
+ public int getMaxAttempts() {
+ return mMaxAttempts;
+ }
+
+ /**
+ * CounterId which is rotated together with user secret.
+ */
+ public long getCounterId() {
+ return mCounterId;
+ }
+
+ /**
+ * Server parameters.
+ */
+ public @NonNull byte[] getServerParams() {
+ return mServerParams;
+ }
+
+ /**
+ * Public key used to encrypt {@code encryptedRecoveryKeyBlob}.
+ *
+ * See implementation for binary key format
+ */
+ // TODO: document key format.
+ public @NonNull byte[] getTrustedHardwarePublicKey() {
+ return mPublicKey;
+ }
+
+ /**
+ * UI and key derivation parameters. Note that combination of secrets may be used.
+ */
+ public @NonNull List<KeychainProtectionParams> getKeychainProtectionParams() {
+ return mKeychainProtectionParams;
+ }
+
+ /**
+ * List of application keys, with key material encrypted by
+ * the recovery key ({@link #getEncryptedRecoveryKeyBlob}).
+ */
+ public @NonNull List<WrappedApplicationKey> getWrappedApplicationKeys() {
+ return mEntryRecoveryData;
+ }
+
+ /**
+ * Recovery key blob, encrypted by user secret and recovery service public key.
+ */
+ public @NonNull byte[] getEncryptedRecoveryKeyBlob() {
+ return mEncryptedRecoveryKeyBlob;
+ }
+
+ public static final Creator<KeychainSnapshot> CREATOR =
+ new Creator<KeychainSnapshot>() {
+ public KeychainSnapshot createFromParcel(Parcel in) {
+ return new KeychainSnapshot(in);
+ }
+
+ public KeychainSnapshot[] newArray(int length) {
+ return new KeychainSnapshot[length];
+ }
+ };
+
+ /**
+ * Builder for creating {@link KeychainSnapshot}.
+ */
+ public static class Builder {
+ private KeychainSnapshot
+ mInstance = new KeychainSnapshot();
+
+ /**
+ * Snapshot version for given account.
+ *
+ * @param snapshotVersion The snapshot version
+ * @return This builder.
+ */
+ public Builder setSnapshotVersion(int snapshotVersion) {
+ mInstance.mSnapshotVersion = snapshotVersion;
+ return this;
+ }
+
+ /**
+ * Sets the number of user secret guesses allowed during Keychain recovery.
+ *
+ * @param maxAttempts The maximum number of guesses.
+ * @return This builder.
+ */
+ public Builder setMaxAttempts(int maxAttempts) {
+ mInstance.mMaxAttempts = maxAttempts;
+ return this;
+ }
+
+ /**
+ * Sets counter id.
+ *
+ * @param counterId The counter id.
+ * @return This builder.
+ */
+ public Builder setCounterId(long counterId) {
+ mInstance.mCounterId = counterId;
+ return this;
+ }
+
+ /**
+ * Sets server parameters.
+ *
+ * @param serverParams The server parameters
+ * @return This builder.
+ */
+ public Builder setServerParams(byte[] serverParams) {
+ mInstance.mServerParams = serverParams;
+ return this;
+ }
+
+ /**
+ * Sets public key used to encrypt recovery blob.
+ *
+ * @param publicKey The public key
+ * @return This builder.
+ */
+ public Builder setTrustedHardwarePublicKey(byte[] publicKey) {
+ mInstance.mPublicKey = publicKey;
+ return this;
+ }
+
+ /**
+ * Sets UI and key derivation parameters
+ *
+ * @param recoveryMetadata The UI and key derivation parameters
+ * @return This builder.
+ */
+ public Builder setKeychainProtectionParams(
+ @NonNull List<KeychainProtectionParams> recoveryMetadata) {
+ mInstance.mKeychainProtectionParams = recoveryMetadata;
+ return this;
+ }
+
+ /**
+ * List of application keys.
+ *
+ * @param entryRecoveryData List of application keys
+ * @return This builder.
+ */
+ public Builder setWrappedApplicationKeys(List<WrappedApplicationKey> entryRecoveryData) {
+ mInstance.mEntryRecoveryData = entryRecoveryData;
+ return this;
+ }
+
+ /**
+ * Sets recovery key blob
+ *
+ * @param encryptedRecoveryKeyBlob The recovery key blob.
+ * @return This builder.
+ */
+ public Builder setEncryptedRecoveryKeyBlob(@NonNull byte[] encryptedRecoveryKeyBlob) {
+ mInstance.mEncryptedRecoveryKeyBlob = encryptedRecoveryKeyBlob;
+ return this;
+ }
+
+
+ /**
+ * Creates a new {@link KeychainSnapshot} instance.
+ *
+ * @return new instance
+ * @throws NullPointerException if some required fields were not set.
+ */
+ @NonNull public KeychainSnapshot build() {
+ Preconditions.checkCollectionElementsNotNull(mInstance.mKeychainProtectionParams,
+ "recoveryMetadata");
+ Preconditions.checkCollectionElementsNotNull(mInstance.mEntryRecoveryData,
+ "entryRecoveryData");
+ Preconditions.checkNotNull(mInstance.mEncryptedRecoveryKeyBlob);
+ Preconditions.checkNotNull(mInstance.mServerParams);
+ Preconditions.checkNotNull(mInstance.mPublicKey);
+ return mInstance;
+ }
+ }
+
+ /**
+ * @hide
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeInt(mSnapshotVersion);
+ out.writeTypedList(mKeychainProtectionParams);
+ out.writeByteArray(mEncryptedRecoveryKeyBlob);
+ out.writeTypedList(mEntryRecoveryData);
+ out.writeInt(mMaxAttempts);
+ out.writeLong(mCounterId);
+ out.writeByteArray(mServerParams);
+ out.writeByteArray(mPublicKey);
+ }
+
+ /**
+ * @hide
+ */
+ protected KeychainSnapshot(Parcel in) {
+ mSnapshotVersion = in.readInt();
+ mKeychainProtectionParams = in.createTypedArrayList(KeychainProtectionParams.CREATOR);
+ mEncryptedRecoveryKeyBlob = in.createByteArray();
+ mEntryRecoveryData = in.createTypedArrayList(WrappedApplicationKey.CREATOR);
+ mMaxAttempts = in.readInt();
+ mCounterId = in.readLong();
+ mServerParams = in.createByteArray();
+ mPublicKey = in.createByteArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/LockScreenRequiredException.java b/core/java/android/security/keystore/recovery/LockScreenRequiredException.java
new file mode 100644
index 000000000000..ced23685690e
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/LockScreenRequiredException.java
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+/**
+ * Error thrown when trying to generate keys for a profile that has no lock screen set.
+ *
+ * <p>A lock screen must be set, as the lock screen is used to encrypt the snapshot.
+ *
+ * @hide
+ */
+public class LockScreenRequiredException extends RecoveryControllerException {
+ public LockScreenRequiredException(String msg) {
+ super(msg);
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoveryClaim.java b/core/java/android/security/keystore/recovery/RecoveryClaim.java
new file mode 100644
index 000000000000..11385d883a77
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoveryClaim.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+/**
+ * An attempt to recover a keychain protected by remote secure hardware.
+ *
+ * @hide
+ */
+public class RecoveryClaim {
+
+ private final RecoverySession mRecoverySession;
+ private final byte[] mClaimBytes;
+
+ RecoveryClaim(RecoverySession recoverySession, byte[] claimBytes) {
+ mRecoverySession = recoverySession;
+ mClaimBytes = claimBytes;
+ }
+
+ /**
+ * Returns the session associated with the recovery attempt. This is used to match the symmetric
+ * key, which remains internal to the framework, for decrypting the claim response.
+ *
+ * @return The session data.
+ */
+ public RecoverySession getRecoverySession() {
+ return mRecoverySession;
+ }
+
+ /**
+ * Returns the encrypted claim's bytes.
+ *
+ * <p>This should be sent by the recovery agent to the remote secure hardware, which will use
+ * it to decrypt the keychain, before sending it re-encrypted with the session's symmetric key
+ * to the device.
+ */
+ public byte[] getClaimBytes() {
+ return mClaimBytes;
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoveryController.java b/core/java/android/security/keystore/recovery/RecoveryController.java
new file mode 100644
index 000000000000..1908ce22bac2
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoveryController.java
@@ -0,0 +1,535 @@
+/*
+ * 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.security.keystore.recovery;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.PendingIntent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.ServiceSpecificException;
+import android.util.Log;
+
+import com.android.internal.widget.ILockSettings;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * An assistant for generating {@link javax.crypto.SecretKey} instances that can be recovered by
+ * other Android devices belonging to the user. The exported keychain is protected by the user's
+ * lock screen.
+ *
+ * <p>The RecoveryController must be paired with a recovery agent. The recovery agent is responsible
+ * for transporting the keychain to remote trusted hardware. This hardware must prevent brute force
+ * attempts against the user's lock screen by limiting the number of allowed guesses (to, e.g., 10).
+ * After that number of incorrect guesses, the trusted hardware no longer allows access to the
+ * key chain.
+ *
+ * <p>For now only the recovery agent itself is able to create keys, so it is expected that the
+ * recovery agent is itself the system app.
+ *
+ * <p>A recovery agent requires the privileged permission
+ * {@code android.Manifest.permission#RECOVER_KEYSTORE}.
+ *
+ * @hide
+ */
+public class RecoveryController {
+ private static final String TAG = "RecoveryController";
+
+ /** Key has been successfully synced. */
+ public static final int RECOVERY_STATUS_SYNCED = 0;
+ /** Waiting for recovery agent to sync the key. */
+ public static final int RECOVERY_STATUS_SYNC_IN_PROGRESS = 1;
+ /** Recovery account is not available. */
+ public static final int RECOVERY_STATUS_MISSING_ACCOUNT = 2;
+ /** Key cannot be synced. */
+ public static final int RECOVERY_STATUS_PERMANENT_FAILURE = 3;
+
+ /**
+ * Failed because no snapshot is yet pending to be synced for the user.
+ *
+ * @hide
+ */
+ public static final int ERROR_NO_SNAPSHOT_PENDING = 21;
+
+ /**
+ * Failed due to an error internal to the recovery service. This is unexpected and indicates
+ * either a problem with the logic in the service, or a problem with a dependency of the
+ * service (such as AndroidKeyStore).
+ *
+ * @hide
+ */
+ public static final int ERROR_SERVICE_INTERNAL_ERROR = 22;
+
+ /**
+ * Failed because the user does not have a lock screen set.
+ *
+ * @hide
+ */
+ public static final int ERROR_INSECURE_USER = 23;
+
+ /**
+ * Error thrown when attempting to use a recovery session that has since been closed.
+ *
+ * @hide
+ */
+ public static final int ERROR_SESSION_EXPIRED = 24;
+
+ /**
+ * Failed because the provided certificate was not a valid X509 certificate.
+ *
+ * @hide
+ */
+ public static final int ERROR_BAD_CERTIFICATE_FORMAT = 25;
+
+ /**
+ * Error thrown if decryption failed. This might be because the tag is wrong, the key is wrong,
+ * the data has become corrupted, the data has been tampered with, etc.
+ *
+ * @hide
+ */
+ public static final int ERROR_DECRYPTION_FAILED = 26;
+
+
+ private final ILockSettings mBinder;
+
+ private RecoveryController(ILockSettings binder) {
+ mBinder = binder;
+ }
+
+ /**
+ * Gets a new instance of the class.
+ */
+ public static RecoveryController getInstance() {
+ ILockSettings lockSettings =
+ ILockSettings.Stub.asInterface(ServiceManager.getService("lock_settings"));
+ return new RecoveryController(lockSettings);
+ }
+
+ /**
+ * Initializes key recovery service for the calling application. RecoveryController
+ * randomly chooses one of the keys from the list and keeps it to use for future key export
+ * operations. Collection of all keys in the list must be signed by the provided {@code
+ * rootCertificateAlias}, which must also be present in the list of root certificates
+ * preinstalled on the device. The random selection allows RecoveryController to select
+ * which of a set of remote recovery service devices will be used.
+ *
+ * <p>In addition, RecoveryController enforces a delay of three months between
+ * consecutive initialization attempts, to limit the ability of an attacker to often switch
+ * remote recovery devices and significantly increase number of recovery attempts.
+ *
+ * @param rootCertificateAlias alias of a root certificate preinstalled on the device
+ * @param signedPublicKeyList binary blob a list of X509 certificates and signature
+ * @throws BadCertificateFormatException if the {@code signedPublicKeyList} is in a bad format.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public void initRecoveryService(
+ @NonNull String rootCertificateAlias, @NonNull byte[] signedPublicKeyList)
+ throws BadCertificateFormatException, InternalRecoveryServiceException {
+ try {
+ mBinder.initRecoveryService(rootCertificateAlias, signedPublicKeyList);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) {
+ throw new BadCertificateFormatException(e.getMessage());
+ }
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Returns data necessary to store all recoverable keys for given account. Key material is
+ * encrypted with user secret and recovery public key.
+ *
+ * @param account specific to Recovery agent.
+ * @return Data necessary to recover keystore.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ @NonNull public KeychainSnapshot getRecoveryData(@NonNull byte[] account)
+ throws InternalRecoveryServiceException {
+ try {
+ return mBinder.getRecoveryData(account);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ERROR_NO_SNAPSHOT_PENDING) {
+ return null;
+ }
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Sets a listener which notifies recovery agent that new recovery snapshot is available. {@link
+ * #getRecoveryData} can be used to get the snapshot. Note that every recovery agent can have at
+ * most one registered listener at any time.
+ *
+ * @param intent triggered when new snapshot is available. Unregisters listener if the value is
+ * {@code null}.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public void setSnapshotCreatedPendingIntent(@Nullable PendingIntent intent)
+ throws InternalRecoveryServiceException {
+ try {
+ mBinder.setSnapshotCreatedPendingIntent(intent);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Returns a map from recovery agent accounts to corresponding KeyStore recovery snapshot
+ * version. Version zero is used, if no snapshots were created for the account.
+ *
+ * @return Map from recovery agent accounts to snapshot versions.
+ * @see KeychainSnapshot#getSnapshotVersion
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public @NonNull Map<byte[], Integer> getRecoverySnapshotVersions()
+ throws InternalRecoveryServiceException {
+ try {
+ // IPC doesn't support generic Maps.
+ @SuppressWarnings("unchecked")
+ Map<byte[], Integer> result =
+ (Map<byte[], Integer>) mBinder.getRecoverySnapshotVersions();
+ return result;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Server parameters used to generate new recovery key blobs. This value will be included in
+ * {@code KeychainSnapshot.getEncryptedRecoveryKeyBlob()}. The same value must be included
+ * in vaultParams {@link #startRecoverySession}
+ *
+ * @param serverParams included in recovery key blob.
+ * @see #getRecoveryData
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public void setServerParams(byte[] serverParams) throws InternalRecoveryServiceException {
+ try {
+ mBinder.setServerParams(serverParams);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Updates recovery status for given keys. It is used to notify keystore that key was
+ * successfully stored on the server or there were an error. Application can check this value
+ * using {@code getRecoveyStatus}.
+ *
+ * @param packageName Application whose recoverable keys' statuses are to be updated.
+ * @param aliases List of application-specific key aliases. If the array is empty, updates the
+ * status for all existing recoverable keys.
+ * @param status Status specific to recovery agent.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public void setRecoveryStatus(
+ @NonNull String packageName, @Nullable String[] aliases, int status)
+ throws NameNotFoundException, InternalRecoveryServiceException {
+ try {
+ mBinder.setRecoveryStatus(packageName, aliases, status);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Returns a {@code Map} from Application's KeyStore key aliases to their recovery status.
+ * Negative status values are reserved for recovery agent specific codes. List of common codes:
+ *
+ * <ul>
+ * <li>{@link #RECOVERY_STATUS_SYNCED}
+ * <li>{@link #RECOVERY_STATUS_SYNC_IN_PROGRESS}
+ * <li>{@link #RECOVERY_STATUS_MISSING_ACCOUNT}
+ * <li>{@link #RECOVERY_STATUS_PERMANENT_FAILURE}
+ * </ul>
+ *
+ * @return {@code Map} from KeyStore alias to recovery status.
+ * @see #setRecoveryStatus
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public Map<String, Integer> getRecoveryStatus() throws InternalRecoveryServiceException {
+ try {
+ // IPC doesn't support generic Maps.
+ @SuppressWarnings("unchecked")
+ Map<String, Integer> result =
+ (Map<String, Integer>) mBinder.getRecoveryStatus(/*packageName=*/ null);
+ return result;
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Specifies a set of secret types used for end-to-end keystore encryption. Knowing all of them
+ * is necessary to recover data.
+ *
+ * @param secretTypes {@link KeychainProtectionParams#TYPE_LOCKSCREEN} or {@link
+ * KeychainProtectionParams#TYPE_CUSTOM_PASSWORD}
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public void setRecoverySecretTypes(
+ @NonNull @KeychainProtectionParams.UserSecretType int[] secretTypes)
+ throws InternalRecoveryServiceException {
+ try {
+ mBinder.setRecoverySecretTypes(secretTypes);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Defines a set of secret types used for end-to-end keystore encryption. Knowing all of them is
+ * necessary to generate KeychainSnapshot.
+ *
+ * @return list of recovery secret types
+ * @see KeychainSnapshot
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public @NonNull @KeychainProtectionParams.UserSecretType int[] getRecoverySecretTypes()
+ throws InternalRecoveryServiceException {
+ try {
+ return mBinder.getRecoverySecretTypes();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Returns a list of recovery secret types, necessary to create a pending recovery snapshot.
+ * When user enters a secret of a pending type {@link #recoverySecretAvailable} should be
+ * called.
+ *
+ * @return list of recovery secret types
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ @NonNull
+ public @KeychainProtectionParams.UserSecretType int[] getPendingRecoverySecretTypes()
+ throws InternalRecoveryServiceException {
+ try {
+ return mBinder.getPendingRecoverySecretTypes();
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Method notifies KeyStore that a user-generated secret is available. This method generates a
+ * symmetric session key which a trusted remote device can use to return a recovery key. Caller
+ * should use {@link KeychainProtectionParams#clearSecret} to override the secret value in
+ * memory.
+ *
+ * @param recoverySecret user generated secret together with parameters necessary to regenerate
+ * it on a new device.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public void recoverySecretAvailable(@NonNull KeychainProtectionParams recoverySecret)
+ throws InternalRecoveryServiceException {
+ try {
+ mBinder.recoverySecretAvailable(recoverySecret);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Initializes recovery session and returns a blob with proof of recovery secrets possession.
+ * The method generates symmetric key for a session, which trusted remote device can use to
+ * return recovery key.
+ *
+ * @param verifierPublicKey Encoded {@code java.security.cert.X509Certificate} with Public key
+ * used to create the recovery blob on the source device.
+ * Keystore will verify the certificate using root of trust.
+ * @param vaultParams Must match the parameters in the corresponding field in the recovery blob.
+ * Used to limit number of guesses.
+ * @param vaultChallenge Data passed from server for this recovery session and used to prevent
+ * replay attacks
+ * @param secrets Secrets provided by user, the method only uses type and secret fields.
+ * @return The recovery claim. Claim provides a b binary blob with recovery claim. It is
+ * encrypted with verifierPublicKey and contains a proof of user secrets, session symmetric
+ * key and parameters necessary to identify the counter with the number of failed recovery
+ * attempts.
+ * @throws BadCertificateFormatException if the {@code verifierPublicKey} is in an incorrect
+ * format.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ @NonNull public RecoveryClaim startRecoverySession(
+ @NonNull byte[] verifierPublicKey,
+ @NonNull byte[] vaultParams,
+ @NonNull byte[] vaultChallenge,
+ @NonNull List<KeychainProtectionParams> secrets)
+ throws BadCertificateFormatException, InternalRecoveryServiceException {
+ try {
+ RecoverySession recoverySession = RecoverySession.newInstance(this);
+ byte[] recoveryClaim =
+ mBinder.startRecoverySession(
+ recoverySession.getSessionId(),
+ verifierPublicKey,
+ vaultParams,
+ vaultChallenge,
+ secrets);
+ return new RecoveryClaim(recoverySession, recoveryClaim);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ERROR_BAD_CERTIFICATE_FORMAT) {
+ throw new BadCertificateFormatException(e.getMessage());
+ }
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Imports keys.
+ *
+ * @param session Related recovery session, as originally created by invoking
+ * {@link #startRecoverySession(byte[], byte[], byte[], List)}.
+ * @param recoveryKeyBlob Recovery blob encrypted by symmetric key generated for this session.
+ * @param applicationKeys Application keys. Key material can be decrypted using recoveryKeyBlob
+ * and session. KeyStore only uses package names from the application info in {@link
+ * WrappedApplicationKey}. Caller is responsibility to perform certificates check.
+ * @return Map from alias to raw key material.
+ * @throws SessionExpiredException if {@code session} has since been closed.
+ * @throws DecryptionFailedException if unable to decrypt the snapshot.
+ * @throws InternalRecoveryServiceException if an error occurs internal to the recovery service.
+ */
+ public Map<String, byte[]> recoverKeys(
+ @NonNull RecoverySession session,
+ @NonNull byte[] recoveryKeyBlob,
+ @NonNull List<WrappedApplicationKey> applicationKeys)
+ throws SessionExpiredException, DecryptionFailedException,
+ InternalRecoveryServiceException {
+ try {
+ return (Map<String, byte[]>) mBinder.recoverKeys(
+ session.getSessionId(), recoveryKeyBlob, applicationKeys);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ERROR_DECRYPTION_FAILED) {
+ throw new DecryptionFailedException(e.getMessage());
+ }
+ if (e.errorCode == ERROR_SESSION_EXPIRED) {
+ throw new SessionExpiredException(e.getMessage());
+ }
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Deletes all data associated with {@code session}. Should not be invoked directly but via
+ * {@link RecoverySession#close()}.
+ *
+ * @hide
+ */
+ void closeSession(RecoverySession session) {
+ try {
+ mBinder.closeSession(session.getSessionId());
+ } catch (RemoteException | ServiceSpecificException e) {
+ Log.e(TAG, "Unexpected error trying to close session", e);
+ }
+ }
+
+ /**
+ * Generates a key called {@code alias} and loads it into the recoverable key store. Returns the
+ * raw material of the key.
+ *
+ * @param alias The key alias.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ * @throws LockScreenRequiredException if the user has not set a lock screen. This is required
+ * to generate recoverable keys, as the snapshots are encrypted using a key derived from the
+ * lock screen.
+ */
+ public byte[] generateAndStoreKey(@NonNull String alias)
+ throws InternalRecoveryServiceException, LockScreenRequiredException {
+ try {
+ return mBinder.generateAndStoreKey(alias);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ if (e.errorCode == ERROR_INSECURE_USER) {
+ throw new LockScreenRequiredException(e.getMessage());
+ }
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ /**
+ * Removes a key called {@code alias} from the recoverable key store.
+ *
+ * @param alias The key alias.
+ * @throws InternalRecoveryServiceException if an unexpected error occurred in the recovery
+ * service.
+ */
+ public void removeKey(@NonNull String alias) throws InternalRecoveryServiceException {
+ try {
+ mBinder.removeKey(alias);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ } catch (ServiceSpecificException e) {
+ throw wrapUnexpectedServiceSpecificException(e);
+ }
+ }
+
+ private InternalRecoveryServiceException wrapUnexpectedServiceSpecificException(
+ ServiceSpecificException e) {
+ if (e.errorCode == ERROR_SERVICE_INTERNAL_ERROR) {
+ return new InternalRecoveryServiceException(e.getMessage());
+ }
+
+ // Should never happen. If it does, it's a bug, and we need to update how the method that
+ // called this throws its exceptions.
+ return new InternalRecoveryServiceException("Unexpected error code for method: "
+ + e.errorCode, e);
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoveryControllerException.java b/core/java/android/security/keystore/recovery/RecoveryControllerException.java
new file mode 100644
index 000000000000..0fb7c07edd5b
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoveryControllerException.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+import java.security.GeneralSecurityException;
+
+/**
+ * Base exception for errors thrown by {@link RecoveryController}.
+ *
+ * @hide
+ */
+public abstract class RecoveryControllerException extends GeneralSecurityException {
+ RecoveryControllerException() { }
+
+ RecoveryControllerException(String msg) {
+ super(msg);
+ }
+
+ public RecoveryControllerException(String message, Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/RecoverySession.java b/core/java/android/security/keystore/recovery/RecoverySession.java
new file mode 100644
index 000000000000..89f894529739
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/RecoverySession.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+import java.security.SecureRandom;
+
+/**
+ * Session to recover a {@link KeychainSnapshot} from the remote trusted hardware, initiated by a
+ * recovery agent.
+ *
+ * @hide
+ */
+public class RecoverySession implements AutoCloseable {
+
+ private static final int SESSION_ID_LENGTH_BYTES = 16;
+
+ private final String mSessionId;
+ private final RecoveryController mRecoveryController;
+
+ private RecoverySession(RecoveryController recoveryController, String sessionId) {
+ mRecoveryController = recoveryController;
+ mSessionId = sessionId;
+ }
+
+ /**
+ * A new session, started by {@code recoveryManager}.
+ */
+ static RecoverySession newInstance(RecoveryController recoveryController) {
+ return new RecoverySession(recoveryController, newSessionId());
+ }
+
+ /**
+ * Returns a new random session ID.
+ */
+ private static String newSessionId() {
+ SecureRandom secureRandom = new SecureRandom();
+ byte[] sessionId = new byte[SESSION_ID_LENGTH_BYTES];
+ secureRandom.nextBytes(sessionId);
+ StringBuilder sb = new StringBuilder();
+ for (byte b : sessionId) {
+ sb.append(Byte.toHexString(b, /*upperCase=*/ false));
+ }
+ return sb.toString();
+ }
+
+ /**
+ * An internal session ID, used by the framework to match recovery claims to snapshot responses.
+ */
+ String getSessionId() {
+ return mSessionId;
+ }
+
+ @Override
+ public void close() {
+ mRecoveryController.closeSession(this);
+ }
+}
diff --git a/core/java/android/security/keystore/recovery/SessionExpiredException.java b/core/java/android/security/keystore/recovery/SessionExpiredException.java
new file mode 100644
index 000000000000..7fc2b0560d69
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/SessionExpiredException.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2018 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.security.keystore.recovery;
+
+/**
+ * Error thrown when attempting to use a {@link RecoverySession} that has since expired.
+ *
+ * @hide
+ */
+public class SessionExpiredException extends RecoveryControllerException {
+ public SessionExpiredException(String msg) {
+ super(msg);
+ }
+}
diff --git a/core/java/android/security/keystore/WrappedApplicationKey.aidl b/core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl
index a6294fee03b3..b2d1ae461346 100644
--- a/core/java/android/security/keystore/WrappedApplicationKey.aidl
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.security.keystore;
+package android.security.keystore.recovery;
/* @hide */
parcelable WrappedApplicationKey;
diff --git a/core/java/android/security/keystore/recovery/WrappedApplicationKey.java b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
new file mode 100644
index 000000000000..bca03b389e43
--- /dev/null
+++ b/core/java/android/security/keystore/recovery/WrappedApplicationKey.java
@@ -0,0 +1,145 @@
+/*
+ * 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.security.keystore.recovery;
+
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.Preconditions;
+
+/**
+ * Helper class with data necessary recover a single application key, given a recovery key.
+ *
+ * <ul>
+ * <li>Alias - Keystore alias of the key.
+ * <li>Encrypted key material.
+ * </ul>
+ *
+ * Note that Application info is not included. Recovery Agent can only make its own keys
+ * recoverable.
+ *
+ * @hide
+ */
+public final class WrappedApplicationKey implements Parcelable {
+ private String mAlias;
+ // The only supported format is AES-256 symmetric key.
+ private byte[] mEncryptedKeyMaterial;
+
+ /**
+ * Builder for creating {@link WrappedApplicationKey}.
+ */
+ public static class Builder {
+ private WrappedApplicationKey
+ mInstance = new WrappedApplicationKey();
+
+ /**
+ * Sets Application-specific alias of the key.
+ *
+ * @param alias The alias.
+ * @return This builder.
+ */
+ public Builder setAlias(@NonNull String alias) {
+ mInstance.mAlias = alias;
+ return this;
+ }
+
+ /**
+ * Sets key material encrypted by recovery key.
+ *
+ * @param encryptedKeyMaterial The key material
+ * @return This builder
+ */
+
+ public Builder setEncryptedKeyMaterial(@NonNull byte[] encryptedKeyMaterial) {
+ mInstance.mEncryptedKeyMaterial = encryptedKeyMaterial;
+ return this;
+ }
+
+ /**
+ * Creates a new {@link WrappedApplicationKey} instance.
+ *
+ * @return new instance
+ * @throws NullPointerException if some required fields were not set.
+ */
+ @NonNull public WrappedApplicationKey build() {
+ Preconditions.checkNotNull(mInstance.mAlias);
+ Preconditions.checkNotNull(mInstance.mEncryptedKeyMaterial);
+ return mInstance;
+ }
+ }
+
+ private WrappedApplicationKey() {
+
+ }
+
+ /**
+ * Deprecated - consider using Builder.
+ * @hide
+ */
+ public WrappedApplicationKey(@NonNull String alias, @NonNull byte[] encryptedKeyMaterial) {
+ mAlias = Preconditions.checkNotNull(alias);
+ mEncryptedKeyMaterial = Preconditions.checkNotNull(encryptedKeyMaterial);
+ }
+
+ /**
+ * Application-specific alias of the key.
+ *
+ * @see java.security.KeyStore.aliases
+ */
+ public @NonNull String getAlias() {
+ return mAlias;
+ }
+
+ /** Key material encrypted by recovery key. */
+ public @NonNull byte[] getEncryptedKeyMaterial() {
+ return mEncryptedKeyMaterial;
+ }
+
+ public static final Creator<WrappedApplicationKey> CREATOR =
+ new Creator<WrappedApplicationKey>() {
+ public WrappedApplicationKey createFromParcel(Parcel in) {
+ return new WrappedApplicationKey(in);
+ }
+
+ public WrappedApplicationKey[] newArray(int length) {
+ return new WrappedApplicationKey[length];
+ }
+ };
+
+ /**
+ * @hide
+ */
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeString(mAlias);
+ out.writeByteArray(mEncryptedKeyMaterial);
+ }
+
+ /**
+ * @hide
+ */
+ protected WrappedApplicationKey(Parcel in) {
+ mAlias = in.readString();
+ mEncryptedKeyMaterial = in.createByteArray();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+}
diff --git a/core/java/android/util/apk/ApkSignatureVerifier.java b/core/java/android/util/apk/ApkSignatureVerifier.java
index a2a76169c83a..87943725ba21 100644
--- a/core/java/android/util/apk/ApkSignatureVerifier.java
+++ b/core/java/android/util/apk/ApkSignatureVerifier.java
@@ -80,10 +80,22 @@ public class ApkSignatureVerifier {
ApkSignatureSchemeV3Verifier.verify(apkPath);
Certificate[][] signerCerts = new Certificate[][] { vSigner.certs };
Signature[] signerSigs = convertToSignatures(signerCerts);
- return new PackageParser.SigningDetails(signerSigs,
- SignatureSchemeVersion.SIGNING_BLOCK_V3);
+ Signature[] pastSignerSigs = null;
+ int[] pastSignerSigsFlags = null;
+ if (vSigner.por != null) {
+ // populate proof-of-rotation information
+ pastSignerSigs = new Signature[vSigner.por.certs.size()];
+ pastSignerSigsFlags = new int[vSigner.por.flagsList.size()];
+ for (int i = 0; i < pastSignerSigs.length; i++) {
+ pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded());
+ pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i);
+ }
+ }
+ return new PackageParser.SigningDetails(
+ signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3,
+ pastSignerSigs, pastSignerSigsFlags);
} catch (SignatureNotFoundException e) {
- // not signed with v2, try older if allowed
+ // not signed with v3, try older if allowed
if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
"No APK Signature Scheme v3 signature in package " + apkPath, e);
@@ -92,7 +104,7 @@ public class ApkSignatureVerifier {
// APK Signature Scheme v2 signature found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
"Failed to collect certificates from " + apkPath
- + " using APK Signature Scheme v2", e);
+ + " using APK Signature Scheme v3", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
@@ -304,25 +316,37 @@ public class ApkSignatureVerifier {
}
// first try v3
- Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "verifyV3");
+ Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "certsOnlyV3");
try {
ApkSignatureSchemeV3Verifier.VerifiedSigner vSigner =
ApkSignatureSchemeV3Verifier.plsCertsNoVerifyOnlyCerts(apkPath);
Certificate[][] signerCerts = new Certificate[][] { vSigner.certs };
Signature[] signerSigs = convertToSignatures(signerCerts);
- return new PackageParser.SigningDetails(signerSigs,
- SignatureSchemeVersion.SIGNING_BLOCK_V3);
+ Signature[] pastSignerSigs = null;
+ int[] pastSignerSigsFlags = null;
+ if (vSigner.por != null) {
+ // populate proof-of-rotation information
+ pastSignerSigs = new Signature[vSigner.por.certs.size()];
+ pastSignerSigsFlags = new int[vSigner.por.flagsList.size()];
+ for (int i = 0; i < pastSignerSigs.length; i++) {
+ pastSignerSigs[i] = new Signature(vSigner.por.certs.get(i).getEncoded());
+ pastSignerSigsFlags[i] = vSigner.por.flagsList.get(i);
+ }
+ }
+ return new PackageParser.SigningDetails(
+ signerSigs, SignatureSchemeVersion.SIGNING_BLOCK_V3,
+ pastSignerSigs, pastSignerSigsFlags);
} catch (SignatureNotFoundException e) {
- // not signed with v2, try older if allowed
+ // not signed with v3, try older if allowed
if (minSignatureSchemeVersion >= SignatureSchemeVersion.SIGNING_BLOCK_V3) {
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
"No APK Signature Scheme v3 signature in package " + apkPath, e);
}
} catch (Exception e) {
- // APK Signature Scheme v2 signature found but did not verify
+ // APK Signature Scheme v3 signature found but did not verify
throw new PackageParserException(INSTALL_PARSE_FAILED_NO_CERTIFICATES,
"Failed to collect certificates from " + apkPath
- + " using APK Signature Scheme v2", e);
+ + " using APK Signature Scheme v3", e);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 176927fef0eb..95abea14b1dd 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -2244,9 +2244,36 @@ public abstract class Window {
* <p>
* The transitionName for the view background will be "android:navigation:background".
* </p>
+ * @attr ref android.R.styleable#Window_navigationBarColor
*/
public abstract void setNavigationBarColor(@ColorInt int color);
+ /**
+ * Shows a thin line of the specified color between the navigation bar and the app
+ * content.
+ * <p>
+ * For this to take effect,
+ * the window must be drawing the system bar backgrounds with
+ * {@link android.view.WindowManager.LayoutParams#FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS} and
+ * {@link android.view.WindowManager.LayoutParams#FLAG_TRANSLUCENT_NAVIGATION} must not be set.
+ *
+ * @param dividerColor The color of the thin line.
+ * @attr ref android.R.styleable#Window_navigationBarDividerColor
+ */
+ public void setNavigationBarDividerColor(@ColorInt int dividerColor) {
+ }
+
+ /**
+ * Retrieves the color of the navigation bar divider.
+ *
+ * @return The color of the navigation bar divider color.
+ * @see #setNavigationBarColor(int)
+ * @attr ref android.R.styleable#Window_navigationBarDividerColor
+ */
+ public @ColorInt int getNavigationBarDividerColor() {
+ return 0;
+ }
+
/** @hide */
public void setTheme(int resId) {
}
diff --git a/core/java/android/view/animation/AnimationUtils.java b/core/java/android/view/animation/AnimationUtils.java
index f5c36139df0f..990fbdb019d6 100644
--- a/core/java/android/view/animation/AnimationUtils.java
+++ b/core/java/android/view/animation/AnimationUtils.java
@@ -156,6 +156,8 @@ public class AnimationUtils {
anim = new RotateAnimation(c, attrs);
} else if (name.equals("translate")) {
anim = new TranslateAnimation(c, attrs);
+ } else if (name.equals("cliprect")) {
+ anim = new ClipRectAnimation(c, attrs);
} else {
throw new RuntimeException("Unknown animation name: " + parser.getName());
}
diff --git a/core/java/android/view/animation/ClipRectAnimation.java b/core/java/android/view/animation/ClipRectAnimation.java
index e194927e8301..21509d3a1159 100644
--- a/core/java/android/view/animation/ClipRectAnimation.java
+++ b/core/java/android/view/animation/ClipRectAnimation.java
@@ -16,7 +16,11 @@
package android.view.animation;
+import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.DisplayMetrics;
/**
* An animation that controls the clip of an object. See the
@@ -26,8 +30,84 @@ import android.graphics.Rect;
* @hide
*/
public class ClipRectAnimation extends Animation {
- protected Rect mFromRect = new Rect();
- protected Rect mToRect = new Rect();
+ protected final Rect mFromRect = new Rect();
+ protected final Rect mToRect = new Rect();
+
+ private int mFromLeftType = ABSOLUTE;
+ private int mFromTopType = ABSOLUTE;
+ private int mFromRightType = ABSOLUTE;
+ private int mFromBottomType = ABSOLUTE;
+
+ private int mToLeftType = ABSOLUTE;
+ private int mToTopType = ABSOLUTE;
+ private int mToRightType = ABSOLUTE;
+ private int mToBottomType = ABSOLUTE;
+
+ private float mFromLeftValue;
+ private float mFromTopValue;
+ private float mFromRightValue;
+ private float mFromBottomValue;
+
+ private float mToLeftValue;
+ private float mToTopValue;
+ private float mToRightValue;
+ private float mToBottomValue;
+
+ /**
+ * Constructor used when a ClipRectAnimation is loaded from a resource.
+ *
+ * @param context Application context to use
+ * @param attrs Attribute set from which to read values
+ */
+ public ClipRectAnimation(Context context, AttributeSet attrs) {
+ super(context, attrs);
+
+ TypedArray a = context.obtainStyledAttributes(attrs,
+ com.android.internal.R.styleable.ClipRectAnimation);
+
+ Description d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_fromLeft));
+ mFromLeftType = d.type;
+ mFromLeftValue = d.value;
+
+ d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_fromTop));
+ mFromTopType = d.type;
+ mFromTopValue = d.value;
+
+ d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_fromRight));
+ mFromRightType = d.type;
+ mFromRightValue = d.value;
+
+ d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_fromBottom));
+ mFromBottomType = d.type;
+ mFromBottomValue = d.value;
+
+
+ d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_toLeft));
+ mToLeftType = d.type;
+ mToLeftValue = d.value;
+
+ d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_toTop));
+ mToTopType = d.type;
+ mToTopValue = d.value;
+
+ d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_toRight));
+ mToRightType = d.type;
+ mToRightValue = d.value;
+
+ d = Description.parseValue(a.peekValue(
+ com.android.internal.R.styleable.ClipRectAnimation_toBottom));
+ mToBottomType = d.type;
+ mToBottomValue = d.value;
+
+ a.recycle();
+ }
/**
* Constructor to use when building a ClipRectAnimation from code
@@ -39,8 +119,15 @@ public class ClipRectAnimation extends Animation {
if (fromClip == null || toClip == null) {
throw new RuntimeException("Expected non-null animation clip rects");
}
- mFromRect.set(fromClip);
- mToRect.set(toClip);
+ mFromLeftValue = fromClip.left;
+ mFromTopValue = fromClip.top;
+ mFromRightValue= fromClip.right;
+ mFromBottomValue = fromClip.bottom;
+
+ mToLeftValue = toClip.left;
+ mToTopValue = toClip.top;
+ mToRightValue= toClip.right;
+ mToBottomValue = toClip.bottom;
}
/**
@@ -48,8 +135,7 @@ public class ClipRectAnimation extends Animation {
*/
public ClipRectAnimation(int fromL, int fromT, int fromR, int fromB,
int toL, int toT, int toR, int toB) {
- mFromRect.set(fromL, fromT, fromR, fromB);
- mToRect.set(toL, toT, toR, toB);
+ this(new Rect(fromL, fromT, fromR, fromB), new Rect(toL, toT, toR, toB));
}
@Override
@@ -65,4 +151,17 @@ public class ClipRectAnimation extends Animation {
public boolean willChangeTransformationMatrix() {
return false;
}
+
+ @Override
+ public void initialize(int width, int height, int parentWidth, int parentHeight) {
+ super.initialize(width, height, parentWidth, parentHeight);
+ mFromRect.set((int) resolveSize(mFromLeftType, mFromLeftValue, width, parentWidth),
+ (int) resolveSize(mFromTopType, mFromTopValue, height, parentHeight),
+ (int) resolveSize(mFromRightType, mFromRightValue, width, parentWidth),
+ (int) resolveSize(mFromBottomType, mFromBottomValue, height, parentHeight));
+ mToRect.set((int) resolveSize(mToLeftType, mToLeftValue, width, parentWidth),
+ (int) resolveSize(mToTopType, mToTopValue, height, parentHeight),
+ (int) resolveSize(mToRightType, mToRightValue, width, parentWidth),
+ (int) resolveSize(mToBottomType, mToBottomValue, height, parentHeight));
+ }
}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index b1c45f729fcb..039b66d4cd7d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6947,6 +6947,8 @@ public class BatteryStatsImpl extends BatteryStats {
WIFI_MULTICAST_ENABLED, mBsi.mWifiMulticastTimers, mBsi.mOnBatteryTimeBase);
}
mWifiMulticastTimer.startRunningLocked(elapsedRealtimeMs);
+ StatsLog.write_non_chained(
+ StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, 1);
}
}
@@ -6955,6 +6957,8 @@ public class BatteryStatsImpl extends BatteryStats {
if (mWifiMulticastEnabled) {
mWifiMulticastEnabled = false;
mWifiMulticastTimer.stopRunningLocked(elapsedRealtimeMs);
+ StatsLog.write_non_chained(
+ StatsLog.WIFI_MULTICAST_LOCK_STATE_CHANGED, getUid(), null, 0);
}
}
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index e8ee29dc19f8..34b5ec8149a7 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -3810,6 +3810,19 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ @Override
+ public void setNavigationBarDividerColor(int navigationBarDividerColor) {
+ mNavigationBarDividerColor = navigationBarDividerColor;
+ if (mDecor != null) {
+ mDecor.updateColorViews(null, false /* animate */);
+ }
+ }
+
+ @Override
+ public int getNavigationBarDividerColor() {
+ return mNavigationBarDividerColor;
+ }
+
public void setIsStartingWindow(boolean isStartingWindow) {
mIsStartingWindow = isStartingWindow;
}
diff --git a/core/java/com/android/internal/widget/ILockSettings.aidl b/core/java/com/android/internal/widget/ILockSettings.aidl
index e3f1f472ce5e..f9da1eb26669 100644
--- a/core/java/com/android/internal/widget/ILockSettings.aidl
+++ b/core/java/com/android/internal/widget/ILockSettings.aidl
@@ -19,9 +19,9 @@ package com.android.internal.widget;
import android.app.PendingIntent;
import android.app.trust.IStrongAuthTracker;
import android.os.Bundle;
-import android.security.keystore.WrappedApplicationKey;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.KeychainProtectionParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
+import android.security.keystore.recovery.KeychainSnapshot;
+import android.security.keystore.recovery.KeychainProtectionParams;
import com.android.internal.widget.ICheckCredentialProgressCallback;
import com.android.internal.widget.VerifyCredentialResponse;
diff --git a/core/jni/android_database_SQLiteCommon.cpp b/core/jni/android_database_SQLiteCommon.cpp
index 34544d37a6bf..daa20876ba65 100644
--- a/core/jni/android_database_SQLiteCommon.cpp
+++ b/core/jni/android_database_SQLiteCommon.cpp
@@ -223,8 +223,8 @@ void throw_sqlite3_exception(JNIEnv* env, int errcode,
if (sqlite3Message) {
String8 fullMessage;
fullMessage.append(sqlite3Message);
- const char* errcode_msg = sqlite3_error_code_to_msg(errcode).c_str();
- fullMessage.appendFormat(" (code %s)", errcode_msg); // print extended error code
+ std::string errcode_msg = sqlite3_error_code_to_msg(errcode);
+ fullMessage.appendFormat(" (code %s)", errcode_msg.c_str()); // print extended error code
if (message) {
fullMessage.append(": ");
fullMessage.append(message);
diff --git a/core/res/res/anim/activity_close_enter.xml b/core/res/res/anim/activity_close_enter.xml
index a67b0ca38519..371bcfef7ec9 100644
--- a/core/res/res/anim/activity_close_enter.xml
+++ b/core/res/res/anim/activity_close_enter.xml
@@ -17,9 +17,17 @@
*/
-->
-<set xmlns:android="http://schemas.android.com/apk/res/android" android:zAdjustment="normal">
- <alpha android:fromAlpha="0.7" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/linear_out_slow_in"
- android:duration="250"/>
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shareInterpolator="false">
+ <translate
+ android:fromYDelta="-2%"
+ android:toYDelta="0"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="425"/>
+ <alpha
+ android:fromAlpha="0.9"
+ android:toAlpha="1.0"
+ android:interpolator="@interpolator/activity_close_dim"
+ android:startOffset="0"
+ android:duration="425"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/activity_close_exit.xml b/core/res/res/anim/activity_close_exit.xml
index d8c42ed808f1..143bedb985e1 100644
--- a/core/res/res/anim/activity_close_exit.xml
+++ b/core/res/res/anim/activity_close_exit.xml
@@ -18,15 +18,27 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false" android:zAdjustment="top">
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
- android:interpolator="@interpolator/linear"
- android:fillEnabled="true"
- android:fillBefore="false" android:fillAfter="true"
- android:startOffset="100"
- android:duration="150"/>
- <translate android:fromYDelta="0%" android:toYDelta="8%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_quart"
- android:duration="250"/>
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+ <translate
+ android:fromYDelta="0"
+ android:toYDelta="4.1%"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="425"/>
+ <cliprect
+ android:fromLeft="0%"
+ android:fromTop="0%"
+ android:fromRight="100%"
+ android:fromBottom="100%"
+ android:toLeft="0%"
+ android:toTop="95.9%"
+ android:toRight="100%"
+ android:toBottom="100%"
+ android:interpolator="@interpolator/exaggerated_ease"
+ android:duration="425"/>
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="1.0"
+ android:interpolator="@interpolator/fast_out_linear_in"
+ android:duration="425"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/activity_open_enter.xml b/core/res/res/anim/activity_open_enter.xml
index 1d949d2f7446..f9381b458c20 100644
--- a/core/res/res/anim/activity_open_enter.xml
+++ b/core/res/res/anim/activity_open_enter.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
** Copyright 2009, The Android Open Source Project
**
@@ -18,15 +17,21 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false"
- android:zAdjustment="top">
- <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
- android:interpolator="@interpolator/decelerate_quart"
- android:fillEnabled="true"
- android:fillBefore="false" android:fillAfter="true"
- android:duration="200"/>
- <translate android:fromYDelta="8%" android:toYDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:duration="350"/>
+ android:shareInterpolator="false">
+ <translate
+ android:fromYDelta="4.1%"
+ android:toYDelta="0"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="425"/>
+ <cliprect
+ android:fromLeft="0%"
+ android:fromTop="95.9%"
+ android:fromRight="100%"
+ android:fromBottom="100%"
+ android:toLeft="0%"
+ android:toTop="0%"
+ android:toRight="100%"
+ android:toBottom="100%"
+ android:interpolator="@interpolator/exaggerated_ease"
+ android:duration="425"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/activity_open_exit.xml b/core/res/res/anim/activity_open_exit.xml
index 3a84197f8f63..d52b150391fb 100644
--- a/core/res/res/anim/activity_open_exit.xml
+++ b/core/res/res/anim/activity_open_exit.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
** Copyright 2009, The Android Open Source Project
**
@@ -18,9 +17,15 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:background="#ff000000" android:zAdjustment="normal">
- <alpha android:fromAlpha="1.0" android:toAlpha="0.7"
- android:fillEnabled="true" android:fillBefore="false" android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="217"/>
+ android:shareInterpolator="false">
+ <translate
+ android:fromYDelta="0"
+ android:toYDelta="-2%"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="425"/>
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="0.9"
+ android:interpolator="@interpolator/linear"
+ android:duration="117"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/task_close_enter.xml b/core/res/res/anim/task_close_enter.xml
index bea0ee51d593..81d1300038e3 100644
--- a/core/res/res/anim/task_close_enter.xml
+++ b/core/res/res/anim/task_close_enter.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
** Copyright 2009, The Android Open Source Project
**
@@ -16,27 +15,54 @@
** limitations under the License.
*/
-->
-
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false" android:zAdjustment="normal">
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
+
+ <alpha
+ android:fromAlpha="1"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="67"
+ android:duration="217"/>
- <alpha android:fromAlpha="0.6" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_cubic"
- android:startOffset="600"
- android:duration="133"/>
+ <translate
+ android:fromXDelta="105%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/aggressive_ease"
+ android:startOffset="50"
+ android:duration="383"/>
- <translate android:fromYDelta="10%" android:toYDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_cubic"
- android:startOffset="300"
- android:duration="433" />
+ <scale
+ android:fromXScale="1.0526"
+ android:toXScale="1"
+ android:fromYScale="1.0526"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="283"/>
- <scale android:fromXScale=".9" android:toXScale="1.0"
- android:fromYScale=".9" android:toYScale="1.0"
- android:pivotX="50%p" android:pivotY="0%p"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:startOffset="300"
- android:duration="433" />
+ <scale
+ android:fromXScale="0.95"
+ android:toXScale="1"
+ android:fromYScale="0.95"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:startOffset="283"
+ android:duration="317"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/task_close_exit.xml b/core/res/res/anim/task_close_exit.xml
index b6a08070c3ce..ab8b89ce7b06 100644
--- a/core/res/res/anim/task_close_exit.xml
+++ b/core/res/res/anim/task_close_exit.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
** Copyright 2009, The Android Open Source Project
**
@@ -18,20 +17,44 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false" android:zAdjustment="top">
+ android:shareInterpolator="false">
- <alpha android:fromAlpha="1.0" android:toAlpha="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_quad"
- android:startOffset="250"
- android:duration="167"/>
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="1"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="67"
+ android:duration="283"/>
- <translate android:fromYDelta="0" android:toYDelta="110%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_quint"
- android:duration="417"/>
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="-105%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/aggressive_ease"
+ android:startOffset="50"
+ android:duration="383"/>
+
+ <scale
+ android:fromXScale="1.0"
+ android:toXScale="0.95"
+ android:fromYScale="1.0"
+ android:toYScale="0.95"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="283"/>
<!-- This is needed to keep the animation running while task_open_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="700" />
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="1.0"
+ android:duration="600"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/task_open_enter.xml b/core/res/res/anim/task_open_enter.xml
index b73e14fc637f..2ee7cd86e323 100644
--- a/core/res/res/anim/task_open_enter.xml
+++ b/core/res/res/anim/task_open_enter.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
** Copyright 2009, The Android Open Source Project
**
@@ -15,20 +14,55 @@
** See the License for the specific language governing permissions and
** limitations under the License.
*/
--->
-<!-- This should in sync with task_open_enter_cross_profile_apps.xml -->
+--><!-- This should in sync with task_open_enter_cross_profile_apps.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false" android:zAdjustment="top">
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quart"
- android:startOffset="300"
- android:duration="167"/>
+ <alpha
+ android:fromAlpha="1"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="67"
+ android:duration="217"/>
- <translate android:fromYDelta="110%" android:toYDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="300"
- android:duration="417" />
+ <translate
+ android:fromXDelta="-105%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/aggressive_ease"
+ android:startOffset="50"
+ android:duration="383"/>
+
+ <scale
+ android:fromXScale="1.0526"
+ android:toXScale="1"
+ android:fromYScale="1.0526"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="283"/>
+
+ <scale
+ android:fromXScale="0.95"
+ android:toXScale="1"
+ android:fromYScale="0.95"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:startOffset="283"
+ android:duration="317"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/task_open_enter_cross_profile_apps.xml b/core/res/res/anim/task_open_enter_cross_profile_apps.xml
index ad89fde92065..a92425e89960 100644
--- a/core/res/res/anim/task_open_enter_cross_profile_apps.xml
+++ b/core/res/res/anim/task_open_enter_cross_profile_apps.xml
@@ -18,24 +18,61 @@
-->
<!-- This should in sync with task_open_enter.xml -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false" android:zAdjustment="top">
+ android:shareInterpolator="false"
+ android:zAdjustment="top">
- <alpha android:fromAlpha="0" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quart"
- android:startOffset="300"
- android:duration="167"/>
+ <alpha
+ android:fromAlpha="1"
+ android:toAlpha="1.0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="67"
+ android:duration="217"/>
- <translate android:fromYDelta="110%" android:toYDelta="0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/decelerate_quint"
- android:startOffset="300"
- android:duration="417"/>
+ <translate
+ android:fromXDelta="-105%"
+ android:toXDelta="0"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/aggressive_ease"
+ android:startOffset="50"
+ android:duration="383"/>
+
+ <scale
+ android:fromXScale="1.0526"
+ android:toXScale="1"
+ android:fromYScale="1.0526"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="283"/>
+
+ <scale
+ android:fromXScale="0.95"
+ android:toXScale="1"
+ android:fromYScale="0.95"
+ android:toYScale="1"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:startOffset="283"
+ android:duration="317"/>
<!-- To keep the transition around longer for the thumbnail, should be kept in sync with
cross_profile_apps_thumbmail.xml -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:startOffset="717"
- android:duration="200"/>
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="1.0"
+ android:startOffset="717"
+ android:duration="200"/>
</set> \ No newline at end of file
diff --git a/core/res/res/anim/task_open_exit.xml b/core/res/res/anim/task_open_exit.xml
index 78d0fb015ce3..ecb98ce2cb16 100644
--- a/core/res/res/anim/task_open_exit.xml
+++ b/core/res/res/anim/task_open_exit.xml
@@ -1,5 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
/*
** Copyright 2009, The Android Open Source Project
**
@@ -18,26 +17,44 @@
-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:background="#ff000000" android:shareInterpolator="false" android:zAdjustment="normal">
+ android:shareInterpolator="false">
- <alpha android:fromAlpha="1.0" android:toAlpha="0.6"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_cubic"
- android:duration="133"/>
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="1"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/linear"
+ android:startOffset="67"
+ android:duration="283"/>
- <translate android:fromYDelta="0" android:toYDelta="10%"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/accelerate_cubic"
- android:duration="433"/>
+ <translate
+ android:fromXDelta="0"
+ android:toXDelta="105%"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:interpolator="@interpolator/aggressive_ease"
+ android:startOffset="50"
+ android:duration="383"/>
- <scale android:fromXScale="1.0" android:toXScale="0.9"
- android:fromYScale="1.0" android:toYScale="0.9"
- android:fillEnabled="true" android:fillBefore="true" android:fillAfter="true"
- android:pivotX="50%p" android:pivotY="50%p"
- android:interpolator="@interpolator/fast_out_slow_in"
- android:duration="433" />
+ <scale
+ android:fromXScale="1.0"
+ android:toXScale="0.95"
+ android:fromYScale="1.0"
+ android:toYScale="0.95"
+ android:fillEnabled="true"
+ android:fillBefore="true"
+ android:fillAfter="true"
+ android:pivotX="50%"
+ android:pivotY="50%"
+ android:interpolator="@interpolator/fast_out_slow_in"
+ android:duration="283"/>
<!-- This is needed to keep the animation running while task_open_enter completes -->
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:duration="700" />
+ <alpha
+ android:fromAlpha="1.0"
+ android:toAlpha="1.0"
+ android:duration="600"/>
</set> \ No newline at end of file
diff --git a/core/res/res/interpolator/activity_close_dim.xml b/core/res/res/interpolator/activity_close_dim.xml
new file mode 100644
index 000000000000..faad1399ff49
--- /dev/null
+++ b/core/res/res/interpolator/activity_close_dim.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2018 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
+ -->
+
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:controlX1="0.33"
+ android:controlY1="0"
+ android:controlX2="1"
+ android:controlY2="1"/>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 4eaf93d822b2..4d80b2f0c00b 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2066,7 +2066,8 @@
<p>For this to take effect, the window must be drawing the system bar backgrounds with
{@link android.R.attr#windowDrawsSystemBarBackgrounds} and the navigation bar must not
have been requested to be translucent with
- {@link android.R.attr#windowTranslucentNavigation}. -->
+ {@link android.R.attr#windowTranslucentNavigation}.
+ Corresponds to {@link android.view.Window#setNavigationBarDividerColor(int)}. -->
<attr name="navigationBarDividerColor" format="color" />
<!-- The duration, in milliseconds, of the window background fade duration
@@ -6336,6 +6337,17 @@
<attr name="toAlpha" format="float" />
</declare-styleable>
+ <declare-styleable name="ClipRectAnimation">
+ <attr name="fromLeft" format="fraction" />
+ <attr name="fromTop" format="fraction" />
+ <attr name="fromRight" format="fraction" />
+ <attr name="fromBottom" format="fraction" />
+ <attr name="toLeft" format="fraction" />
+ <attr name="toTop" format="fraction" />
+ <attr name="toRight" format="fraction" />
+ <attr name="toBottom" format="fraction" />
+ </declare-styleable>
+
<declare-styleable name="LayoutAnimation">
<!-- Fraction of the animation duration used to delay the beginning of
the animation of each child. -->
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index 2c4058acc972..35eee6a3b175 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -23,35 +23,60 @@
<item>ak-GH</item> <!-- Akan (Ghana) -->
<item>am-ET</item> <!-- Amharic (Ethiopia) -->
<item>ar-AE</item> <!-- Arabic (United Arab Emirates) -->
+ <item>ar-AE-u-nu-latn</item> <!-- Arabic (United Arab Emirates,Western Digits) -->
<item>ar-BH</item> <!-- Arabic (Bahrain) -->
+ <item>ar-BH-u-nu-latn</item> <!-- Arabic (Bahrain,Western Digits) -->
<item>ar-DJ</item> <!-- Arabic (Djibouti) -->
+ <item>ar-DJ-u-nu-latn</item> <!-- Arabic (Djibouti,Western Digits) -->
<item>ar-DZ</item> <!-- Arabic (Algeria) -->
+ <item>ar-DZ-u-nu-arab</item> <!-- Arabic (Algeria,Arabic-Indic Digits) -->
<item>ar-EG</item> <!-- Arabic (Egypt) -->
<item>ar-EG-u-nu-latn</item> <!-- Arabic (Egypt,Western Digits) -->
<item>ar-EH</item> <!-- Arabic (Western Sahara) -->
+ <item>ar-EH-u-nu-arab</item> <!-- Arabic (Western Sahara,Arabic-Indic Digits) -->
<item>ar-ER</item> <!-- Arabic (Eritrea) -->
+ <item>ar-ER-u-nu-latn</item> <!-- Arabic (Eritrea,Western Digits) -->
<item>ar-IL</item> <!-- Arabic (Israel) -->
+ <item>ar-IL-u-nu-latn</item> <!-- Arabic (Israel,Western Digits) -->
<item>ar-IQ</item> <!-- Arabic (Iraq) -->
+ <item>ar-IQ-u-nu-latn</item> <!-- Arabic (Iraq,Western Digits) -->
<item>ar-JO</item> <!-- Arabic (Jordan) -->
+ <item>ar-JO-u-nu-latn</item> <!-- Arabic (Jordan,Western Digits) -->
<item>ar-KM</item> <!-- Arabic (Comoros) -->
+ <item>ar-KM-u-nu-latn</item> <!-- Arabic (Comoros,Western Digits) -->
<item>ar-KW</item> <!-- Arabic (Kuwait) -->
+ <item>ar-KW-u-nu-latn</item> <!-- Arabic (Kuwait,Western Digits) -->
<item>ar-LB</item> <!-- Arabic (Lebanon) -->
+ <item>ar-LB-u-nu-latn</item> <!-- Arabic (Lebanon,Western Digits) -->
<item>ar-LY</item> <!-- Arabic (Libya) -->
+ <item>ar-LY-u-nu-arab</item> <!-- Arabic (Libya,Arabic-Indic Digits) -->
<item>ar-MA</item> <!-- Arabic (Morocco) -->
+ <item>ar-MA-u-nu-arab</item> <!-- Arabic (Morocco,Arabic-Indic Digits) -->
<item>ar-MR</item> <!-- Arabic (Mauritania) -->
+ <item>ar-MR-u-nu-latn</item> <!-- Arabic (Mauritania,Western Digits) -->
<item>ar-OM</item> <!-- Arabic (Oman) -->
+ <item>ar-OM-u-nu-latn</item> <!-- Arabic (Oman,Western Digits) -->
<item>ar-PS</item> <!-- Arabic (Palestine) -->
+ <item>ar-PS-u-nu-latn</item> <!-- Arabic (Palestine,Western Digits) -->
<item>ar-QA</item> <!-- Arabic (Qatar) -->
+ <item>ar-QA-u-nu-latn</item> <!-- Arabic (Qatar,Western Digits) -->
<item>ar-SA</item> <!-- Arabic (Saudi Arabia) -->
+ <item>ar-SA-u-nu-latn</item> <!-- Arabic (Saudi Arabia,Western Digits) -->
<item>ar-SD</item> <!-- Arabic (Sudan) -->
+ <item>ar-SD-u-nu-latn</item> <!-- Arabic (Sudan,Western Digits) -->
<item>ar-SO</item> <!-- Arabic (Somalia) -->
+ <item>ar-SO-u-nu-latn</item> <!-- Arabic (Somalia,Western Digits) -->
<item>ar-SS</item> <!-- Arabic (South Sudan) -->
+ <item>ar-SS-u-nu-latn</item> <!-- Arabic (South Sudan,Western Digits) -->
<item>ar-SY</item> <!-- Arabic (Syria) -->
+ <item>ar-SY-u-nu-latn</item> <!-- Arabic (Syria,Western Digits) -->
<item>ar-TD</item> <!-- Arabic (Chad) -->
+ <item>ar-TD-u-nu-latn</item> <!-- Arabic (Chad,Western Digits) -->
<item>ar-TN</item> <!-- Arabic (Tunisia) -->
<item>ar-TN-u-nu-arab</item> <!-- Arabic (Tunisia,Arabic-Indic Digits) -->
<item>ar-XB</item> <!-- Right-to-left pseudolocale -->
<item>ar-YE</item> <!-- Arabic (Yemen) -->
+ <item>ar-YE-u-nu-latn</item> <!-- Arabic (Yemen,Western Digits) -->
<item>as-IN</item> <!-- Assamese (India) -->
<item>asa-TZ</item> <!-- Asu (Tanzania) -->
<item>az-Cyrl-AZ</item> <!-- Azerbaijani (Cyrillic,Azerbaijan) -->
@@ -63,7 +88,9 @@
<item>bg-BG</item> <!-- Bulgarian (Bulgaria) -->
<item>bm-ML</item> <!-- Bambara (Mali) -->
<item>bn-BD</item> <!-- Bengali (Bangladesh) -->
+ <item>bn-BD-u-nu-latn</item> <!-- Bengali (Bangladesh,Western Digits) -->
<item>bn-IN</item> <!-- Bengali (India) -->
+ <item>bn-IN-u-nu-latn</item> <!-- Bengali (India,Western Digits) -->
<item>bo-CN</item> <!-- Tibetan (China) -->
<item>bo-IN</item> <!-- Tibetan (India) -->
<item>br-FR</item> <!-- Breton (France) -->
@@ -230,7 +257,9 @@
<item>eu-ES</item> <!-- Basque (Spain) -->
<item>ewo-CM</item> <!-- Ewondo (Cameroon) -->
<item>fa-AF</item> <!-- Persian (Afghanistan) -->
+ <item>fa-AF-u-nu-latn</item> <!-- Persian (Afghanistan,Western Digits) -->
<item>fa-IR</item> <!-- Persian (Iran) -->
+ <item>fa-IR-u-nu-latn</item> <!-- Persian (Iran,Western Digits) -->
<item>ff-CM</item> <!-- Fulah (Cameroon) -->
<item>ff-GN</item> <!-- Fulah (Guinea) -->
<item>ff-MR</item> <!-- Fulah (Mauritania) -->
@@ -473,7 +502,9 @@
<item>ug-CN</item> <!-- Uyghur (China) -->
<item>uk-UA</item> <!-- Ukrainian (Ukraine) -->
<item>ur-IN</item> <!-- Urdu (India) -->
+ <item>ur-IN-u-nu-latn</item> <!-- Urdu (India,Western Digits) -->
<item>ur-PK</item> <!-- Urdu (Pakistan) -->
+ <item>ur-PK-u-nu-arabext</item> <!-- Urdu (Pakistan,Extended Arabic-Indic Digits) -->
<item>uz-Arab-AF</item> <!-- Uzbek (Arabic,Afghanistan) -->
<item>uz-Cyrl-UZ</item> <!-- Uzbek (Cyrillic,Uzbekistan) -->
<item>uz-Latn-UZ</item> <!-- Uzbek (Latin,Uzbekistan) -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 170ba4264e04..9cab9fa45014 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4480,7 +4480,7 @@
<string name="zen_mode_alarm">Until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g> (next alarm)</string>
<!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
- <string name="zen_mode_forever">Until you turn off Do Not Disturb</string>
+ <string name="zen_mode_forever">Until you turn off</string>
<!-- Zen mode condition: no exit criteria, includes the name of the feature for emphasis. [CHAR LIMIT=NONE] -->
<string name="zen_mode_forever_dnd">Until you turn off Do Not Disturb</string>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 4be6408dca16..09192f4fa72f 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -172,6 +172,8 @@
<assign-permission name="android.permission.ACCESS_LOWPAN_STATE" uid="lowpan" />
<assign-permission name="android.permission.MANAGE_LOWPAN_INTERFACES" uid="lowpan" />
+ <assign-permission name="android.permission.DUMP" uid="statsd" />
+ <assign-permission name="android.permission.PACKAGE_USAGE_STATS" uid="statsd" />
<assign-permission name="android.permission.STATSCOMPANION" uid="statsd" />
<!-- This is a list of all the libraries available for application
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 1690e8ce9309..e25386baf969 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -510,6 +510,19 @@ public class KeyStore {
return importKey(alias, args, format, keyData, UID_SELF, flags, outCharacteristics);
}
+ public int importWrappedKey(String wrappedKeyAlias, byte[] wrappedKey,
+ String wrappingKeyAlias,
+ byte[] maskingKey, KeymasterArguments args, long rootSid, long fingerprintSid, int uid,
+ KeyCharacteristics outCharacteristics) {
+ try {
+ return mBinder.importWrappedKey(wrappedKeyAlias, wrappedKey, wrappingKeyAlias,
+ maskingKey, args, rootSid, fingerprintSid, outCharacteristics);
+ } catch (RemoteException e) {
+ Log.w(TAG, "Cannot connect to keystore", e);
+ return SYSTEM_ERROR;
+ }
+ }
+
public ExportResult exportKey(String alias, int format, KeymasterBlob clientId,
KeymasterBlob appId, int uid) {
try {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java
new file mode 100644
index 000000000000..01fd0624572c
--- /dev/null
+++ b/keystore/java/android/security/keystore/AndroidKeyStore3DESCipherSpi.java
@@ -0,0 +1,298 @@
+/*
+ * Copyright (C) 2018 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.security.keystore;
+
+import android.security.keymaster.KeymasterArguments;
+import android.security.keymaster.KeymasterDefs;
+
+import java.security.AlgorithmParameters;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.ProviderException;
+import java.security.spec.AlgorithmParameterSpec;
+import java.security.spec.InvalidParameterSpecException;
+import java.util.Arrays;
+
+import javax.crypto.CipherSpi;
+import javax.crypto.spec.IvParameterSpec;
+
+/**
+ * Base class for Android Keystore 3DES {@link CipherSpi} implementations.
+ *
+ * @hide
+ */
+public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+
+ private static final int BLOCK_SIZE_BYTES = 8;
+
+ private final int mKeymasterBlockMode;
+ private final int mKeymasterPadding;
+ /** Whether this transformation requires an IV. */
+ private final boolean mIvRequired;
+
+ private byte[] mIv;
+
+ /** Whether the current {@code #mIv} has been used by the underlying crypto operation. */
+ private boolean mIvHasBeenUsed;
+
+ AndroidKeyStore3DESCipherSpi(
+ int keymasterBlockMode,
+ int keymasterPadding,
+ boolean ivRequired) {
+ mKeymasterBlockMode = keymasterBlockMode;
+ mKeymasterPadding = keymasterPadding;
+ mIvRequired = ivRequired;
+ }
+
+ abstract static class ECB extends AndroidKeyStore3DESCipherSpi {
+ protected ECB(int keymasterPadding) {
+ super(KeymasterDefs.KM_MODE_ECB, keymasterPadding, false);
+ }
+
+ public static class NoPadding extends ECB {
+ public NoPadding() {
+ super(KeymasterDefs.KM_PAD_NONE);
+ }
+ }
+
+ public static class PKCS7Padding extends ECB {
+ public PKCS7Padding() {
+ super(KeymasterDefs.KM_PAD_PKCS7);
+ }
+ }
+ }
+
+ abstract static class CBC extends AndroidKeyStore3DESCipherSpi {
+ protected CBC(int keymasterPadding) {
+ super(KeymasterDefs.KM_MODE_CBC, keymasterPadding, true);
+ }
+
+ public static class NoPadding extends CBC {
+ public NoPadding() {
+ super(KeymasterDefs.KM_PAD_NONE);
+ }
+ }
+
+ public static class PKCS7Padding extends CBC {
+ public PKCS7Padding() {
+ super(KeymasterDefs.KM_PAD_PKCS7);
+ }
+ }
+ }
+
+ @Override
+ protected void initKey(int i, Key key) throws InvalidKeyException {
+ if (!(key instanceof AndroidKeyStoreSecretKey)) {
+ throw new InvalidKeyException(
+ "Unsupported key: " + ((key != null) ? key.getClass().getName() : "null"));
+ }
+ if (!KeyProperties.KEY_ALGORITHM_3DES.equalsIgnoreCase(key.getAlgorithm())) {
+ throw new InvalidKeyException(
+ "Unsupported key algorithm: " + key.getAlgorithm() + ". Only " +
+ KeyProperties.KEY_ALGORITHM_3DES + " supported");
+ }
+ setKey((AndroidKeyStoreSecretKey) key);
+ }
+
+ @Override
+ protected int engineGetBlockSize() {
+ return BLOCK_SIZE_BYTES;
+ }
+
+ @Override
+ protected int engineGetOutputSize(int inputLen) {
+ return inputLen + 3 * BLOCK_SIZE_BYTES;
+ }
+
+ @Override
+ protected final byte[] engineGetIV() {
+ return ArrayUtils.cloneIfNotEmpty(mIv);
+ }
+
+ @Override
+ protected AlgorithmParameters engineGetParameters() {
+ if (!mIvRequired) {
+ return null;
+ }
+ if ((mIv != null) && (mIv.length > 0)) {
+ try {
+ AlgorithmParameters params = AlgorithmParameters.getInstance("DESede");
+ params.init(new IvParameterSpec(mIv));
+ return params;
+ } catch (NoSuchAlgorithmException e) {
+ throw new ProviderException(
+ "Failed to obtain 3DES AlgorithmParameters", e);
+ } catch (InvalidParameterSpecException e) {
+ throw new ProviderException(
+ "Failed to initialize 3DES AlgorithmParameters with an IV",
+ e);
+ }
+ }
+ return null;
+ }
+
+ @Override
+ protected void initAlgorithmSpecificParameters() throws InvalidKeyException {
+ if (!mIvRequired) {
+ return;
+ }
+
+ // IV is used
+ if (!isEncrypting()) {
+ throw new InvalidKeyException("IV required when decrypting"
+ + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
+ }
+ }
+
+ @Override
+ protected void initAlgorithmSpecificParameters(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ if (!mIvRequired) {
+ if (params != null) {
+ throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
+ }
+ return;
+ }
+
+ // IV is used
+ if (params == null) {
+ if (!isEncrypting()) {
+ // IV must be provided by the caller
+ throw new InvalidAlgorithmParameterException(
+ "IvParameterSpec must be provided when decrypting");
+ }
+ return;
+ }
+ if (!(params instanceof IvParameterSpec)) {
+ throw new InvalidAlgorithmParameterException("Only IvParameterSpec supported");
+ }
+ mIv = ((IvParameterSpec) params).getIV();
+ if (mIv == null) {
+ throw new InvalidAlgorithmParameterException("Null IV in IvParameterSpec");
+ }
+ }
+
+ @Override
+ protected void initAlgorithmSpecificParameters(AlgorithmParameters params)
+ throws InvalidAlgorithmParameterException {
+ if (!mIvRequired) {
+ if (params != null) {
+ throw new InvalidAlgorithmParameterException("Unsupported parameters: " + params);
+ }
+ return;
+ }
+
+ // IV is used
+ if (params == null) {
+ if (!isEncrypting()) {
+ // IV must be provided by the caller
+ throw new InvalidAlgorithmParameterException("IV required when decrypting"
+ + ". Use IvParameterSpec or AlgorithmParameters to provide it.");
+ }
+ return;
+ }
+
+ if (!"DESede".equalsIgnoreCase(params.getAlgorithm())) {
+ throw new InvalidAlgorithmParameterException(
+ "Unsupported AlgorithmParameters algorithm: " + params.getAlgorithm()
+ + ". Supported: DESede");
+ }
+
+ IvParameterSpec ivSpec;
+ try {
+ ivSpec = params.getParameterSpec(IvParameterSpec.class);
+ } catch (InvalidParameterSpecException e) {
+ if (!isEncrypting()) {
+ // IV must be provided by the caller
+ throw new InvalidAlgorithmParameterException("IV required when decrypting"
+ + ", but not found in parameters: " + params, e);
+ }
+ mIv = null;
+ return;
+ }
+ mIv = ivSpec.getIV();
+ if (mIv == null) {
+ throw new InvalidAlgorithmParameterException("Null IV in AlgorithmParameters");
+ }
+ }
+
+ @Override
+ protected final int getAdditionalEntropyAmountForBegin() {
+ if ((mIvRequired) && (mIv == null) && (isEncrypting())) {
+ // IV will need to be generated
+ return BLOCK_SIZE_BYTES;
+ }
+
+ return 0;
+ }
+
+ @Override
+ protected int getAdditionalEntropyAmountForFinish() {
+ return 0;
+ }
+
+ @Override
+ protected void addAlgorithmSpecificParametersToBegin(KeymasterArguments keymasterArgs) {
+ if ((isEncrypting()) && (mIvRequired) && (mIvHasBeenUsed)) {
+ // IV is being reused for encryption: this violates security best practices.
+ throw new IllegalStateException(
+ "IV has already been used. Reusing IV in encryption mode violates security best"
+ + " practices.");
+ }
+
+ keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_3DES);
+ keymasterArgs.addEnum(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockMode);
+ keymasterArgs.addEnum(KeymasterDefs.KM_TAG_PADDING, mKeymasterPadding);
+ if ((mIvRequired) && (mIv != null)) {
+ keymasterArgs.addBytes(KeymasterDefs.KM_TAG_NONCE, mIv);
+ }
+ }
+
+ @Override
+ protected void loadAlgorithmSpecificParametersFromBeginResult(
+ KeymasterArguments keymasterArgs) {
+ mIvHasBeenUsed = true;
+
+ // NOTE: Keymaster doesn't always return an IV, even if it's used.
+ byte[] returnedIv = keymasterArgs.getBytes(KeymasterDefs.KM_TAG_NONCE, null);
+ if ((returnedIv != null) && (returnedIv.length == 0)) {
+ returnedIv = null;
+ }
+
+ if (mIvRequired) {
+ if (mIv == null) {
+ mIv = returnedIv;
+ } else if ((returnedIv != null) && (!Arrays.equals(returnedIv, mIv))) {
+ throw new ProviderException("IV in use differs from provided IV");
+ }
+ } else {
+ if (returnedIv != null) {
+ throw new ProviderException(
+ "IV in use despite IV not being used by this transformation");
+ }
+ }
+ }
+
+ @Override
+ protected final void resetAll() {
+ mIv = null;
+ mIvHasBeenUsed = false;
+ super.resetAll();
+ }
+}
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
index be390ffca2d9..e4cf84afcb8f 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
@@ -93,6 +93,16 @@ class AndroidKeyStoreBCWorkaroundProvider extends Provider {
putSymmetricCipherImpl("AES/CTR/NoPadding",
PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CTR$NoPadding");
+ putSymmetricCipherImpl("DESede/CBC/NoPadding",
+ PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$CBC$NoPadding");
+ putSymmetricCipherImpl("DESede/CBC/PKCS7Padding",
+ PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$CBC$PKCS7Padding");
+
+ putSymmetricCipherImpl("DESede/ECB/NoPadding",
+ PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$ECB$NoPadding");
+ putSymmetricCipherImpl("DESede/ECB/PKCS7Padding",
+ PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$ECB$PKCS7Padding");
+
putSymmetricCipherImpl("AES/GCM/NoPadding",
PACKAGE_NAME + ".AndroidKeyStoreAuthenticatedAESCipherSpi$GCM$NoPadding");
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index fdebf3793f12..5bcb34a67a54 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -307,7 +307,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
*
* <p>This implementation returns {@code null}.
*
- * @returns stream or {@code null} if AAD is not supported by this cipher.
+ * @return stream or {@code null} if AAD is not supported by this cipher.
*/
@Nullable
protected KeyStoreCryptoOperationStreamer createAdditionalAuthenticationDataStreamer(
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
index f1d1e1665387..379e17701c8f 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java
@@ -60,6 +60,12 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
}
}
+ public static class DESede extends AndroidKeyStoreKeyGeneratorSpi {
+ public DESede() {
+ super(KeymasterDefs.KM_ALGORITHM_3DES, 168);
+ }
+ }
+
protected static abstract class HmacBase extends AndroidKeyStoreKeyGeneratorSpi {
protected HmacBase(int keymasterDigest) {
super(KeymasterDefs.KM_ALGORITHM_HMAC,
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
index 55e6519d805d..10189263e98f 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreProvider.java
@@ -80,6 +80,7 @@ public class AndroidKeyStoreProvider extends Provider {
// javax.crypto.KeyGenerator
put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES");
+ put("KeyGenerator.DESede", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$DESede");
put("KeyGenerator.HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA1");
put("KeyGenerator.HmacSHA224", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA224");
put("KeyGenerator.HmacSHA256", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA256");
@@ -88,6 +89,7 @@ public class AndroidKeyStoreProvider extends Provider {
// java.security.SecretKeyFactory
putSecretKeyFactoryImpl("AES");
+ putSecretKeyFactoryImpl("DESede");
putSecretKeyFactoryImpl("HmacSHA1");
putSecretKeyFactoryImpl("HmacSHA224");
putSecretKeyFactoryImpl("HmacSHA256");
@@ -348,7 +350,8 @@ public class AndroidKeyStoreProvider extends Provider {
}
if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC ||
- keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_AES) {
+ keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_AES ||
+ keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_3DES) {
return loadAndroidKeyStoreSecretKeyFromKeystore(userKeyAlias, uid,
keyCharacteristics);
} else if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_RSA ||
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index d73a9e29bb1b..440e0863fbb1 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -18,6 +18,7 @@ package android.security.keystore;
import libcore.util.EmptyArray;
import android.security.Credentials;
+import android.security.GateKeeper;
import android.security.KeyStore;
import android.security.KeyStoreParameter;
import android.security.keymaster.KeyCharacteristics;
@@ -25,6 +26,7 @@ import android.security.keymaster.KeymasterArguments;
import android.security.keymaster.KeymasterDefs;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
+import android.security.keystore.WrappedKeyEntry;
import android.util.Log;
import java.io.ByteArrayInputStream;
@@ -744,6 +746,31 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
}
}
+ private void setWrappedKeyEntry(String alias, byte[] wrappedKeyBytes, String wrappingKeyAlias,
+ java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
+ if (param != null) {
+ throw new KeyStoreException("Protection parameters are specified inside wrapped keys");
+ }
+
+ byte[] maskingKey = new byte[32];
+ KeymasterArguments args = new KeymasterArguments(); // TODO: populate wrapping key args.
+
+ int errorCode = mKeyStore.importWrappedKey(
+ Credentials.USER_SECRET_KEY + alias,
+ wrappedKeyBytes,
+ Credentials.USER_PRIVATE_KEY + wrappingKeyAlias,
+ maskingKey,
+ args,
+ GateKeeper.getSecureUserId(),
+ 0, // FIXME fingerprint id?
+ mUid,
+ new KeyCharacteristics());
+ if (errorCode != KeyStore.NO_ERROR) {
+ throw new KeyStoreException("Failed to import wrapped key. Keystore error code: "
+ + errorCode);
+ }
+ }
+
@Override
public void engineSetKeyEntry(String alias, byte[] userKey, Certificate[] chain)
throws KeyStoreException {
@@ -974,6 +1001,9 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
} else if (entry instanceof SecretKeyEntry) {
SecretKeyEntry secE = (SecretKeyEntry) entry;
setSecretKeyEntry(alias, secE.getSecretKey(), param);
+ } else if (entry instanceof WrappedKeyEntry) {
+ WrappedKeyEntry wke = (WrappedKeyEntry) entry;
+ setWrappedKeyEntry(alias, wke.getWrappedKeyBytes(), wke.getWrappingKeyAlias(), param);
} else {
throw new KeyStoreException(
"Entry must be a PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry"
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 1238d8774e58..1e2b873c7fdd 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -262,6 +262,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
private final boolean mUniqueIdIncluded;
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
+ private final boolean mIsStrongBoxBacked;
/**
* @hide should be built with Builder
@@ -289,7 +290,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
byte[] attestationChallenge,
boolean uniqueIdIncluded,
boolean userAuthenticationValidWhileOnBody,
- boolean invalidatedByBiometricEnrollment) {
+ boolean invalidatedByBiometricEnrollment,
+ boolean isStrongBoxBacked) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -335,6 +337,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
mUniqueIdIncluded = uniqueIdIncluded;
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
+ mIsStrongBoxBacked = isStrongBoxBacked;
}
/**
@@ -625,6 +628,13 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
}
/**
+ * Returns {@code true} if the key is protected by a Strongbox security chip.
+ */
+ public boolean isStrongBoxBacked() {
+ return mIsStrongBoxBacked;
+ }
+
+ /**
* Builder of {@link KeyGenParameterSpec} instances.
*/
public final static class Builder {
@@ -652,6 +662,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
private boolean mUniqueIdIncluded = false;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
+ private boolean mIsStrongBoxBacked = false;
/**
* Creates a new instance of the {@code Builder}.
@@ -1177,6 +1188,15 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
}
/**
+ * Sets whether this key should be protected by a StrongBox security chip.
+ */
+ @NonNull
+ public Builder setIsStrongBoxBacked(boolean isStrongBoxBacked) {
+ mIsStrongBoxBacked = isStrongBoxBacked;
+ return this;
+ }
+
+ /**
* Builds an instance of {@code KeyGenParameterSpec}.
*/
@NonNull
@@ -1204,7 +1224,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec {
mAttestationChallenge,
mUniqueIdIncluded,
mUserAuthenticationValidWhileOnBody,
- mInvalidatedByBiometricEnrollment);
+ mInvalidatedByBiometricEnrollment,
+ mIsStrongBoxBacked);
}
}
}
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index a250d1f01ba1..f54b6decc5c4 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -44,6 +44,7 @@ public abstract class KeyProperties {
PURPOSE_DECRYPT,
PURPOSE_SIGN,
PURPOSE_VERIFY,
+ PURPOSE_WRAP_KEY,
})
public @interface PurposeEnum {}
@@ -68,6 +69,11 @@ public abstract class KeyProperties {
public static final int PURPOSE_VERIFY = 1 << 3;
/**
+ * Purpose of key: wrapping and unwrapping wrapped keys for secure import.
+ */
+ public static final int PURPOSE_WRAP_KEY = 1 << 5;
+
+ /**
* @hide
*/
public static abstract class Purpose {
@@ -83,6 +89,8 @@ public abstract class KeyProperties {
return KeymasterDefs.KM_PURPOSE_SIGN;
case PURPOSE_VERIFY:
return KeymasterDefs.KM_PURPOSE_VERIFY;
+ case PURPOSE_WRAP_KEY:
+ return KeymasterDefs.KM_PURPOSE_WRAP;
default:
throw new IllegalArgumentException("Unknown purpose: " + purpose);
}
@@ -98,6 +106,8 @@ public abstract class KeyProperties {
return PURPOSE_SIGN;
case KeymasterDefs.KM_PURPOSE_VERIFY:
return PURPOSE_VERIFY;
+ case KeymasterDefs.KM_PURPOSE_WRAP:
+ return PURPOSE_WRAP_KEY;
default:
throw new IllegalArgumentException("Unknown purpose: " + purpose);
}
@@ -146,6 +156,15 @@ public abstract class KeyProperties {
/** Advanced Encryption Standard (AES) key. */
public static final String KEY_ALGORITHM_AES = "AES";
+ /**
+ * Triple Data Encryption Algorithm (3DES) key.
+ *
+ * @deprecated Included for interoperability with legacy systems. Prefer {@link
+ * KeyProperties#KEY_ALGORITHM_AES} for new development.
+ */
+ @Deprecated
+ public static final String KEY_ALGORITHM_3DES = "DESede";
+
/** Keyed-Hash Message Authentication Code (HMAC) key using SHA-1 as the hash. */
public static final String KEY_ALGORITHM_HMAC_SHA1 = "HmacSHA1";
@@ -196,6 +215,8 @@ public abstract class KeyProperties {
@NonNull @KeyAlgorithmEnum String algorithm) {
if (KEY_ALGORITHM_AES.equalsIgnoreCase(algorithm)) {
return KeymasterDefs.KM_ALGORITHM_AES;
+ } else if (KEY_ALGORITHM_3DES.equalsIgnoreCase(algorithm)) {
+ return KeymasterDefs.KM_ALGORITHM_3DES;
} else if (algorithm.toUpperCase(Locale.US).startsWith("HMAC")) {
return KeymasterDefs.KM_ALGORITHM_HMAC;
} else {
@@ -210,6 +231,8 @@ public abstract class KeyProperties {
switch (keymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_AES:
return KEY_ALGORITHM_AES;
+ case KeymasterDefs.KM_ALGORITHM_3DES:
+ return KEY_ALGORITHM_3DES;
case KeymasterDefs.KM_ALGORITHM_HMAC:
switch (keymasterDigest) {
case KeymasterDefs.KM_DIGEST_SHA1:
@@ -666,6 +689,10 @@ public abstract class KeyProperties {
*/
public static final int ORIGIN_UNKNOWN = 1 << 2;
+ /** Key was imported into the AndroidKeyStore in an encrypted wrapper */
+ public static final int ORIGIN_SECURELY_IMPORTED = 1 << 3;
+
+
/**
* @hide
*/
@@ -680,6 +707,8 @@ public abstract class KeyProperties {
return ORIGIN_IMPORTED;
case KeymasterDefs.KM_ORIGIN_UNKNOWN:
return ORIGIN_UNKNOWN;
+ case KeymasterDefs.KM_ORIGIN_SECURELY_IMPORTED:
+ return ORIGIN_SECURELY_IMPORTED;
default:
throw new IllegalArgumentException("Unknown origin: " + origin);
}
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 2eb06631c228..dbacb9c53dd6 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -488,9 +488,9 @@ public final class KeyProtection implements ProtectionParameter {
private int mUserAuthenticationValidityDurationSeconds = -1;
private boolean mUserAuthenticationValidWhileOnBody;
private boolean mInvalidatedByBiometricEnrollment = true;
-
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
private boolean mCriticalToDeviceEncryption = false;
+
/**
* Creates a new instance of the {@code Builder}.
*
diff --git a/keystore/java/android/security/keystore/StrongBoxUnavailableException.java b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
new file mode 100644
index 000000000000..ad41a58eb76f
--- /dev/null
+++ b/keystore/java/android/security/keystore/StrongBoxUnavailableException.java
@@ -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.
+ */
+
+package android.security.keystore;
+
+import java.security.ProviderException;
+
+/**
+ * Indicates that an operation could not be performed because the requested security hardware
+ * is not available.
+ */
+public class StrongBoxUnavailableException extends ProviderException {
+
+}
+
diff --git a/keystore/java/android/security/keystore/WrappedKeyEntry.java b/keystore/java/android/security/keystore/WrappedKeyEntry.java
new file mode 100644
index 000000000000..a8f4afe7a201
--- /dev/null
+++ b/keystore/java/android/security/keystore/WrappedKeyEntry.java
@@ -0,0 +1,56 @@
+/*
+ * 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.security.keystore;
+
+import java.security.KeyStore.Entry;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ * An {@link Entry} that holds a wrapped key.
+ */
+public class WrappedKeyEntry implements Entry {
+
+ private final byte[] mWrappedKeyBytes;
+ private final String mWrappingKeyAlias;
+ private final String mTransformation;
+ private final AlgorithmParameterSpec mAlgorithmParameterSpec;
+
+ public WrappedKeyEntry(byte[] wrappedKeyBytes, String wrappingKeyAlias, String transformation,
+ AlgorithmParameterSpec algorithmParameterSpec) {
+ mWrappedKeyBytes = wrappedKeyBytes;
+ mWrappingKeyAlias = wrappingKeyAlias;
+ mTransformation = transformation;
+ mAlgorithmParameterSpec = algorithmParameterSpec;
+ }
+
+ public byte[] getWrappedKeyBytes() {
+ return mWrappedKeyBytes;
+ }
+
+ public String getWrappingKeyAlias() {
+ return mWrappingKeyAlias;
+ }
+
+ public String getTransformation() {
+ return mTransformation;
+ }
+
+ public AlgorithmParameterSpec getAlgorithmParameterSpec() {
+ return mAlgorithmParameterSpec;
+ }
+}
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 5b95c81db24e..696a00c7b2c0 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -1877,19 +1877,27 @@ void ResTable_config::swapHtoD() {
return (l.locale > r.locale) ? 1 : -1;
}
- // The language & region are equal, so compare the scripts and variants.
+ // The language & region are equal, so compare the scripts, variants and
+ // numbering systms in this order. Comparison of variants and numbering
+ // systems should happen very infrequently (if at all.)
+ // The comparison code relies on memcmp low-level optimizations that make it
+ // more efficient than strncmp.
const char emptyScript[sizeof(l.localeScript)] = {'\0', '\0', '\0', '\0'};
const char *lScript = l.localeScriptWasComputed ? emptyScript : l.localeScript;
const char *rScript = r.localeScriptWasComputed ? emptyScript : r.localeScript;
+
int script = memcmp(lScript, rScript, sizeof(l.localeScript));
if (script) {
return script;
}
- // The language, region and script are equal, so compare variants.
- //
- // This should happen very infrequently (if at all.)
- return memcmp(l.localeVariant, r.localeVariant, sizeof(l.localeVariant));
+ int variant = memcmp(l.localeVariant, r.localeVariant, sizeof(l.localeVariant));
+ if (variant) {
+ return variant;
+ }
+
+ return memcmp(l.localeNumberingSystem, r.localeNumberingSystem,
+ sizeof(l.localeNumberingSystem));
}
int ResTable_config::compare(const ResTable_config& o) const {
@@ -2030,6 +2038,22 @@ int ResTable_config::diff(const ResTable_config& o) const {
return diffs;
}
+// There isn't a well specified "importance" order between variants and
+// scripts. We can't easily tell whether, say "en-Latn-US" is more or less
+// specific than "en-US-POSIX".
+//
+// We therefore arbitrarily decide to give priority to variants over
+// scripts since it seems more useful to do so. We will consider
+// "en-US-POSIX" to be more specific than "en-Latn-US".
+//
+// Unicode extension keywords are considered to be less important than
+// scripts and variants.
+inline int ResTable_config::getImportanceScoreOfLocale() const {
+ return (localeVariant[0] ? 4 : 0)
+ + (localeScript[0] && !localeScriptWasComputed ? 2: 0)
+ + (localeNumberingSystem[0] ? 1: 0);
+}
+
int ResTable_config::isLocaleMoreSpecificThan(const ResTable_config& o) const {
if (locale || o.locale) {
if (language[0] != o.language[0]) {
@@ -2043,21 +2067,7 @@ int ResTable_config::isLocaleMoreSpecificThan(const ResTable_config& o) const {
}
}
- // There isn't a well specified "importance" order between variants and
- // scripts. We can't easily tell whether, say "en-Latn-US" is more or less
- // specific than "en-US-POSIX".
- //
- // We therefore arbitrarily decide to give priority to variants over
- // scripts since it seems more useful to do so. We will consider
- // "en-US-POSIX" to be more specific than "en-Latn-US".
-
- const int score = ((localeScript[0] != '\0' && !localeScriptWasComputed) ? 1 : 0) +
- ((localeVariant[0] != '\0') ? 2 : 0);
-
- const int oScore = (o.localeScript[0] != '\0' && !o.localeScriptWasComputed ? 1 : 0) +
- ((o.localeVariant[0] != '\0') ? 2 : 0);
-
- return score - oScore;
+ return getImportanceScoreOfLocale() - o.getImportanceScoreOfLocale();
}
bool ResTable_config::isMoreSpecificThan(const ResTable_config& o) const {
@@ -2314,6 +2324,17 @@ bool ResTable_config::isLocaleBetterThan(const ResTable_config& o,
return localeMatches;
}
+ // The variants are the same, try numbering system.
+ const bool localeNumsysMatches = strncmp(localeNumberingSystem,
+ requested->localeNumberingSystem,
+ sizeof(localeNumberingSystem)) == 0;
+ const bool otherNumsysMatches = strncmp(o.localeNumberingSystem,
+ requested->localeNumberingSystem,
+ sizeof(localeNumberingSystem)) == 0;
+ if (localeNumsysMatches != otherNumsysMatches) {
+ return localeNumsysMatches;
+ }
+
// Finally, the languages, although equivalent, may still be different
// (like for Tagalog and Filipino). Identical is better than just
// equivalent.
@@ -2781,7 +2802,7 @@ void ResTable_config::appendDirLocale(String8& out) const {
return;
}
const bool scriptWasProvided = localeScript[0] != '\0' && !localeScriptWasComputed;
- if (!scriptWasProvided && !localeVariant[0]) {
+ if (!scriptWasProvided && !localeVariant[0] && !localeNumberingSystem[0]) {
// Legacy format.
if (out.size() > 0) {
out.append("-");
@@ -2826,6 +2847,12 @@ void ResTable_config::appendDirLocale(String8& out) const {
out.append("+");
out.append(localeVariant, strnlen(localeVariant, sizeof(localeVariant)));
}
+
+ if (localeNumberingSystem[0]) {
+ out.append("+u+nu+");
+ out.append(localeNumberingSystem,
+ strnlen(localeNumberingSystem, sizeof(localeNumberingSystem)));
+ }
}
void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN], bool canonicalize) const {
@@ -2868,10 +2895,17 @@ void ResTable_config::getBcp47Locale(char str[RESTABLE_MAX_LOCALE_LEN], bool can
str[charsWritten++] = '-';
}
memcpy(str + charsWritten, localeVariant, sizeof(localeVariant));
+ charsWritten += strnlen(str + charsWritten, sizeof(localeVariant));
}
- /* TODO: Add BCP47 extension. It requires RESTABLE_MAX_LOCALE_LEN
- * increase from 28 to 42 bytes (-u-nu-xxxxxxxx) */
+ // Add Unicode extension only if at least one other locale component is present
+ if (localeNumberingSystem[0] != '\0' && charsWritten > 0) {
+ static constexpr char NU_PREFIX[] = "-u-nu-";
+ static constexpr size_t NU_PREFIX_LEN = sizeof(NU_PREFIX) - 1;
+ memcpy(str + charsWritten, NU_PREFIX, NU_PREFIX_LEN);
+ charsWritten += NU_PREFIX_LEN;
+ memcpy(str + charsWritten, localeNumberingSystem, sizeof(localeNumberingSystem));
+ }
}
struct LocaleParserState {
@@ -3004,10 +3038,7 @@ struct LocaleParserState {
}
void ResTable_config::setBcp47Locale(const char* in) {
- locale = 0;
- memset(localeScript, 0, sizeof(localeScript));
- memset(localeVariant, 0, sizeof(localeVariant));
- memset(localeNumberingSystem, 0, sizeof(localeNumberingSystem));
+ clearLocale();
const char* start = in;
LocaleParserState state;
diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h
index 8cf4de9167e5..a1f15f0c96cb 100644
--- a/libs/androidfw/include/androidfw/ResourceTypes.h
+++ b/libs/androidfw/include/androidfw/ResourceTypes.h
@@ -894,9 +894,10 @@ struct ResTable_package
// - a 8 char variant code prefixed by a 'v'
//
// each separated by a single char separator, which sums up to a total of 24
-// chars, (25 include the string terminator) rounded up to 28 to be 4 byte
-// aligned.
-#define RESTABLE_MAX_LOCALE_LEN 28
+// chars, (25 include the string terminator). Numbering system specificator,
+// if present, can add up to 14 bytes (-u-nu-xxxxxxxx), giving 39 bytes,
+// or 40 bytes to make it 4 bytes aligned.
+#define RESTABLE_MAX_LOCALE_LEN 40
/**
@@ -1303,6 +1304,9 @@ struct ResTable_config
// and 0 if they're equally specific.
int isLocaleMoreSpecificThan(const ResTable_config &o) const;
+ // Returns an integer representng the imporance score of the configuration locale.
+ int getImportanceScoreOfLocale() const;
+
// Return true if 'this' is a better locale match than 'o' for the
// 'requested' configuration. Similar to isBetterThan(), this assumes that
// match() has already been used to remove any configurations that don't
diff --git a/libs/androidfw/tests/ConfigLocale_test.cpp b/libs/androidfw/tests/ConfigLocale_test.cpp
index 35007c815edd..ac08c52772d1 100644
--- a/libs/androidfw/tests/ConfigLocale_test.cpp
+++ b/libs/androidfw/tests/ConfigLocale_test.cpp
@@ -173,6 +173,18 @@ TEST(ConfigLocaleTest, IsMoreSpecificThan) {
fillIn("en", "US", NULL, "POSIX", &r);
EXPECT_FALSE(l.isMoreSpecificThan(r));
EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+ fillIn("ar", "EG", NULL, NULL, &l);
+ fillIn("ar", "EG", NULL, NULL, &r);
+ memcpy(&r.localeNumberingSystem, "latn", 4);
+ EXPECT_FALSE(l.isMoreSpecificThan(r));
+ EXPECT_TRUE(r.isMoreSpecificThan(l));
+
+ fillIn("en", "US", NULL, NULL, &l);
+ fillIn("es", "ES", NULL, NULL, &r);
+
+ EXPECT_FALSE(l.isMoreSpecificThan(r));
+ EXPECT_FALSE(r.isMoreSpecificThan(l));
}
TEST(ConfigLocaleTest, setLocale) {
@@ -321,6 +333,22 @@ TEST(ConfigLocaleTest, getBcp47Locale_script) {
EXPECT_EQ(0, strcmp("en", out));
}
+TEST(ConfigLocaleTest, getBcp47Locale_numberingSystem) {
+ ResTable_config config;
+ fillIn("en", NULL, NULL, NULL, &config);
+
+ char out[RESTABLE_MAX_LOCALE_LEN];
+
+ memcpy(&config.localeNumberingSystem, "latn", 4);
+ config.getBcp47Locale(out);
+ EXPECT_EQ(0, strcmp("en-u-nu-latn", out));
+
+ fillIn("sr", "SR", "Latn", NULL, &config);
+ memcpy(&config.localeNumberingSystem, "latn", 4);
+ config.getBcp47Locale(out);
+ EXPECT_EQ(0, strcmp("sr-Latn-SR-u-nu-latn", out));
+}
+
TEST(ConfigLocaleTest, getBcp47Locale_canonicalize) {
ResTable_config config;
char out[RESTABLE_MAX_LOCALE_LEN];
@@ -433,6 +461,11 @@ TEST(ConfigLocaleTest, match) {
fillIn("ar", "XB", NULL, NULL, &requested);
// Even if they are pseudo-locales, exactly equal locales match.
EXPECT_TRUE(supported.match(requested));
+
+ fillIn("ar", "EG", NULL, NULL, &supported);
+ fillIn("ar", "TN", NULL, NULL, &requested);
+ memcpy(&supported.localeNumberingSystem, "latn", 4);
+ EXPECT_TRUE(supported.match(requested));
}
TEST(ConfigLocaleTest, match_emptyScript) {
@@ -758,6 +791,26 @@ TEST(ConfigLocaleTest, isLocaleBetterThan_regionComparison) {
EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
}
+TEST(ConfigLocaleTest, isLocaleBetterThan_numberingSystem) {
+ ResTable_config config1, config2, request;
+
+ fillIn("ar", "EG", NULL, NULL, &request);
+ memcpy(&request.localeNumberingSystem, "latn", 4);
+ fillIn("ar", NULL, NULL, NULL, &config1);
+ memcpy(&config1.localeNumberingSystem, "latn", 4);
+ fillIn("ar", NULL, NULL, NULL, &config2);
+ EXPECT_TRUE(config1.isLocaleBetterThan(config2, &request));
+ EXPECT_FALSE(config2.isLocaleBetterThan(config1, &request));
+
+ fillIn("ar", "EG", NULL, NULL, &request);
+ memcpy(&request.localeNumberingSystem, "latn", 4);
+ fillIn("ar", "TN", NULL, NULL, &config1);
+ memcpy(&config1.localeNumberingSystem, "latn", 4);
+ fillIn("ar", NULL, NULL, NULL, &config2);
+ EXPECT_TRUE(config2.isLocaleBetterThan(config1, &request));
+ EXPECT_FALSE(config1.isLocaleBetterThan(config2, &request));
+}
+
// Default resources are considered better matches for US English
// and US-like English locales than International English locales
TEST(ConfigLocaleTest, isLocaleBetterThan_UsEnglishIsSpecial) {
diff --git a/media/java/android/media/MediaDrm.java b/media/java/android/media/MediaDrm.java
index e2f9b47ed482..690d74040ce1 100644
--- a/media/java/android/media/MediaDrm.java
+++ b/media/java/android/media/MediaDrm.java
@@ -16,13 +16,6 @@
package android.media;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.UUID;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -34,6 +27,16 @@ import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.util.Log;
+import dalvik.system.CloseGuard;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicBoolean;
+
/**
* MediaDrm can be used to obtain keys for decrypting protected media streams, in
@@ -117,10 +120,13 @@ import android.util.Log;
* MediaDrm objects on a thread with its own Looper running (main UI
* thread by default has a Looper running).
*/
-public final class MediaDrm {
+public final class MediaDrm implements AutoCloseable {
private static final String TAG = "MediaDrm";
+ private final AtomicBoolean mClosed = new AtomicBoolean();
+ private final CloseGuard mCloseGuard = CloseGuard.get();
+
private static final String PERMISSION = android.Manifest.permission.ACCESS_DRM_CERTIFICATES;
private EventHandler mEventHandler;
@@ -215,6 +221,8 @@ public final class MediaDrm {
*/
native_setup(new WeakReference<MediaDrm>(this),
getByteArrayFromUUID(uuid), ActivityThread.currentOpPackageName());
+
+ mCloseGuard.open("release");
}
/**
@@ -954,6 +962,168 @@ public final class MediaDrm {
*/
public native void releaseAllSecureStops();
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({HDCP_LEVEL_UNKNOWN, HDCP_NONE, HDCP_V1, HDCP_V2,
+ HDCP_V2_1, HDCP_V2_2, HDCP_NO_DIGITAL_OUTPUT})
+ public @interface HdcpLevel {}
+
+
+ /**
+ * The DRM plugin did not report an HDCP level, or an error
+ * occurred accessing it
+ */
+ public static final int HDCP_LEVEL_UNKNOWN = 0;
+
+ /**
+ * HDCP is not supported on this device, content is unprotected
+ */
+ public static final int HDCP_NONE = 1;
+
+ /**
+ * HDCP version 1.0
+ */
+ public static final int HDCP_V1 = 2;
+
+ /**
+ * HDCP version 2.0 Type 1.
+ */
+ public static final int HDCP_V2 = 3;
+
+ /**
+ * HDCP version 2.1 Type 1.
+ */
+ public static final int HDCP_V2_1 = 4;
+
+ /**
+ * HDCP version 2.2 Type 1.
+ */
+ public static final int HDCP_V2_2 = 5;
+
+ /**
+ * No digital output, implicitly secure
+ */
+ public static final int HDCP_NO_DIGITAL_OUTPUT = Integer.MAX_VALUE;
+
+ /**
+ * Return the HDCP level negotiated with downstream receivers the
+ * device is connected to. If multiple HDCP-capable displays are
+ * simultaneously connected to separate interfaces, this method
+ * returns the lowest negotiated level of all interfaces.
+ * <p>
+ * This method should only be used for informational purposes, not for
+ * enforcing compliance with HDCP requirements. Trusted enforcement of
+ * HDCP policies must be handled by the DRM system.
+ * <p>
+ * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
+ * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
+ * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
+ */
+ @HdcpLevel
+ public native int getConnectedHdcpLevel();
+
+ /**
+ * Return the maximum supported HDCP level. The maximum HDCP level is a
+ * constant for a given device, it does not depend on downstream receivers
+ * that may be connected. If multiple HDCP-capable interfaces are present,
+ * it indicates the highest of the maximum HDCP levels of all interfaces.
+ * <p>
+ * @return one of {@link #HDCP_LEVEL_UNKNOWN}, {@link #HDCP_NONE},
+ * {@link #HDCP_V1}, {@link #HDCP_V2}, {@link #HDCP_V2_1}, {@link #HDCP_V2_2}
+ * or {@link #HDCP_NO_DIGITAL_OUTPUT}.
+ */
+ @HdcpLevel
+ public native int getMaxHdcpLevel();
+
+ /**
+ * Return the number of MediaDrm sessions that are currently opened
+ * simultaneously among all MediaDrm instances for the active DRM scheme.
+ * @return the number of open sessions.
+ */
+ public native int getOpenSessionCount();
+
+ /**
+ * Return the maximum number of MediaDrm sessions that may be opened
+ * simultaneosly among all MediaDrm instances for the active DRM
+ * scheme. The maximum number of sessions is not affected by any
+ * sessions that may have already been opened.
+ * @return maximum sessions.
+ */
+ public native int getMaxSessionCount();
+
+ /**
+ * Security level indicates the robustness of the device's DRM
+ * implementation.
+ */
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({SECURITY_LEVEL_UNKNOWN, SW_SECURE_CRYPTO, SW_SECURE_DECODE,
+ HW_SECURE_CRYPTO, HW_SECURE_DECODE, HW_SECURE_ALL})
+ public @interface SecurityLevel {}
+
+ /**
+ * The DRM plugin did not report a security level, or an error occurred
+ * accessing it
+ */
+ public static final int SECURITY_LEVEL_UNKNOWN = 0;
+
+ /**
+ * Software-based whitebox crypto
+ */
+ public static final int SW_SECURE_CRYPTO = 1;
+
+ /**
+ * Software-based whitebox crypto and an obfuscated decoder
+ */
+ public static final int SW_SECURE_DECODE = 2;
+
+ /**
+ * DRM key management and crypto operations are performed within a
+ * hardware backed trusted execution environment
+ */
+ public static final int HW_SECURE_CRYPTO = 3;
+
+ /**
+ * DRM key management, crypto operations and decoding of content
+ * are performed within a hardware backed trusted execution environment
+ */
+ public static final int HW_SECURE_DECODE = 4;
+
+ /**
+ * DRM key management, crypto operations, decoding of content and all
+ * handling of the media (compressed and uncompressed) is handled within
+ * a hardware backed trusted execution environment.
+ */
+ public static final int HW_SECURE_ALL = 5;
+
+ /**
+ * Return the current security level of a session. A session
+ * has an initial security level determined by the robustness of
+ * the DRM system's implementation on the device. The security
+ * level may be adjusted using {@link #setSecurityLevel}.
+ * @param sessionId the session to query.
+ * <p>
+ * @return one of {@link #SECURITY_LEVEL_UNKNOWN},
+ * {@link #SW_SECURE_CRYPTO}, {@link #SW_SECURE_DECODE},
+ * {@link #HW_SECURE_CRYPTO}, {@link #HW_SECURE_DECODE} or
+ * {@link #HW_SECURE_ALL}.
+ */
+ @SecurityLevel
+ public native int getSecurityLevel(@NonNull byte[] sessionId);
+
+ /**
+ * Set the security level of a session. This can be useful if specific
+ * attributes of a lower security level are needed by an application,
+ * such as image manipulation or compositing. Reducing the security
+ * level will typically limit decryption to lower content resolutions,
+ * depending on the license policy.
+ * @param sessionId the session to set the security level on.
+ * @param level the new security level, one of
+ * {@link #SW_SECURE_CRYPTO}, {@link #SW_SECURE_DECODE},
+ * {@link #HW_SECURE_CRYPTO}, {@link #HW_SECURE_DECODE} or
+ * {@link #HW_SECURE_ALL}.
+ */
+ public native void setSecurityLevel(@NonNull byte[] sessionId,
+ @SecurityLevel int level);
+
/**
* String property name: identifies the maker of the DRM plugin
*/
@@ -1311,18 +1481,52 @@ public final class MediaDrm {
}
@Override
- protected void finalize() {
- native_finalize();
+ protected void finalize() throws Throwable {
+ try {
+ if (mCloseGuard != null) {
+ mCloseGuard.warnIfOpen();
+ }
+ release();
+ } finally {
+ super.finalize();
+ }
}
- public native final void release();
+ /**
+ * Releases resources associated with the current session of
+ * MediaDrm. It is considered good practice to call this method when
+ * the {@link MediaDrm} object is no longer needed in your
+ * application. After this method is called, {@link MediaDrm} is no
+ * longer usable since it has lost all of its required resource.
+ *
+ * This method was added in API 28. In API versions 18 through 27, release()
+ * should be called instead. There is no need to do anything for API
+ * versions prior to 18.
+ */
+ @Override
+ public void close() {
+ release();
+ }
+
+ /**
+ * @deprecated replaced by {@link #close()}.
+ */
+ @Deprecated
+ public void release() {
+ mCloseGuard.close();
+ if (mClosed.compareAndSet(false, true)) {
+ native_release();
+ }
+ }
+
+ /** @hide */
+ public native final void native_release();
+
private static native final void native_init();
private native final void native_setup(Object mediadrm_this, byte[] uuid,
String appPackageName);
- private native final void native_finalize();
-
static {
System.loadLibrary("media_jni");
native_init();
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 51c9e5f1c7da..1dddbeed608c 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -130,6 +130,26 @@ struct StateExceptionFields {
jclass classId;
};
+struct HDCPLevels {
+ jint kHdcpLevelUnknown;
+ jint kHdcpNone;
+ jint kHdcpV1;
+ jint kHdcpV2;
+ jint kHdcpV2_1;
+ jint kHdcpV2_2;
+ jint kHdcpNoOutput;
+} gHdcpLevels;
+
+struct SecurityLevels {
+ jint kSecurityLevelUnknown;
+ jint kSecurityLevelSwSecureCrypto;
+ jint kSecurityLevelSwSecureDecode;
+ jint kSecurityLevelHwSecureCrypto;
+ jint kSecurityLevelHwSecureDecode;
+ jint kSecurityLevelHwSecureAll;
+} gSecurityLevels;
+
+
struct fields_t {
jfieldID context;
jmethodID post_event;
@@ -565,12 +585,19 @@ static sp<JDrm> setDrm(
return old;
}
-static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
-{
+static bool CheckDrm(JNIEnv *env, const sp<IDrm> &drm) {
if (drm == NULL) {
jniThrowException(env, "java/lang/IllegalStateException", "MediaDrm obj is null");
return false;
}
+ return true;
+}
+
+static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jsessionId)
+{
+ if (!CheckDrm(env, drm)) {
+ return false;
+ }
if (jsessionId == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", "sessionId is null");
@@ -579,7 +606,7 @@ static bool CheckSession(JNIEnv *env, const sp<IDrm> &drm, jbyteArray const &jse
return true;
}
-static void android_media_MediaDrm_release(JNIEnv *env, jobject thiz) {
+static void android_media_MediaDrm_native_release(JNIEnv *env, jobject thiz) {
sp<JDrm> drm = setDrm(env, thiz, NULL);
if (drm != NULL) {
drm->setListener(NULL);
@@ -625,6 +652,34 @@ static void android_media_MediaDrm_native_init(JNIEnv *env) {
GET_STATIC_FIELD_ID(field, clazz, "CERTIFICATE_TYPE_X509", "I");
gCertificateTypes.kCertificateTypeX509 = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HDCP_LEVEL_UNKNOWN", "I");
+ gHdcpLevels.kHdcpLevelUnknown = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HDCP_NONE", "I");
+ gHdcpLevels.kHdcpNone = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HDCP_V1", "I");
+ gHdcpLevels.kHdcpV1 = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2", "I");
+ gHdcpLevels.kHdcpV2 = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_1", "I");
+ gHdcpLevels.kHdcpV2_1 = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HDCP_V2_2", "I");
+ gHdcpLevels.kHdcpV2_2 = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HDCP_NO_DIGITAL_OUTPUT", "I");
+ gHdcpLevels.kHdcpNoOutput = env->GetStaticIntField(clazz, field);
+
+ GET_STATIC_FIELD_ID(field, clazz, "SECURITY_LEVEL_UNKNOWN", "I");
+ gSecurityLevels.kSecurityLevelUnknown = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "SW_SECURE_CRYPTO", "I");
+ gSecurityLevels.kSecurityLevelSwSecureCrypto = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "SW_SECURE_DECODE", "I");
+ gSecurityLevels.kSecurityLevelSwSecureDecode = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_CRYPTO", "I");
+ gSecurityLevels.kSecurityLevelHwSecureCrypto = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_DECODE", "I");
+ gSecurityLevels.kSecurityLevelHwSecureDecode = env->GetStaticIntField(clazz, field);
+ GET_STATIC_FIELD_ID(field, clazz, "HW_SECURE_ALL", "I");
+ gSecurityLevels.kSecurityLevelHwSecureAll = env->GetStaticIntField(clazz, field);
+
FIND_CLASS(clazz, "android/media/MediaDrm$KeyRequest");
GET_FIELD_ID(gFields.keyRequest.data, clazz, "mData", "[B");
GET_FIELD_ID(gFields.keyRequest.defaultUrl, clazz, "mDefaultUrl", "Ljava/lang/String;");
@@ -724,11 +779,6 @@ static void android_media_MediaDrm_native_setup(
setDrm(env, thiz, drm);
}
-static void android_media_MediaDrm_native_finalize(
- JNIEnv *env, jobject thiz) {
- android_media_MediaDrm_release(env, thiz);
-}
-
static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
JNIEnv *env, jobject /* thiz */, jbyteArray uuidObj, jstring jmimeType) {
@@ -971,9 +1021,7 @@ static jobject android_media_MediaDrm_getProvisionRequestNative(
JNIEnv *env, jobject thiz, jint jcertType, jstring jcertAuthority) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1018,9 +1066,7 @@ static jobject android_media_MediaDrm_provideProvisionResponseNative(
JNIEnv *env, jobject thiz, jbyteArray jresponse) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1057,9 +1103,7 @@ static jobject android_media_MediaDrm_getSecureStops(
JNIEnv *env, jobject thiz) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1078,9 +1122,7 @@ static jbyteArray android_media_MediaDrm_getSecureStop(
JNIEnv *env, jobject thiz, jbyteArray ssid) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1099,9 +1141,7 @@ static void android_media_MediaDrm_releaseSecureStops(
JNIEnv *env, jobject thiz, jbyteArray jssRelease) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return;
}
@@ -1116,9 +1156,7 @@ static void android_media_MediaDrm_releaseAllSecureStops(
JNIEnv *env, jobject thiz) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return;
}
@@ -1127,13 +1165,173 @@ static void android_media_MediaDrm_releaseAllSecureStops(
throwExceptionAsNecessary(env, err, "Failed to release all secure stops");
}
+
+static jint HdcpLevelTojint(DrmPlugin::HdcpLevel level) {
+ switch(level) {
+ case DrmPlugin::kHdcpLevelUnknown:
+ return gHdcpLevels.kHdcpLevelUnknown;
+ case DrmPlugin::kHdcpNone:
+ return gHdcpLevels.kHdcpNone;
+ case DrmPlugin::kHdcpV1:
+ return gHdcpLevels.kHdcpV1;
+ case DrmPlugin::kHdcpV2:
+ return gHdcpLevels.kHdcpV2;
+ case DrmPlugin::kHdcpV2_1:
+ return gHdcpLevels.kHdcpV2_1;
+ case DrmPlugin::kHdcpV2_2:
+ return gHdcpLevels.kHdcpV2_2;
+ case DrmPlugin::kHdcpNoOutput:
+ return gHdcpLevels.kHdcpNoOutput;
+ }
+ return gHdcpLevels.kHdcpNone;
+}
+
+static jint android_media_MediaDrm_getConnectedHdcpLevel(JNIEnv *env,
+ jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckDrm(env, drm)) {
+ return gHdcpLevels.kHdcpNone;
+ }
+
+ DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpNone;
+ DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpNone;
+
+ status_t err = drm->getHdcpLevels(&connected, &max);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+ return gHdcpLevels.kHdcpLevelUnknown;
+ }
+ return HdcpLevelTojint(connected);
+}
+
+static jint android_media_MediaDrm_getMaxHdcpLevel(JNIEnv *env,
+ jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckDrm(env, drm)) {
+ return gHdcpLevels.kHdcpLevelUnknown;
+ }
+
+ DrmPlugin::HdcpLevel connected = DrmPlugin::kHdcpLevelUnknown;
+ DrmPlugin::HdcpLevel max = DrmPlugin::kHdcpLevelUnknown;
+
+ status_t err = drm->getHdcpLevels(&connected, &max);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get HDCP levels")) {
+ return gHdcpLevels.kHdcpLevelUnknown;
+ }
+ return HdcpLevelTojint(max);
+}
+
+static jint android_media_MediaDrm_getOpenSessionCount(JNIEnv *env,
+ jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckDrm(env, drm)) {
+ return 0;
+ }
+
+ uint32_t open = 0, max = 0;
+ status_t err = drm->getNumberOfSessions(&open, &max);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+ return 0;
+ }
+ return open;
+}
+
+static jint android_media_MediaDrm_getMaxSessionCount(JNIEnv *env,
+ jobject thiz) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckDrm(env, drm)) {
+ return 0;
+ }
+
+ uint32_t open = 0, max = 0;
+ status_t err = drm->getNumberOfSessions(&open, &max);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get number of sessions")) {
+ return 0;
+ }
+ return max;
+}
+
+static jint android_media_MediaDrm_getSecurityLevel(JNIEnv *env,
+ jobject thiz, jbyteArray jsessionId) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckSession(env, drm, jsessionId)) {
+ return gSecurityLevels.kSecurityLevelUnknown;
+ }
+
+ Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
+
+ DrmPlugin::SecurityLevel level = DrmPlugin::kSecurityLevelUnknown;
+
+ status_t err = drm->getSecurityLevel(sessionId, &level);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to get security level")) {
+ return gSecurityLevels.kSecurityLevelUnknown;
+ }
+
+ switch(level) {
+ case DrmPlugin::kSecurityLevelSwSecureCrypto:
+ return gSecurityLevels.kSecurityLevelSwSecureCrypto;
+ case DrmPlugin::kSecurityLevelSwSecureDecode:
+ return gSecurityLevels.kSecurityLevelSwSecureDecode;
+ case DrmPlugin::kSecurityLevelHwSecureCrypto:
+ return gSecurityLevels.kSecurityLevelHwSecureCrypto;
+ case DrmPlugin::kSecurityLevelHwSecureDecode:
+ return gSecurityLevels.kSecurityLevelHwSecureDecode;
+ case DrmPlugin::kSecurityLevelHwSecureAll:
+ return gSecurityLevels.kSecurityLevelHwSecureAll;
+ default:
+ return gSecurityLevels.kSecurityLevelUnknown;
+ }
+}
+
+
+static void android_media_MediaDrm_setSecurityLevel(JNIEnv *env,
+ jobject thiz, jbyteArray jsessionId, jint jlevel) {
+ sp<IDrm> drm = GetDrm(env, thiz);
+
+ if (!CheckSession(env, drm, jsessionId)) {
+ return;
+ }
+
+ Vector<uint8_t> sessionId(JByteArrayToVector(env, jsessionId));
+ DrmPlugin::SecurityLevel level;
+
+ if (jlevel == gSecurityLevels.kSecurityLevelSwSecureCrypto) {
+ level = DrmPlugin::kSecurityLevelSwSecureCrypto;
+ } else if (jlevel == gSecurityLevels.kSecurityLevelSwSecureDecode) {
+ level = DrmPlugin::kSecurityLevelSwSecureDecode;
+ } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureCrypto) {
+ level = DrmPlugin::kSecurityLevelHwSecureCrypto;
+ } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureDecode) {
+ level = DrmPlugin::kSecurityLevelHwSecureDecode;
+ } else if (jlevel == gSecurityLevels.kSecurityLevelHwSecureAll) {
+ level = DrmPlugin::kSecurityLevelHwSecureAll;
+ } else {
+ jniThrowException(env, "java/lang/IllegalArgumentException", "Invalid security level");
+ return;
+ }
+
+ status_t err = drm->setSecurityLevel(sessionId, level);
+
+ if (throwExceptionAsNecessary(env, err, "Failed to set security level")) {
+ return;
+ }
+}
+
+
static jstring android_media_MediaDrm_getPropertyString(
JNIEnv *env, jobject thiz, jstring jname) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1159,9 +1357,7 @@ static jbyteArray android_media_MediaDrm_getPropertyByteArray(
JNIEnv *env, jobject thiz, jstring jname) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return NULL;
}
@@ -1187,9 +1383,7 @@ static void android_media_MediaDrm_setPropertyString(
JNIEnv *env, jobject thiz, jstring jname, jstring jvalue) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return;
}
@@ -1217,9 +1411,7 @@ static void android_media_MediaDrm_setPropertyByteArray(
JNIEnv *env, jobject thiz, jstring jname, jbyteArray jvalue) {
sp<IDrm> drm = GetDrm(env, thiz);
- if (drm == NULL) {
- jniThrowException(env, "java/lang/IllegalStateException",
- "MediaDrm obj is null");
+ if (!CheckDrm(env, drm)) {
return;
}
@@ -1445,15 +1637,13 @@ static jbyteArray android_media_MediaDrm_signRSANative(
static const JNINativeMethod gMethods[] = {
- { "release", "()V", (void *)android_media_MediaDrm_release },
+ { "native_release", "()V", (void *)android_media_MediaDrm_native_release },
+
{ "native_init", "()V", (void *)android_media_MediaDrm_native_init },
{ "native_setup", "(Ljava/lang/Object;[BLjava/lang/String;)V",
(void *)android_media_MediaDrm_native_setup },
- { "native_finalize", "()V",
- (void *)android_media_MediaDrm_native_finalize },
-
{ "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z",
(void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
@@ -1497,6 +1687,24 @@ static const JNINativeMethod gMethods[] = {
{ "releaseAllSecureStops", "()V",
(void *)android_media_MediaDrm_releaseAllSecureStops },
+ { "getConnectedHdcpLevel", "()I",
+ (void *)android_media_MediaDrm_getConnectedHdcpLevel },
+
+ { "getMaxHdcpLevel", "()I",
+ (void *)android_media_MediaDrm_getMaxHdcpLevel },
+
+ { "getOpenSessionCount", "()I",
+ (void *)android_media_MediaDrm_getOpenSessionCount },
+
+ { "getMaxSessionCount", "()I",
+ (void *)android_media_MediaDrm_getMaxSessionCount },
+
+ { "getSecurityLevel", "([B)I",
+ (void *)android_media_MediaDrm_getSecurityLevel },
+
+ { "setSecurityLevel", "([BI)V",
+ (void *)android_media_MediaDrm_setSecurityLevel },
+
{ "getPropertyString", "(Ljava/lang/String;)Ljava/lang/String;",
(void *)android_media_MediaDrm_getPropertyString },
diff --git a/packages/SettingsLib/res/drawable/btn_borderless_rect.xml b/packages/SettingsLib/res/drawable/btn_borderless_rect.xml
new file mode 100644
index 000000000000..9eaba8364f8e
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/btn_borderless_rect.xml
@@ -0,0 +1,31 @@
+<!--
+ Copyright (C) 2018 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.
+-->
+<inset
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:insetTop="4dp"
+ android:insetBottom="4dp">
+ <ripple
+ android:color="?android:attr/colorControlHighlight" >
+
+ <item android:id="@android:id/mask">
+ <shape>
+ <corners android:radius="2dp" />
+ <solid android:color="@android:color/white" />
+ </shape>
+ </item>
+
+ </ripple>
+</inset> \ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_minus.xml b/packages/SettingsLib/res/drawable/ic_minus.xml
new file mode 100644
index 000000000000..9a929a44c665
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_minus.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2018 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24.0dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:width="24.0dp" >
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18,13H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h12c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector> \ No newline at end of file
diff --git a/packages/SettingsLib/res/drawable/ic_plus.xml b/packages/SettingsLib/res/drawable/ic_plus.xml
new file mode 100644
index 000000000000..2a10e707df2a
--- /dev/null
+++ b/packages/SettingsLib/res/drawable/ic_plus.xml
@@ -0,0 +1,24 @@
+<!--
+ Copyright (C) 2018 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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:height="24.0dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0"
+ android:width="24.0dp" >
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M18,13h-5v5c0,0.55 -0.45,1 -1,1h0c-0.55,0 -1,-0.45 -1,-1v-5H6c-0.55,0 -1,-0.45 -1,-1v0c0,-0.55 0.45,-1 1,-1h5V6c0,-0.55 0.45,-1 1,-1h0c0.55,0 1,0.45 1,1v5h5c0.55,0 1,0.45 1,1v0C19,12.55 18.55,13 18,13z"/>
+</vector> \ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/zen_mode_condition.xml b/packages/SettingsLib/res/layout/zen_mode_condition.xml
new file mode 100644
index 000000000000..c85a8922a552
--- /dev/null
+++ b/packages/SettingsLib/res/layout/zen_mode_condition.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+-->
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clipChildren="false"
+ android:layout_marginStart="1dp"
+ android:layout_marginEnd="0dp"
+ android:layout_weight="1"
+ android:gravity="center_vertical" >
+
+ <LinearLayout
+ android:id="@android:id/content"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:minHeight="48dp"
+ android:gravity="center_vertical"
+ android:layout_centerVertical="true"
+ android:orientation="vertical"
+ android:layout_toEndOf="@android:id/checkbox"
+ android:layout_toStartOf="@android:id/button1">
+
+ <TextView
+ android:id="@android:id/text1"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:textAlignment="viewStart"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorPrimary"
+ android:textSize="16sp"/>
+
+ <TextView
+ android:id="@android:id/text2"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/zen_mode_condition_detail_item_interline_spacing"
+ android:ellipsize="end"
+ android:textAlignment="viewStart"
+ android:maxLines="1"
+ android:textColor="?android:attr/textColorSecondary"
+ android:textSize="14sp"/>
+
+ </LinearLayout>
+
+ <ImageView
+ android:id="@android:id/button1"
+ style="@style/BorderlessButton"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_centerVertical="true"
+ android:scaleType="center"
+ android:layout_toStartOf="@android:id/button2"
+ android:contentDescription="@string/accessibility_manual_zen_less_time"
+ android:tint="?android:attr/colorAccent"
+ android:src="@drawable/ic_minus" />
+
+ <ImageView
+ android:id="@android:id/button2"
+ style="@style/BorderlessButton"
+ android:layout_width="48dp"
+ android:layout_height="48dp"
+ android:layout_alignParentEnd="true"
+ android:scaleType="center"
+ android:layout_centerVertical="true"
+ android:contentDescription="@string/accessibility_manual_zen_more_time"
+ android:tint="?android:attr/colorAccent"
+ android:src="@drawable/ic_plus" />
+
+</RelativeLayout> \ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/zen_mode_radio_button.xml b/packages/SettingsLib/res/layout/zen_mode_radio_button.xml
new file mode 100644
index 000000000000..4c0faed610f7
--- /dev/null
+++ b/packages/SettingsLib/res/layout/zen_mode_radio_button.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+-->
+<RadioButton
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@android:id/checkbox"
+ android:layout_width="40dp"
+ android:layout_marginStart="7dp"
+ android:layout_marginEnd="4dp"
+ android:layout_height="48dp"
+ android:layout_alignParentStart="true"
+ android:gravity="center"
+ android:paddingTop="10dp"
+ android:paddingBottom="10dp">
+
+</RadioButton> \ No newline at end of file
diff --git a/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml b/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml
new file mode 100644
index 000000000000..ac56a2d9d2c3
--- /dev/null
+++ b/packages/SettingsLib/res/layout/zen_mode_turn_on_dialog_container.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2018 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.
+-->
+
+<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:fillViewport ="true"
+ android:orientation="vertical">
+
+ <com.android.settingslib.notification.ZenRadioLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/zen_conditions"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="8dp"
+ android:layout_marginEnd="4dp"
+ android:layout_marginStart="4dp"
+ android:paddingBottom="4dp"
+ android:orientation="horizontal">
+ <RadioGroup
+ android:id="@+id/zen_radio_buttons"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+ <LinearLayout
+ android:id="@+id/zen_radio_buttons_content"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"/>
+ </com.android.settingslib.notification.ZenRadioLayout>
+
+</ScrollView> \ No newline at end of file
diff --git a/packages/SettingsLib/res/values-af/strings.xml b/packages/SettingsLib/res/values-af/strings.xml
index ff81fc17698c..93c0e1007aa6 100644
--- a/packages/SettingsLib/res/values-af/strings.xml
+++ b/packages/SettingsLib/res/values-af/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Inligtingruiling"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Draadlose skermsertifisering"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiveer Wi-Fi-woordryke aanmelding"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiewe Wi‑Fi-na-mobiel-oorhandiging"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Laat altyd Wi-Fi-swerfskanderings toe"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data is altyd aktief"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardewareversnelling vir verbinding"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Voer gasheernaam van DNS-verskaffer in"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Wys opsies vir draadlose skermsertifisering"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Verhoog Wi-Fi-aantekeningvlak, wys per SSID RSSI in Wi‑Fi-kieser"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wanneer dit geaktiveer is, sal Wi-Fi die dataverbinding aggressiewer na mobiel oordra wanneer die Wi-Fi-sein swak is"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Laat toe of verbied Wi-Fi-swerfskanderings op grond van die hoeveelheid dataverkeer wat op die koppelvlak teenwoordig is"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Loggerbuffer se groottes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies loggergroottes per logbuffer"</string>
diff --git a/packages/SettingsLib/res/values-am/strings.xml b/packages/SettingsLib/res/values-am/strings.xml
index 111b7cf9eaf3..83fd2afc4787 100644
--- a/packages/SettingsLib/res/values-am/strings.xml
+++ b/packages/SettingsLib/res/values-am/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"አውታረ መረብ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"የWi‑Fi ተጨማሪ ቃላት ምዝግብ ማስታወሻ መያዝ"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"አስገዳጅ ከWi‑Fi ወደ ሞባይል ማቀበል"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ሁልጊዜ የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"የተንቀሳቃሽ ስልክ ውሂብ ሁልጊዜ ገቢር ነው"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"የሃርድዌር ማቀላጠፊያን በማስተሳሰር ላይ"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"የዲኤንኤስ አቅራቢ አስተናጋጅ ስም ያስገቡ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"የገመድ አልባ ማሳያ እውቅና ማረጋገጫ አማራጮችን አሳይ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"የWi‑Fi ምዝግብ ማስታወሻ አያያዝ ደረጃ ጨምር፣ በWi‑Fi መምረጫ ውስጥ በአንድ SSID RSSI አሳይ"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ሲነቃ የWi‑Fi ምልክት ዝቅተኛ ሲሆን Wi‑Fi የውሂብ ግንኙነት ለሞባይል ማስረከብ ላይ ይበልጥ አስገዳጅ ይሆናል"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"በበይነገጹ ላይ ባለው የውሂብ ትራፊክ መጠን ላይ ተመስርተው የWi‑Fi ማንቀሳቀስ ቅኝቶችን ይፍቀዱ/ይከልክሉ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"የምዝግብ ማስታወሻ ያዥ መጠኖች"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"በአንድ ምዝግብ ማስታወሻ ቋጥ የሚኖረው የምዝግብ ማስታወሻ ያዥ መጠኖች ይምረጡ"</string>
diff --git a/packages/SettingsLib/res/values-ar/strings.xml b/packages/SettingsLib/res/values-ar/strings.xml
index b101a1d2bea2..a541cbd62317 100644
--- a/packages/SettingsLib/res/values-ar/strings.xml
+++ b/packages/SettingsLib/res/values-ar/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"الشبكات"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"شهادة عرض شاشة لاسلكي"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"‏تمكين تسجيل Wi‑Fi Verbose"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏تسليم Wi-Fi حاد إلى جوّال"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏السماح دائمًا بعمليات فحص Wi-Fi للتجوال"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"بيانات الجوّال نشطة دائمًا"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"تسريع الأجهزة للتوصيل"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"أدخل اسم مضيف مزوّد نظام أسماء النطاقات"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"عرض خيارات شهادة عرض شاشة لاسلكي"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏زيادة مستوى تسجيل Wi-Fi، وعرض لكل SSID RSSI في منتقي Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏عند تمكينه، سيكون Wi-Fi أكثر حدة في تسليم اتصال البيانات إلى الجوّال، وذلك عندما تكون إشارة WiFi منخفضة"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏السماح/عدم السماح بعمليات فحص Wi-Fi للتجوال بناءً على حجم حركة البيانات في الواجهة"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"أحجام ذاكرة التخزين المؤقت للتسجيل"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"حدد أحجامًا أكبر لكل ذاكرة تخزين مؤقت للتسجيل"</string>
diff --git a/packages/SettingsLib/res/values-az/strings.xml b/packages/SettingsLib/res/values-az/strings.xml
index 03c9b9225a5c..5b4e45ced376 100644
--- a/packages/SettingsLib/res/values-az/strings.xml
+++ b/packages/SettingsLib/res/values-az/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Şəbəkələşmə"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz displey sertifikatlaşması"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Çoxsözlü Girişə icazə verin"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Möbül ötürücüyə aqressiv Wi‑Fi"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi axtarışlarına həmişə icazə verin"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil data həmişə aktiv"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Birləşmə üçün avadanlıq akselerasiyası"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderinin host adını daxil edin"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz displey sertifikatlaşması üçün seçimləri göstərir"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi giriş səviyyəsini qaldırın, Wi‑Fi seçəndə hər SSID RSSI üzrə göstərin"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Aktiv edildikdə, Wi-Fi siqnalı zəif olan zaman, data bağlantısını mobilə ötürərəkən Wi-Fi daha aqressiv olacaq"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi‑Fi Axtarışlarına data trafikinə əsasən İcazə verin/Qadağan edin"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger bufer ölçüləri"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hər jurnal buferinı Logger ölçüsü seçin"</string>
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 62e4b4c6b08a..0545021b159d 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikacija bežičnog ekrana"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući detaljniju evidenciju za Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivan prelaz sa Wi‑Fi mreže na mobilnu"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvek dozvoli skeniranje Wi‑Fi-ja u romingu"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci su uvek aktivni"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje privezivanja"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite ime hosta dobavljača usluge DNS-a"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaz opcija za sertifikaciju bežičnog ekrana"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećava nivo evidentiranja za Wi‑Fi. Prikaz po SSID RSSI-u u biraču Wi‑Fi mreže"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kad se omogući, Wi‑Fi će biti agresivniji pri prebacivanju mreže za prenos podataka na mobilnu ako je Wi‑Fi signal slab"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/zabrani skeniranje Wi-Fi-ja u romingu na osnovu prisutnog protoka podataka na interfejsu"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera podataka u programu za evidentiranje"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izaberite veličine po baferu evidencije"</string>
diff --git a/packages/SettingsLib/res/values-be/strings.xml b/packages/SettingsLib/res/values-be/strings.xml
index c648ea5ace03..05be22280f81 100644
--- a/packages/SettingsLib/res/values-be/strings.xml
+++ b/packages/SettingsLib/res/values-be/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Сеткі"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сертыфікацыя бесправаднога дысплея"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Уключыць падрабязны журнал Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Інтэнсіўны пераход з Wi‑Fi на маб. сетку"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Заўсёды дазваляць роўмінгавае сканіраванне Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мабільная перадача даных заўсёды актыўная"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратнае паскарэнне ў рэжыме мадэма"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Увядзіце імя вузла аператара DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Паказаць опцыі сертыфікацыі бесправаднога дысплея"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Падвыс. узровень дэтал-цыі журнала Wi‑Fi у залежн. ад SSID RSSI у Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Калі гэта функцыя ўключана, Wi-Fi будзе больш інтэнсіўна імкнуцца перайсці на падключ. маб. перад. даных пры слабым сігнале Wi‑Fi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дазволіць/забараніць роўмінгавае сканіраванне Wi‑Fi ў залежнасці ад аб\'ёму трафіку даных у інтэрфейсе"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Памеры буфера для сродку вядзення журнала"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберыце памеры сродку вядзення журнала для буфераў журнала"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 83c1ec0b0ab7..ea67a980590d 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Мрежи"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Безжичен дисплей"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"„Многословно“ регистр. на Wi‑Fi: Актив."</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi към моб. мрежи: Агресивно предав."</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Сканирането за роуминг на Wi-Fi да е разрешено винаги"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Винаги активни мобилни данни"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардуерно ускорение за тетъринга"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Въведете името на хоста на DNS доставчика"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показване на опциите за сертифициране на безжичния дисплей"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"По-подробно регистр. на Wi‑Fi – данни за RSSI на SSID в инстр. за избор на Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"При активиране предаването на връзката за данни от Wi-Fi към мобилната мрежа ще е по-агресивно, когато сигналът за Wi-Fi е слаб"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Разрешаване/забраняване на сканирането за роуминг на Wi-Fi въз основа на посочения в интерфейса обем на трафика на данни"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Размери на регистрац. буфери"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Размер на един рег. буфер: Избор"</string>
diff --git a/packages/SettingsLib/res/values-bn/strings.xml b/packages/SettingsLib/res/values-bn/strings.xml
index baf9e2c91fc4..f30ed2b87791 100644
--- a/packages/SettingsLib/res/values-bn/strings.xml
+++ b/packages/SettingsLib/res/values-bn/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"নেটওয়ার্কিং"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ওয়্যারলেস ডিসপ্লে সার্টিফিকেশন"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"ওয়াই-ফাই ভারবোস লগিং সক্ষম করুন"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ওয়াই-ফাই থেকে মোবাইলে তৎপর হস্তান্তর"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"সর্বদা ওয়াই ফাই রোম স্ক্যানকে অনুমতি দিন"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"মোবাইল ডেটা সব সময় সক্রিয় থাক"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"টিথারিং হার্ডওয়্যার অ্যাক্সিলারেশন"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ডিএনএস প্রদানকারীর হোস্টনেম লিখুন"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ওয়্যারলেস প্রদর্শন সার্টিফিকেশন জন্য বিকল্পগুলি দেখান"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ওয়াই-ফাই লগিং স্তর বাড়ান, ওয়াই-ফাই চয়নকারীতে SSID RSSI অনুযায়ী দেখান"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"সক্ষম করা থাকলে, ওয়াই ফাই সিগন্যালের মান খারাপ হলে ডেটা সংযোগ মোবাইলের কাছে হস্তান্তর করার জন্য ওয়াই ফাই আরো বেশি তৎপর হবে।"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ইন্টারফেসে উপস্থিত ডেটা ট্রাফিকের পরিমাণের উপরে ভিত্তি করে ওয়াই-ফাই রোম স্ক্যানকে অনুমোদিত/অননুমোদিত করুন"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"লগার বাফারের আকারগুলি"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"লগ বাফার প্রতি অপেক্ষাকৃত বড় আকারগুলির বেছে নিন"</string>
diff --git a/packages/SettingsLib/res/values-bs/strings.xml b/packages/SettingsLib/res/values-bs/strings.xml
index 88b01e9877a9..915eb4917bd1 100644
--- a/packages/SettingsLib/res/values-bs/strings.xml
+++ b/packages/SettingsLib/res/values-bs/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogućiti Wi-Fi Verbose zapisivanje"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivni prijenos s Wi-Fi mreže na mob."</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopustiti Wi-Fi lutajuće skeniranje"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna mreža za prijenos podataka je uvijek aktivna"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzavanje dijeljenja veze"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv host računara pružaoca DNS-a"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži opcije za certifikaciju Bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećajte nivo Wi-Fi zapisivanja, pokazati po SSID RSSI Wi-Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kada je omogućeno, Wi-Fi veza će u slučaju slabog signala agresivnije predavati vezu za prijenos podataka na mobilnu vezu"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dozvoli/Zabrani Wi-Fi lutajuće skeniranje na osnovu količine podatkovnog saobraćaja prisutnog na interfejsu"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine bafera za zapisnik"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličine za Logger prema međumemoriji evidencije"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index 48223ce614ba..d8c66933310e 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Xarxes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificació de pantalla sense fil"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Activa el registre Wi‑Fi detallat"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferència agressiva de Wi-Fi a mòbil"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permet sempre cerca de Wi-Fi en ininerància"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dades mòbils sempre actives"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Acceleració per maquinari per compartir la xarxa"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introdueix el nom d\'amfitrió del proveïdor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra les opcions de certificació de pantalla sense fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Augmenta nivell de registre Wi‑Fi i mostra\'l per SSID RSSI al Selector de Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quan s\'activa, la Wi-Fi és més agressiva en transferir la connexió de dades al mòbil quan el senyal de la Wi-Fi sigui dèbil"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permet/No permetis cerques de xarxes Wi-Fi en itinerància basades en la quantitat de dades presents a la interfície"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Mides memòria intermèdia Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Mida Logger per memòria intermèdia"</string>
diff --git a/packages/SettingsLib/res/values-cs/strings.xml b/packages/SettingsLib/res/values-cs/strings.xml
index 88bbaa77399f..41ff8e23f83c 100644
--- a/packages/SettingsLib/res/values-cs/strings.xml
+++ b/packages/SettingsLib/res/values-cs/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Sítě"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikace bezdrát. displeje"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné protokolování Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresivní předání z Wi-Fi na mobilní síť"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povolit Wi-Fi roaming"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilní data jsou vždy aktivní"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarová akcelerace tetheringu"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadejte název hostitele poskytovatele DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobrazit možnosti certifikace bezdrátového displeje"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšit úroveň protokolování Wi‑Fi zobrazenou v SSID a RSSI při výběru sítě Wi‑Fi."</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Pokud je tato možnost zapnuta, bude síť Wi-Fi při předávání datového připojení mobilní síti při slabém signálu Wi-Fi agresivnější."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povolí nebo zakáže Wi-Fi roaming na základě množství datového provozu na rozhraní."</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávací paměť protokol. nástroje"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velikost vyrovnávací paměti protokol. nástroje"</string>
@@ -395,7 +393,7 @@
<string name="content_description_menu_button" msgid="8182594799812351266">"Nabídka"</string>
<string name="retail_demo_reset_message" msgid="118771671364131297">"Chcete-li v ukázkovém režimu obnovit zařízení do továrního nastavení, zadejte heslo"</string>
<string name="retail_demo_reset_next" msgid="8356731459226304963">"Další"</string>
- <string name="retail_demo_reset_title" msgid="696589204029930100">"Je třeba zadat heslo"</string>
+ <string name="retail_demo_reset_title" msgid="696589204029930100">"Zadejte heslo"</string>
<string name="active_input_method_subtypes" msgid="3596398805424733238">"Aktivní metody zadávání"</string>
<string name="use_system_language_to_select_input_method_subtypes" msgid="5747329075020379587">"Použít systémové jazyky"</string>
<string name="failed_to_open_app_settings_toast" msgid="1251067459298072462">"Nastavení aplikace <xliff:g id="SPELL_APPLICATION_NAME">%1$s</xliff:g> se nepodařilo otevřít"</string>
diff --git a/packages/SettingsLib/res/values-da/strings.xml b/packages/SettingsLib/res/values-da/strings.xml
index 6f36bc563e3a..17d1f083ecb3 100644
--- a/packages/SettingsLib/res/values-da/strings.xml
+++ b/packages/SettingsLib/res/values-da/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netværk"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificering af trådløs skærm"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivér detaljeret Wi-Fi-logføring"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Tvungen skift fra Wi-Fi til mobildata"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillad altid scanning af Wi-Fi-roaming"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er altid aktiveret"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareacceleration ved netdeling"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Angiv hostname for DNS-udbyder"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis valgmuligheder for certificering af trådløs skærm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øg mængden af Wi‑Fi-logføring. Vis opdelt efter SSID RSSI i Wi‑Fi-vælgeren"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Når dette er aktiveret, gennemtvinges en overdragelse af dataforbindelsen fra Wi-Fi til mobilnetværk, når Wi-Fi-signalet er svagt"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillad/forbyd scanning i forbindelse med Wi-Fi-roaming afhængigt af mængden af datatrafik i grænsefladen"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Størrelser for Logger-buffer"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vælg Logger-størrelser pr. logbuffer"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index 4d53e2dd07bb..2fbac9315979 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netzwerke"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Kabellose Übertragung"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ausführliche WLAN-Protokolle aktivieren"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressives Handover von WLAN an Mobilfunk"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"WLAN-Roamingsuchen immer zulassen"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile Datennutzung immer aktiviert"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwarebeschleunigung für Tethering"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Hostname des DNS-Anbieters eingeben"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Optionen zur Zertifizierung für kabellose Übertragung anzeigen"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Level für WLAN-Protokollierung erhöhen, in WiFi Picker pro SSID-RSSI anzeigen"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wenn diese Option aktiviert ist, ist das WLAN bei schwachem Signal bei der Übergabe der Datenverbindung an den Mobilfunk aggressiver"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"WLAN-Roamingsuchen je nach Umfang des Datentraffics an der Schnittstelle zulassen bzw. nicht zulassen"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger-Puffergrößen"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Größe pro Protokollpuffer wählen"</string>
diff --git a/packages/SettingsLib/res/values-el/strings.xml b/packages/SettingsLib/res/values-el/strings.xml
index e5103564d0cc..25de91426de7 100644
--- a/packages/SettingsLib/res/values-el/strings.xml
+++ b/packages/SettingsLib/res/values-el/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Δικτύωση"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Πιστοποίηση ασύρματης οθόνης"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ενεργοποίηση λεπτομερ. καταγραφής Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Επιθ.μεταβ. Wi-Fi σε δίκτυο κιν.τηλ."</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Να επιτρέπεται πάντα η σάρωση Wi-Fi κατά την περιαγωγή"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Πάντα ενεργά δεδομένα κινητής τηλεφωνίας"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Σύνδεση επιτάχυνσης υλικού"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Εισαγάγετε το όνομα κεντρικού υπολογιστή του παρόχου DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Εμφάνιση επιλογών για πιστοποίηση ασύρματης οθόνης"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Αύξηση επιπέδου καταγ. Wi-Fi, εμφάνιση ανά SSID RSSI στο εργαλείο επιλογής Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Όταν είναι ενεργό, το Wi-Fi θα μεταβιβάζει πιο επιθετικά τη σύνδ.δεδομένων σε δίκτυο κινητής τηλ., όταν το σήμα Wi-Fi είναι χαμηλό"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Να επιτρέπεται/να μην επιτρέπεται η σάρωση Wi-Fi κατά την περιαγωγή, βάσει της ποσότητας επισκεψιμότητας δεδομένων στη διεπαφή"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Μέγεθος προσωρινής μνήμης για τη λειτουργία καταγραφής"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Μέγεθος αρχείων κατ/φής ανά προ/νή μνήμη αρχείου κατ/φής"</string>
diff --git a/packages/SettingsLib/res/values-en-rAU/strings.xml b/packages/SettingsLib/res/values-en-rAU/strings.xml
index a32238898bc7..9f5353f4b1cd 100644
--- a/packages/SettingsLib/res/values-en-rAU/strings.xml
+++ b/packages/SettingsLib/res/values-en-rAU/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rCA/strings.xml b/packages/SettingsLib/res/values-en-rCA/strings.xml
index a32238898bc7..9f5353f4b1cd 100644
--- a/packages/SettingsLib/res/values-en-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-en-rCA/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rGB/strings.xml b/packages/SettingsLib/res/values-en-rGB/strings.xml
index a32238898bc7..9f5353f4b1cd 100644
--- a/packages/SettingsLib/res/values-en-rGB/strings.xml
+++ b/packages/SettingsLib/res/values-en-rGB/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rIN/strings.xml b/packages/SettingsLib/res/values-en-rIN/strings.xml
index a32238898bc7..9f5353f4b1cd 100644
--- a/packages/SettingsLib/res/values-en-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-en-rIN/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wireless display certification"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Enable Wi‑Fi verbose logging"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressive Wi‑Fi to mobile handover"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Always allow Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobile data always active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Enter hostname of DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Show options for wireless display certification"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger buffer sizes"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Select Logger sizes per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-en-rXC/strings.xml b/packages/SettingsLib/res/values-en-rXC/strings.xml
index 80c2eb8b3eb1..a8561fab9f47 100644
--- a/packages/SettingsLib/res/values-en-rXC/strings.xml
+++ b/packages/SettingsLib/res/values-en-rXC/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‎‎‏‏‏‎‎‎‎‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‏‏‎‏‏‎‎‏‎‏‎‎‎‏‏‏‎‎‎‎‎‏‏‏‎‎‏‏‏‏‏‏‎‎Networking‎‏‎‎‏‎"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‏‏‎‎‎‎‎‏‎‎‏‏‏‎‎‎‎‏‏‎‏‏‏‏‏‏‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‎‏‎‏‏‎‎‎‎‏‏‎‏‎Wireless display certification‎‏‎‎‏‎"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‏‎‏‎‎‏‎‏‎‏‏‎‏‎‏‎‎‏‎‏‏‏‏‏‎‎‎‎‏‏‎‏‏‎‎‎‏‏‏‎‏‏‏‏‎‏‏‏‎‏‎‎‎‏‏‎‏‎‎‎‎Enable Wi‑Fi Verbose Logging‎‏‎‎‏‎"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‎‏‏‏‎‏‎‎‏‏‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‏‏‎‏‏‏‎‎‏‏‏‎‎‎‏‎‎‏‎‎‎‏‎‎‎‎Aggressive Wi‑Fi to mobile handover‎‏‎‎‏‎"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‏‎‎‎‏‏‏‏‏‏‏‎‎‎‏‎‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‎‎‏‏‎‎‎‏‏‎‏‏‎‏‏‎‎‎‏‎‏‏‏‎‏‎‎Always allow Wi‑Fi Roam Scans‎‏‎‎‏‎"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‎‏‏‎‏‎‎‎‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‎‏‏‏‎‎‏‏‎‏‏‏‎‎‏‎‎Mobile data always active‎‏‎‎‏‎"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‏‎‏‎‏‎‏‏‎‎‎‎‏‏‎‎‎‎‏‏‎‏‎‎‏‎‏‎‎‎‎‎‎‎‏‏‏‏‎‏‏‎‏‎‎‎‎‏‎‎‏‏‎‏‏‎‎Tethering hardware acceleration‎‏‎‎‏‎"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‎‏‎‎‎‎‏‎‏‎‏‎‏‏‎‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‎‏‎‏‏‏‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‎‏‏‏‏‎Enter hostname of DNS provider‎‏‎‎‏‎"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‎‎‎‎‏‎‎‎‎‎‎‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‎‏‎‏‎‎‏‎‏‏‎‎‏‏‎‎‎‎‏‏‎‏‎‏‎‏‏‏‎‏‎Show options for wireless display certification‎‏‎‎‏‎"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‎‏‏‎‏‏‏‏‎‎‏‏‎‏‎‏‏‏‎‏‎‎‏‎‎‏‎‏‏‎‎‎‏‏‎‎‏‎‎‎‎‏‏‎‏‏‏‏‏‎‎‏‎‎‏‏‏‏‎‏‏‎‎Increase Wi‑Fi logging level, show per SSID RSSI in Wi‑Fi Picker‎‏‎‎‏‎"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‎‎‏‏‎‏‎‏‏‏‎‎‏‏‎‎‎‎‎‏‎‏‎‎‎‎‏‎‎‏‏‏‎‎‎‎‎‏‎‏‏‎‎‏‎‎‏‏‎‏‎‎‏‏‏‎‏‏‎When enabled, Wi‑Fi will be more aggressive in handing over the data connection to mobile, when Wi‑Fi signal is low‎‏‎‎‏‎"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‎‏‏‎‎‏‎‎‎‏‏‎‏‎‎‏‎‎‎‎‎‎‎‎‎‏‏‎‎‏‎‏‏‎‎‎‏‏‏‏‏‎‎‏‏‎‎Allow/Disallow Wi‑Fi Roam Scans based on the amount of data traffic present at the interface‎‏‎‎‏‎"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‏‏‏‏‎‎‏‏‏‎‎‏‎‎‏‏‏‏‏‎‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‎‏‏‎‏‏‏‏‎‎‎‏‏‏‏‎‎‏‎‎‏‎‎‏‎‎‏‎‎‎Logger buffer sizes‎‏‎‎‏‎"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‏‎‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‏‏‏‏‏‏‎‏‎‎‏‏‏‎‎‏‎‎‏‎‏‏‎‎‏‏‏‏‏‎‎‏‏‏‏‏‎‏‎‎‎‎‎‏‎‏‎‏‎‏‏‎‎‎‎Select Logger sizes per log buffer‎‏‎‎‏‎"</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 65000b375d8f..eeaf18fdac07 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro detallado de Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Priorizar cambio de red Wi-Fi a móvil"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activados"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware de conexión mediante dispositivo portátil"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ingresa el nombre de host del proveedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones de certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar nivel de registro Wi-Fi; mostrar por SSID RSSI en el selector de Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si habilitas esta opción, se priorizará el cambio de Wi-Fi a datos móviles cuando la señal de Wi-Fi sea débil"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/no permitir las búsquedas de Wi-Fi basadas la cantidad de tráfico de datos presente en la interfaz"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selecciona el tamaño del Logger por búfer"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 2a5e41b536b0..97d9a1020967 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificación de pantalla inalámbrica"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Habilitar registro Wi-Fi detallado"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferencia agresiva de Wi-Fi a móvil"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir siempre búsquedas de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móviles siempre activos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración por hardware para conexión compartida"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce el nombre de host del proveedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opciones para la certificación de la pantalla inalámbrica"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar el nivel de registro de Wi-Fi, mostrar por SSID RSSI en el selector Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si se activa esta opción, la conexión Wi-Fi será más agresiva al pasar la conexión a datos móviles (si la señal Wi-Fi es débil)"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/No permitir búsquedas de Wi-Fi basadas en la cantidad de tráfico de datos presente en la interfaz"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de registrador"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Elige el tamaño del Logger por búfer"</string>
diff --git a/packages/SettingsLib/res/values-et/strings.xml b/packages/SettingsLib/res/values-et/strings.xml
index a8ac99f896ff..b680b843919a 100644
--- a/packages/SettingsLib/res/values-et/strings.xml
+++ b/packages/SettingsLib/res/values-et/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Võrgustik"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Juhtmeta ekraaniühenduse sertifitseerimine"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Luba WiFi paljusõnaline logimine"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agress. üleminek WiFi-lt mobiilsidele"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luba alati WiFi-rändluse skannimine"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilne andmeside on alati aktiivne"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Jagamise riistvaraline kiirendus"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Sisestage DNS-i teenusepakkuja hostinimi"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Juhtmeta ekraaniühenduse sertifitseerimisvalikute kuvamine"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Suurenda WiFi logimistaset, kuva WiFi valijas SSID RSSI järgi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kui seade on lubatud, asendatakse nõrga signaaliga WiFi-ühendus agressiivsemalt mobiilse andmesideühendusega"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Luba/keela WiFi-rändluse skannimine liidese andmeliikluse põhjal"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logija puhvri suurused"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Vali logija suur. logipuhvri kohta"</string>
diff --git a/packages/SettingsLib/res/values-eu/strings.xml b/packages/SettingsLib/res/values-eu/strings.xml
index 2c81f2ef5ace..ca8ea039919e 100644
--- a/packages/SettingsLib/res/values-eu/strings.xml
+++ b/packages/SettingsLib/res/values-eu/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Sareak"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Hari gabeko bistaratze-egiaztatzea"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Gaitu Wi-Fi sareetan saioa hasteko modu xehatua"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Behartu Wi-Fi konexiotik datuenera aldatzera"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Onartu beti ibiltaritzan Wi-Fi sareak bilatzea"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datu mugikorrak beti aktibo"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Konexioa partekatzeko hardwarearen azelerazioa"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Idatzi DNS hornitzailearen ostalari-izena"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Erakutsi hari gabeko bistaratze-egiaztapenaren aukerak"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Erakutsi datu gehiago Wi-Fi sareetan saioa hasterakoan. Erakutsi sarearen identifikatzailea eta seinalearen indarra Wi‑Fi sareen hautagailuan."</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Aukera hori gaituz gero, gailua nahitaez aldatuko da datu mugikorren konexiora Wi-Fi seinalea ahultzen dela nabaritutakoan"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Onartu edo debekatu ibiltaritzan Wi-Fi sareak bilatzea, interfazeko datu-trafikoaren arabera"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Erregistroen buffer-tamainak"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Hautatu erregistroen buffer-tamainak"</string>
diff --git a/packages/SettingsLib/res/values-fa/strings.xml b/packages/SettingsLib/res/values-fa/strings.xml
index 4f3c77f7e9da..675e3827731b 100644
--- a/packages/SettingsLib/res/values-fa/strings.xml
+++ b/packages/SettingsLib/res/values-fa/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"شبکه"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"گواهینامه نمایش بی‌سیم"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"‏فعال کردن گزارش‌گیری طولانی Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏Wi‑Fi قوی برای واگذاری به دستگاه همراه"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏اسکن‌های رومینگ Wi‑Fi همیشه مجاز است"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"داده تلفن همراه همیشه فعال باشد"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"شتاب سخت‌افزاری اتصال به اینترنت با تلفن همراه"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏نام میزبان ارائه‌دهنده DNS خصوصی را وارد کنید"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"نمایش گزینه‌ها برای گواهینامه نمایش بی‌سیم"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏افزایش سطح گزارش‌گیری Wi‑Fi، نمایش به ازای SSID RSSI در انتخاب‌کننده Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏زمانی‌که فعال است، درشرایطی که سیگنال Wi-Fi ضعیف باشد، Wi‑Fi برای واگذاری اتصال داده به دستگاه همراه قوی‌تر عمل خواهد کرد."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏مجاز/غیرمجاز کردن اسکن‌های رومینگ Wi‑Fi براساس مقدار ترافیک داده موجود در واسط"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"اندازه‌های حافظه موقت ثبت‌کننده"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"انتخاب اندازه‌ ثبت‌کننده در حافظه موقت ثبت"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index 5932d00afb0f..ba7fcd39ca3a 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Yhteysominaisuudet"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Langattoman näytön sertifiointi"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Käytä Wi-Fin laajennettua lokikirjausta"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Vaihda herkästi Wi-Fi mobiiliyhteyteen"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Salli Wi-Fi-verkkovierailuskannaus aina"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiilidata aina käytössä"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Laitteistokiihdytyksen yhteyden jakaminen"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Anna isäntänimi tai DNS-tarjoaja."</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Näytä langattoman näytön sertifiointiin liittyvät asetukset"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Lisää Wi‑Fin lokikirjaustasoa, näytä SSID RSSI -kohtaisesti Wi‑Fi-valitsimessa."</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kun asetus on käytössä, datayhteys siirtyy helpommin Wi-Fistä matkapuhelinverkkoon, jos Wi-Fi-signaali on heikko."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Salli/estä Wi-Fi-verkkovierailuskannaus liittymässä esiintyvän dataliikenteen perusteella."</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Lokipuskurien koot"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Valitse puskurikohtaiset lokikoot"</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index c0c29d3236fd..f266e2ddb725 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Réseautage"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. données Wi-Fi détaillées"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Passage forcé du Wi-Fi aux données cell."</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Données cellulaires toujours actives"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Entrez le nom d\'hôte du fournisseur DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options pour la certification d\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler davantage les données Wi-Fi, afficher par SSID RSSI dans sélect. Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si cette option est activée, le passage du Wi-Fi aux données cellulaires est forcé lorsque le signal Wi-Fi est faible"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du transfert de données dans l\'interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tailles des mémoires tampons d\'enregistreur"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
diff --git a/packages/SettingsLib/res/values-fr/strings.xml b/packages/SettingsLib/res/values-fr/strings.xml
index 50c99e2a558e..87f00d151e18 100644
--- a/packages/SettingsLib/res/values-fr/strings.xml
+++ b/packages/SettingsLib/res/values-fr/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Mise en réseau"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certification affichage sans fil"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Autoriser enreg. infos Wi-Fi détaillées"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Passage forcé Wi-Fi vers données mobiles"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Toujours autoriser la détection de réseaux Wi-Fi en itinérance"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Données mobiles toujours actives"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accélération matérielle pour le partage de connexion"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Saisissez le nom d\'hôte du fournisseur DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afficher les options de la certification de l\'affichage sans fil"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Détailler plus infos Wi-Fi, afficher par RSSI de SSID dans outil sélection Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Si cette option est activée, le passage du Wi-Fi aux données mobiles est forcé en cas de signal Wi-Fi faible."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Autoriser ou non la détection de réseaux Wi-Fi en itinérance en fonction de l\'importance du trafic de données dans l\'interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tailles mémoires tampons enregistr."</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Tailles enreg. par tampon journal"</string>
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 775bbf1a9bbd..9026aaba9f68 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificado de visualización sen fíos"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Activar rexistro detallado da wifi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Transferencia agresiva de wifi a móbil"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre buscas de itinerancia da wifi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Datos móbiles sempre activados"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleración de hardware para conexión compartida"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduce o nome de host de provedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opcións para o certificado de visualización sen fíos"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nivel de rexistro da wifi, mostrar por SSID RSSI no selector de wifi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Cando estea activada esta función, a wifi será máis agresiva ao transferir a conexión de datos ao móbil cando o sinal wifi sexa feble"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/Non permitir buscas de itinerancia da wifi baseadas na cantidade de tráfico de datos presente na interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamaños de búfer de rexistrador"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleccionar tamaños por búfer"</string>
diff --git a/packages/SettingsLib/res/values-gu/strings.xml b/packages/SettingsLib/res/values-gu/strings.xml
index 712e57eb09da..b1ee90b2c6b0 100644
--- a/packages/SettingsLib/res/values-gu/strings.xml
+++ b/packages/SettingsLib/res/values-gu/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"નેટવર્કિંગ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"વાયરલેસ ડિસ્પ્લે પ્રમાણન"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"વાઇ-ફાઇ વર્બોઝ લૉગિંગ સક્ષમ કરો"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"સશક્ત Wi‑Fiથી મોબાઇલ પર હૅન્ડઓવર"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"હંમેશા વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"મોબાઇલ ડેટા હંમેશાં સક્રિય"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ટિથરિંગ માટે હાર્ડવેર ગતિવૃદ્ધિ"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS પ્રદાતાના હોસ્ટનું નામ દાખલ કરો"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"વાયરલેસ ડિસ્પ્લે પ્રમાણપત્ર માટેના વિકલ્પો બતાવો"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"વાઇ-ફાઇ લોગિંગ સ્તર વધારો, વાઇ-ફાઇ પીકરમાં SSID RSSI દીઠ બતાવો"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"જ્યારે સક્ષમ કરેલ હોય, ત્યારે વાઇ-ફાઇ સિગ્નલ નબળું હોવા પર, વાઇ-ફાઇ વધુ ઝડપથી ડેટા કનેક્શનને મોબાઇલ પર મોકલશે"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ઇન્ટરફેસ પર હાજર ડેટા ટ્રાફિકના પ્રમાણનાં આધારે વાઇ-ફાઇ રોમ સ્કૅન્સને મંજૂરી આપો/નામંજૂર કરો"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"લોગર બફર કદ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"લૉગ દીઠ લૉગર કદ બફર પસંદ કરો"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index a88abb5a7fa8..e235fc5b7741 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस दिखाई देने के लिए प्रमाणन"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"वाई-फ़ाई वर्बोस लॉगिंग चालू करें"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"वाई-फ़ाई से मोबाइल पर ज़्यादा तेज़ी से हैंडओवर"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"हमेशा वाई-फ़ाई रोम स्कैन करने दें"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा हमेशा सक्रिय"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"हार्डवेयर से तेज़ी लाने के लिए टेदर करें"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS सेवा देने वाले का होस्टनाम डालें"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस दिखाई देने के लिए प्रमाणन विकल्प दिखाएं"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाई-फ़ाई प्रवेश स्तर बढ़ाएं, वाई-फ़ाई पिकर में प्रति SSID RSSI दिखाएं"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"इसके सक्षम होने पर, जब वाई-फ़ाई संकेत कमज़ोर हों तो वाई-फ़ाई, डेटा कनेक्शन को मोबाइल पर ज़्यादा तेज़ी से भेजेगा"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"इंटरफ़ेस पर वर्तमान में मौजूद डेटा ट्रैफ़िक के आधार पर वाई-फ़ाई रोम स्कैन करने देता/नहीं देता है"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफ़र आकार"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफ़र लॉगर आकार चुनें"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index a417cc153f77..a8549872146f 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Umrežavanje"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikacija bežičnog prikaza"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogući opširnu prijavu na Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aktivni prijelaz s Wi‑Fi na mob. mrežu"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Uvijek dopusti slobodno traženje Wi-Fi mreže"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilni podaci uvijek aktivni"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardversko ubrzanje za modemsko povezivanje"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Unesite naziv hosta davatelja usluge DNS-a"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Prikaži opcije za certifikaciju bežičnog prikaza"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povećana razina prijave na Wi‑Fi, prikaz po SSID RSSI-ju u Biraču Wi‑Fi-ja"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ako je omogućeno, Wi-Fi će aktivno prebacivati podatkovnu vezu mobilnoj mreži kada je Wi-Fi signal slab."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Dopustite ili blokirajte slobodno traženje Wi-Fi mreža na temelju količine podatkovnog prometa na sučelju."</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Veličine međuspremnika zapisnika"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Odaberite veličinu međuspremnika zapisnika"</string>
diff --git a/packages/SettingsLib/res/values-hu/strings.xml b/packages/SettingsLib/res/values-hu/strings.xml
index b6f1460a7ba5..553ed88d779e 100644
--- a/packages/SettingsLib/res/values-hu/strings.xml
+++ b/packages/SettingsLib/res/values-hu/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Hálózatok"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Vezeték nélküli kijelző tanúsítványa"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Részletes Wi-Fi-naplózás engedélyezése"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresszív Wi‑Fi–mobilhálózat átadás"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi-roaming ellenőrzésének engedélyezése mindig"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"A mobilhálózati kapcsolat mindig aktív"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Internetmegosztás hardveres gyorsítása"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Adja meg a DNS-szolgáltató gazdagépnevét"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vezeték nélküli kijelző tanúsítványával kapcsolatos lehetőségek megjelenítése"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-naplózási szint növelése, RSSI/SSID megjelenítése a Wi‑Fi-választóban"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ha engedélyezi, a Wi-Fi agresszívebben fogja átadni az adatkapcsolatot a mobilhálózatnak gyenge Wi-Fi-jel esetén"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"A Wi-Fi-roaming ellenőrzésének engedélyezése vagy letiltása az interfészen jelen lévő adatforgalom mennyiségétől függően"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Naplózási puffer mérete"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Naplózási pufferméret kiválasztása"</string>
diff --git a/packages/SettingsLib/res/values-hy/strings.xml b/packages/SettingsLib/res/values-hy/strings.xml
index 3ba3f453a361..dced49f50fa3 100644
--- a/packages/SettingsLib/res/values-hy/strings.xml
+++ b/packages/SettingsLib/res/values-hy/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Ցանց"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Անլար էկրանի վկայագրում"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Միացնել Wi‑Fi մանրամասն գրանցամատյանները"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi-ից կտրուկ անցում բջջային ինտերնետի"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Միշտ թույլատրել Wi‑Fi ռոումինգի որոնումը"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Բջջային ինտերնետը միշտ ակտիվ է"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Սարքակազմի արագացման միացում"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Մուտքագրեք DNS ծառայության մատակարարի խնամորդի անունը"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ցույց տալ անլար էկրանի հավաստագրման ընտրանքները"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Բարձրացնել մակարդակը, Wi‑Fi ընտրիչում ամեն մի SSID-ի համար ցույց տալ RSSI"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Եթե այս գործառույթը միացված է, Wi-Fi-ի թույլ ազդանշանի դեպքում Wi‑Fi ինտերնետից բջջային ինտերնետի անցումը ավելի կտրուկ կկատարվի"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Թույլատրել/արգելել Wi‑Fi ռոումինգի որոնումը՝ կախված միջերեսում տվյալների երթևեկի ծավալից"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Տեղեկամատյանի պահնակի չափերը"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ընտրեք տեղեկամատյանի չափը մեկ պահնակի համար"</string>
diff --git a/packages/SettingsLib/res/values-in/strings.xml b/packages/SettingsLib/res/values-in/strings.xml
index 2bb9ae0f3e1f..5c067663970a 100644
--- a/packages/SettingsLib/res/values-in/strings.xml
+++ b/packages/SettingsLib/res/values-in/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Jaringan"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Sertifikasi layar nirkabel"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktifkan Pencatatan Log Panjang Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Pengalihan Wi-Fi Agresif ke seluler"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Selalu izinkan Pemindaian Roaming Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Data seluler selalu aktif"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Akselerasi hardware tethering"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan hostname penyedia DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tampilkan opsi untuk sertifikasi layar nirkabel"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan level pencatatan log Wi-Fi, tampilkan per SSID RSSI di Pemilih Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Jika diaktifkan, Wi-Fi akan menjadi lebih agresif dalam mengalihkan sambungan data ke seluler saat sinyal Wi-Fi lemah"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Izinkan/Larang Pemindaian Roaming Wi-Fi berdasarkan jumlah lalu lintas data yang ada di antarmuka"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Ukuran penyangga pencatat log"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Ukuran Pencatat Log per penyangga log"</string>
diff --git a/packages/SettingsLib/res/values-is/strings.xml b/packages/SettingsLib/res/values-is/strings.xml
index 311227f35875..21b8b0ed2975 100644
--- a/packages/SettingsLib/res/values-is/strings.xml
+++ b/packages/SettingsLib/res/values-is/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netkerfi"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Vottun þráðlausra skjáa"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Kveikja á ítarlegri skráningu Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Hröð skipti úr Wi‑Fi í farsímagögn"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Leyfa alltaf reikileit með Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Alltaf kveikt á farsímagögnum"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Vélbúnaðarhröðun fyrir tjóðrun"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Slá inn hýsilheiti DNS-veitu"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Sýna valkosti fyrir vottun þráðlausra skjáa"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Auka skráningarstig Wi-Fi, sýna RSSI fyrir hvert SSID í Wi-Fi vali"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Þegar þetta er virkt mun Wi-Fi skipta hraðar yfir í farsímagagnatengingu þegar Wi-Fi-tenging er léleg"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leyfa/banna reikileit með Wi-Fi á grunni þess hversu mikil gagnaumferð er fyrir hendi í viðmótinu"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Annálsritastærðir biðminna"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veldu annálsritastærðir á biðminni"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index b63232d7a6a6..7408b25f7d10 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Reti"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificazione display wireless"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Attiva registrazione dettagliata Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi aggressivo per passaggio a cellulare"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Consenti sempre scansioni roaming Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dati mobili sempre attivi"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering accelerazione hardware"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Inserisci il nome host del provider DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostra opzioni per la certificazione display wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumenta il livello di registrazione Wi-Fi, mostrando il SSID RSSI nel selettore Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Con questa impostazione attivata, il Wi-Fi è più aggressivo nel passare la connessione dati al cellulare, con segnale Wi-Fi basso"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Consenti/vieta scansioni roaming Wi-Fi basate sulla quantità di traffico dati presente a livello di interfaccia"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Dimensioni buffer Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Seleziona dimensioni Logger per buffer log"</string>
diff --git a/packages/SettingsLib/res/values-iw/strings.xml b/packages/SettingsLib/res/values-iw/strings.xml
index 538da919c798..fceaacc0b7b6 100644
--- a/packages/SettingsLib/res/values-iw/strings.xml
+++ b/packages/SettingsLib/res/values-iw/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"תקשורת רשתות"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"‏אישור של תצוגת WiFi"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"‏הפעל רישום מפורט של Wi‑Fi ביומן"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏העברה אגרסיבית מ-Wi‑Fi לרשת סלולרית"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏התר תמיד סריקות נדידה של Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"חבילת הגלישה פעילה תמיד"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"שיפור מהירות באמצעות חומרה לצורך שיתוף אינטרנט בין ניידים"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏צריך להזין את שם המארח של ספק DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"‏הצג אפשרויות עבור אישור של תצוגת WiFi"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏העלה את רמת הרישום של Wi‑Fi ביומן, הצג לכל SSID RSSI ב-Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏כשאפשרות זו מופעלת, Wi-Fi יתנהג בצורה אגרסיבית יותר בעת העברת חיבור הנתונים לרשת הסלולרית כשאות ה-Wi-Fi חלש."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏התר/מנע סריקות נדידה של Wi-Fi בהתבסס על נפח תנועת הנתונים הקיימת בממשק"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"גדלי מאגר של יומן רישום"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"בחר גדלים של יוצר יומן לכל מאגר יומן"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index db1baa1188c0..671320bc9444 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ネットワーク"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ワイヤレスディスプレイ認証"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi詳細ログの有効化"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi を強制的にモバイル接続に切り替える"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fiローミングスキャンを常に許可する"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"モバイルデータを常に ON にする"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"テザリング時のハードウェア アクセラレーション"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS プロバイダのホスト名を入力"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ワイヤレスディスプレイ認証のオプションを表示"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fiログレベルを上げて、Wi-Fi選択ツールでSSID RSSIごとに表示します"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ON にすると、Wi-Fi の電波強度が弱い場合は強制的にモバイルデータ接続に切り替わるようになります"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"インターフェースのデータトラフィック量に基づいたWi-Fiローミングスキャンを許可するかしないかを設定できます"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ログバッファのサイズ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"各ログバッファのログサイズを選択"</string>
diff --git a/packages/SettingsLib/res/values-ka/strings.xml b/packages/SettingsLib/res/values-ka/strings.xml
index 00eaf84733d4..1948460ff731 100644
--- a/packages/SettingsLib/res/values-ka/strings.xml
+++ b/packages/SettingsLib/res/values-ka/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ქსელი"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"უსადენო ეკრანის სერტიფიცირება"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi-ს დაწვრილებითი აღრიცხვის ჩართვა"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi-ს მობ. ინტერნეტზე აგრესიული გადართვა"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Roam სკანირების მუდამ დაშვება"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"მობილური ინტერნეტის ყოველთვის გააქტიურება"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ტეტერინგის აპარატურული აჩქარება"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"შეიყვანეთ DNS პროვაიდერის სერვერის სახელი"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"უსადენო ეკრანის სერტიფიცირების ვარიანტების ჩვენება"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi-ს აღრიცხვის დონის გაზრდა, Wi‑Fi ამომრჩეველში ყოველ SSID RSSI-ზე ჩვენება"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ჩართვის შემთხვევაში, Wi‑Fi უფრო აქტიურად შეეცდება მობილურ ინტერნეტზე გადართვას, როცა Wi‑Fi სიგნალი სუსტია"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wifi Roam სკანირების დაშვება/აკრძალვა, ინტერფეისზე არსებული მონაცემთა ტრაფიკზე დაფუძნებით"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ჟურნალიზაციის ბუფერის ზომები"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"აირჩიეთ ჟურნ. ზომა / ჟურნ. ბუფერზე"</string>
diff --git a/packages/SettingsLib/res/values-kk/strings.xml b/packages/SettingsLib/res/values-kk/strings.xml
index a318bd88a8f0..2d03f7f82bc8 100644
--- a/packages/SettingsLib/res/values-kk/strings.xml
+++ b/packages/SettingsLib/res/values-kk/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Желі орнату"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сымсыз дисплей сертификаты"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi егжей-тегжейлі журналға тір. қосу"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi желісінен мобильдік желіге ауысу"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi роумингін іздеулерге әрқашан рұқсат ету"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобильдік деректер әрқашан қосулы"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингтің аппараттық жеделдетуі"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS провайдерінің хост атауын енгізіңіз"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Сымсыз дисплей растау опцияларын көрсету"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi жур. тір. дең. арт., Wi‑Fi желісін таңдағышта әр SSID RSSI бойынша көрсету"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Wi‑Fi сигналы әлсіз болғанда, деректер байланысы мәжбүрлі түрде мобильдік желіге ауысады"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейсте бар деректер трафигінің мөлшерінің негізінде Wi-Fi роумингін іздеулерге рұқсат ету/тыйым салу"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Журналға тіркеуші буферінің өлшемдері"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Әр журнал буфері үшін журналға тіркеуші өлшемдерін таңдау"</string>
diff --git a/packages/SettingsLib/res/values-km/strings.xml b/packages/SettingsLib/res/values-km/strings.xml
index ae473187219b..1d2476cf6ca8 100644
--- a/packages/SettingsLib/res/values-km/strings.xml
+++ b/packages/SettingsLib/res/values-km/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ការភ្ជាប់បណ្ដាញ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"បង្ហាញ​ការ​កំណត់​រចនាសម្ព័ន្ធ​ឥត​ខ្សែ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"បើក​កំណត់ហេតុ​រៀបរាប់​វ៉ាយហ្វាយ"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ប្តូរទៅប្រើបណ្តាញចល័តពេល Wi‑Fi មានរលកសញ្ញាខ្លាំងពេក"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"តែងតែ​អនុញ្ញាត​​​ការវិភាគ​រ៉ូម​វ៉ាយហ្វាយ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ទិន្នន័យទូរសព្ទចល័តដំណើរការជានិច្ច"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ការ​បង្កើនល្បឿន​ផ្នែករឹងសម្រាប់​ការភ្ជាប់"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"បញ្ចូលឈ្មោះម៉ាស៊ីនរបស់ក្រុមហ៊ុនផ្ដល់សេវា DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"បង្ហាញ​ជម្រើស​សម្រាប់​វិញ្ញាបនបត្រ​បង្ហាញ​ឥត​ខ្សែ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"បង្កើនកម្រិតកំណត់ហេតុវ៉ាយហ្វាយបង្ហាញក្នុង SSID RSSI ក្នុងកម្មវិធីជ្រើស​វ៉ាយហ្វាយ"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"នៅពេលដែលបើក នោះ Wi‑Fi នឹងផ្តល់ការតភ្ជាប់ទិន្នន័យយ៉ាងគំហុកទៅបណ្តាញទូរសព្ទចល័ត នៅពេលរលកសញ្ញា Wi‑Fi ចុះខ្សោយ។"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"អនុញ្ញាត/មិន​អនុញ្ញាត​ការ​វិភាគ​រ៉ូម​​វ៉ាយហ្វាយ​ផ្អែក​លើ​​​ចំនួន​ការ​បង្ហាញ​ចរាចរណ៍​ទិន្នន័យ​​នៅ​ចំណុច​ប្រទាក់"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ទំហំ buffer របស់ Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ជ្រើស​ទំហំ Logger per log buffer"</string>
diff --git a/packages/SettingsLib/res/values-kn/strings.xml b/packages/SettingsLib/res/values-kn/strings.xml
index fbabb627ce4d..385308aafab3 100644
--- a/packages/SettingsLib/res/values-kn/strings.xml
+++ b/packages/SettingsLib/res/values-kn/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ನೆಟ್‌ವರ್ಕಿಂಗ್"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ವೈರ್‌ಲೆಸ್ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi ವೆರ್ಬೋಸ್ ಲಾಗಿಂಗ್ ಸಕ್ರಿಯಗೊಳಿಸಿ"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ವೈ-ಫೈನಿಂದ ಮೊಬೈಲ್‌ಗೆ ಆಕ್ರಮಣಕಾರಿ ಹಸ್ತಾಂತರ"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ವೈ-ಫೈ ರೋಮ್ ಸ್ಕ್ಯಾನ್‌ಗಳನ್ನು ಯಾವಾಗಲೂ ಅನುಮತಿಸಿ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ಮೊಬೈಲ್ ಡೇಟಾ ಯಾವಾಗಲೂ ಸಕ್ರಿಯ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ಹಾರ್ಡ್‌ವೇರ್‌ನ ವೇಗವರ್ಧನೆಯನ್ನು ಟೆಥರಿಂಗ್ ಮಾಡಿ"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ಪೂರೈಕೆದಾರರ ಹೋಸ್ಟ್‌ಹೆಸರನ್ನು ನಮೂದಿಸಿ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ವೈರ್‌ಲೆಸ್‌‌‌ ಪ್ರದರ್ಶನ ಪ್ರಮಾಣೀಕರಣಕ್ಕಾಗಿ ಆಯ್ಕೆಗಳನ್ನು ತೋರಿಸು"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ಲಾಗಿಂಗ್ ಮಟ್ಟನ್ನು ಹೆಚ್ಚಿಸಿ, Wi‑Fi ಆಯ್ಕೆಯಲ್ಲಿ ಪ್ರತಿಯೊಂದು SSID RSSI ತೋರಿಸಿ"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ಇದು ಸಕ್ರಿಯಗೊಂಡರೆ, ವೈ-ಫೈ ಸಿಗ್ನಲ್ ದುರ್ಬಲವಾಗಿದ್ದಾಗ, ಮೊಬೈಲ್‌ಗೆ ಡೇಟಾ ಸಂಪರ್ಕವನ್ನು ಹಸ್ತಾಂತರಿಸುವಲ್ಲಿ ವೈ-ಫೈ ಹೆಚ್ಚು ಆಕ್ರಮಣಕಾರಿಯಾಗಿರುತ್ತದೆ"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ಇಂಟರ್‌ಫೇಸ್‌ನಲ್ಲಿ ಲಭ್ಯವಿರುವ ಡೇಟಾ ಟ್ರಾಫಿಕ್ ಆಧಾರದ ಮೇಲೆ Wi‑Fi ರೋಮ್ ಸ್ಕ್ಯಾನ್‌ಗಳನ್ನು ಅನುಮತಿಸಿ/ನಿರಾಕರಿಸಿ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ಲಾಗರ್ ಬಫರ್ ಗಾತ್ರಗಳು"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ಪ್ರತಿ ಲಾಗ್ ಬಫರ್‌ಗೆ ಲಾಗರ್ ಗಾತ್ರಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ"</string>
diff --git a/packages/SettingsLib/res/values-ko/strings.xml b/packages/SettingsLib/res/values-ko/strings.xml
index 4b7d0a4cd680..e1be8dc01d83 100644
--- a/packages/SettingsLib/res/values-ko/strings.xml
+++ b/packages/SettingsLib/res/values-ko/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"네트워크"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"무선 디스플레이 인증서"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi 상세 로깅 사용"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"적극적인 Wi-Fi-모바일 핸드오버"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi 로밍 스캔 항상 허용"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"항상 모바일 데이터 활성화"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"테더링 하드웨어 가속"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS 제공업체의 호스트 이름 입력"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"무선 디스플레이 인증서 옵션 표시"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi 로깅 수준을 높이고, Wi‑Fi 선택도구에서 SSID RSSI당 값을 표시합니다."</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"사용 설정하면 Wi-Fi 신호가 약할 때 데이터 연결을 Wi-Fi에서 모바일 네트워크로 더욱 적극적으로 핸드오버합니다."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"인터페이스에 표시되는 데이터 트래픽의 양을 기반으로 Wi-Fi 로밍 스캔을 허용하거나 허용하지 않습니다."</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"로거 버퍼 크기"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"로그 버퍼당 로거 크기 선택"</string>
diff --git a/packages/SettingsLib/res/values-ky/strings.xml b/packages/SettingsLib/res/values-ky/strings.xml
index 98ca36a6a2d2..d323df2e8405 100644
--- a/packages/SettingsLib/res/values-ky/strings.xml
+++ b/packages/SettingsLib/res/values-ky/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Тармактык байланыштарды кеңейтүү"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Зымсыз дисплейди аныктоо"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi дайын-даректүү протоколун иштетүү"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi начар болсо, мобилдик Инт-ке өтсүн"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi Роуминг Скандоо мүмкүнчүлүгүнө ар дайым уруксат берилсин"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилдик Интернет иштей берсин"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Тетерингдин иштешин тездетүү"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS түйүндүн аталышын киргизиңиз"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Зымсыз дисплейди сертификатто мүмкүнчүлүктөрүн көргөзүү"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi Кармагычта Wi‑Fi протокол деңгээлин жогорулатуу жана ар бир SSID RSSI үчүн көрсөтүү."</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Иштетилсе, Wi-Fi байланышы үзүл-кесил болуп жатканда, Wi-Fi тармагы туташууну мобилдик Интернетке өжөрлүк менен өткөрүп берет"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфейстеги дайындар трафигинин көлөмүнө жараша Wi-Fi Роуминг скандоо мүмкүнчүлүгүн иштетүү/өчүрүү"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Каттагыч буферлеринин өлчөмдөрү"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Каттоо буфери үчүн Каттагычтын көлөмүн тандаңыз"</string>
diff --git a/packages/SettingsLib/res/values-lo/strings.xml b/packages/SettingsLib/res/values-lo/strings.xml
index 6de2a2e95f75..1e58af1c7cd0 100644
--- a/packages/SettingsLib/res/values-lo/strings.xml
+++ b/packages/SettingsLib/res/values-lo/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ການ​ສ້າງເຄືອຂ່າຍ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ສະແດງການຮັບຮອງຂອງລະບົບໄຮ້ສາຍ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"​ເປີດ​ນຳ​ໃຊ້ການ​ເກັບ​ປະ​ຫວັດ​ Verbose Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ສະຫຼັບເປັນ Wi-Fi ເມື່ອມືຖືສັນຍານອ່ອນ"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ອະ​ນຸ​ຍາດ​ການ​ສະ​ແກນ​ການ​ໂຣມ Wi‑Fi ​ສະ​ເໝີ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ເປີດໃຊ້ອິນເຕີເນັດມືຖືຕະຫຼອດເວລາ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ເປີດໃຊ້ການເລັ່ງຄວາມໄວດ້ວຍຮາດແວ"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ລະບຸຊື່ໂຮສຂອງຜູ້ໃຫ້ບໍລິການ DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ສະແດງໂຕເລືອກສຳລັບການສະແດງການຮັບຮອງລະບົບໄຮ້ສາຍ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ເພີ່ມ​ລະ​ດັບ​ການ​ເກັບ​ປະ​ຫວັດ Wi‑Fi, ສະ​ແດງ​ຕໍ່ SSID RSSI ​ໃນ​ Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ເມື່ອເປີດໃຊ້ແລ້ວ, Wi-Fi ຈະສົ່ງຜ່ານການເຊື່ອມຕໍ່ຂໍ້ມູນໄປຫາເຄືອຂ່າຍມືຖືເມື່ອສັນຍານ Wi-Fi ອ່ອນ"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"​ອະ​ນຸ​ຍາດ/ບໍ່​ອະ​ນຸ​ຍາດການ​ສະ​ແກນ​ການ​ໂຣມ Wi-Fi ອີງ​ຕາມ​ຈຳ​ນວນ​ຂໍ້​ມູນທີ່​ເກີດ​ຂຶ້ນ​ໃນ​ລະ​ດັບ​ສ່ວນ​ຕິດ​ຕໍ່"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ຂະ​ໜາດ​​ບັບ​ເຟີໂຕ​ລັອກ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ເລືອກ​ຂະ​ໜາດ​ລັອກ​ຕໍ່​ບັບ​ເຟີ"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 66fa62a89723..a35cd3c7be50 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Tinklai"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Belaidžio rodymo sertifikavimas"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Įgal. „Wi‑Fi“ daugiaž. įraš. į žurnalą"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agres. „Wi‑Fi“ perd. į mob. r. tinklą"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Visada leisti „Wi-Fi“ tarptiklinio ryšio nuskaitymą"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiliojo ryšio duomenys visada suaktyvinti"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Įrenginio kaip modemo naudojimo aparatinės įrangos spartinimas"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Įveskite DNS teikėjo prieglobos serverio pavadinimą"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rodyti belaidžio rodymo sertifikavimo parinktis"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Padidinti „Wi‑Fi“ įrašymo į žurnalą lygį, rodyti SSID RSSI „Wi-Fi“ rinkiklyje"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Jei ši parinktis įgalinta, „Wi‑Fi“ agresyviau perduos duomenų ryšiu į mobiliojo ryšio tinklą, kai „Wi‑Fi“ signalas silpnas"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Leisti / neleisti „Wi‑Fi“ tarptinklinio ryšio nuskaitymo, atsižvelgiant į sąsajos duomenų srauto kiekį"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Registruotuvo buferio dydžiai"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pasir. registr. dydž. žurn. bufer."</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index f32accddfc99..8239d9f62042 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Tīklošana"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Bezvadu attēlošanas sertifikācija"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Iespējot Wi‑Fi detalizēto reģistrēšanu"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresīva pāreja no Wi‑Fi uz mobilo tīklu"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vienmēr atļaut Wi‑Fi meklēšanu"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Vienmēr aktīvs mobilo datu savienojums"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Paātrināta aparatūras darbība piesaistei"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ievadiet DNS pakalpojumu sniedzēja saimniekdatora nosaukumu"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Rādīt bezvadu attēlošanas sertifikācijas iespējas"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Palieliniet Wi‑Fi reģistrēšanas līmeni; rādīt katram SSID RSSI Wi‑Fi atlasītājā."</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ja opcija ir iespējota un Wi‑Fi signāls ir vājš, datu savienojuma pāreja no Wi-Fi uz mobilo tīklu tiks veikta agresīvāk."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Atļaujiet/neatļaujiet Wi‑Fi meklēšanu, pamatojoties uz saskarnē saņemto datplūsmas apjomu."</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Reģistrētāja buferu lielumi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Atlasīt reģistrētāja bufera liel."</string>
diff --git a/packages/SettingsLib/res/values-mk/strings.xml b/packages/SettingsLib/res/values-mk/strings.xml
index 3151f5677008..eaa553903a32 100644
--- a/packages/SettingsLib/res/values-mk/strings.xml
+++ b/packages/SettingsLib/res/values-mk/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Вмрежување"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Приказ на сертификација на безжична мрежа"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Овозможи преопширно пријавување Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Агресивно предавање од Wi‑Fi на мобилен"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Секогаш дозволувај Wi‑Fi скенирање во роаминг"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилниот интернет е секогаш активен"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско забрзување за врзување"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Внесете име на хост на операторот на DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Покажи ги опциите за безжичен приказ на сертификат"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Зголеми Wi‑Fi ниво на пријавување, прикажи по SSID RSSI во Wi‑Fi бирач"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Кога е овозможено, Wi-Fi ќе биде поагресивна при предавање на интернет-врската на мобилната мрежа при слаб сигнал на Wi-Fi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/Забрани Wi‑Fi скенирање во роаминг според количината на постоечкиот податочен сообраќај на интерфејсот."</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Величини на меѓумеморија на забележувач"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Величина/меѓумеморија на дневник"</string>
diff --git a/packages/SettingsLib/res/values-ml/strings.xml b/packages/SettingsLib/res/values-ml/strings.xml
index 2b86e509fb05..0ddfc793312e 100644
--- a/packages/SettingsLib/res/values-ml/strings.xml
+++ b/packages/SettingsLib/res/values-ml/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"നെറ്റ്‍വര്‍ക്കിംഗ്"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"വയർലെസ് ഡിസ്‌പ്ലേ സർട്ടിഫിക്കേഷൻ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"വൈഫൈ വെർബോസ് ലോഗിംഗ് പ്രവർത്തനക്ഷമമാക്കുക"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"മൊബൈൽ ഹാൻഡ്ഓവറിലേക്ക് വൈഫൈ സക്രിയമാക്കുക"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"എപ്പോഴും വൈഫൈ റോം സ്‌‌കാൻ അനുവദിക്കൂ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"മൊബൈൽ ഡാറ്റ എല്ലായ്‌പ്പോഴും സജീവം"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ടെതറിംഗ് ഹാർഡ്‌വെയർ ത്വരിതപ്പെടുത്തൽ"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ദാതാവിന്‍റെ ഹോസ്റ്റുനാമം നൽകുക"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"വയർലെസ് ഡിസ്‌പ്ലേ സർട്ടിഫിക്കേഷനായി ഓപ്‌ഷനുകൾ ദൃശ്യമാക്കുക"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"വൈഫൈ പിക്കറിൽ ഓരോ SSID RSSI പ്രകാരം കാണിക്കാൻ വൈഫൈ ലോഗിംഗ് നില വർദ്ധിപ്പിക്കുക"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"പ്രവർത്തനക്ഷമമായിരിക്കുമ്പോൾ, വൈഫൈ സിഗ്‌നൽ കുറവായിരിക്കുന്ന സമയത്ത് മൊബൈലിലേക്ക് ഡാറ്റ കണക്ഷൻ വഴി കൈമാറുന്നതിൽ വൈഫൈ കൂടുതൽ സക്രിയമായിരിക്കും"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ഇന്റർഫേസിലെ ഡാറ്റ ട്രാഫിക്ക് സാന്നിദ്ധ്യത്തിന്റെ കണക്ക് അടിസ്ഥാനമാക്കി വൈഫൈ റോം സ്‌കാനുകൾ അനുവദിക്കുക/അനുവദിക്കാതിരിക്കുക"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ലോഗർ ബഫർ വലുപ്പം"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ഓരോ ലോഗ് ബഫറിനും വലുപ്പം തിരഞ്ഞെടുക്കൂ"</string>
diff --git a/packages/SettingsLib/res/values-mn/strings.xml b/packages/SettingsLib/res/values-mn/strings.xml
index 152408aa6213..67c64958fed1 100644
--- a/packages/SettingsLib/res/values-mn/strings.xml
+++ b/packages/SettingsLib/res/values-mn/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Сүлжээ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Утасгүй дэлгэцийн сертификат"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose лог-г идэвхжүүлэх"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Идэвхтэй Wi‑Fi-с мобайл сүлжээнд"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi Роум сканыг байнга зөвшөөрөх"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобайл дата байнга идэвхтэй"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Модем болгох хардвер хурдасгуур"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS-н үйлчилгээ үзүүлэгчийн хостын нэрийг оруулах"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Утасгүй дэлгэцийн сертификатын сонголтыг харуулах"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi лог-н түвшинг нэмэгдүүлэх, Wi‑Fi Сонгогч дээрх SSID-д ногдох RSSI-г харуулах"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Идэвхжүүлсэн үед Wi‑Fi холболт сул байх үед дата холболтыг мобайлд шилжүүлэхэд илүү идэвхтэй байх болно"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Интерфэйс дээрх дата трафикын хэмжээнээс хамааран Wi‑Fi Роум Скан-г зөвшөөрөх/үл зөвшөөрөх"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Логгерын буферын хэмжээ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Лог буфер бүрт ногдох логгерын хэмжээг сонгоно уу"</string>
diff --git a/packages/SettingsLib/res/values-mr/strings.xml b/packages/SettingsLib/res/values-mr/strings.xml
index 7402d29ee2e9..eeb0a165cf37 100644
--- a/packages/SettingsLib/res/values-mr/strings.xml
+++ b/packages/SettingsLib/res/values-mr/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किंग"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"वायरलेस डिस्प्ले प्रमाणीकरण"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"वाय-फाय व्हर्बोझ लॉगिंग सक्षम करा"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"मोबाइलकडे सोपवण्यासाठी अॅग्रेसिव्ह वाय-फाय"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"वाय-फाय रोम स्‍कॅनला नेहमी अनुमती द्या"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा नेहमी सक्रिय"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिंग हार्डवेअर प्रवेग"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS पुरवठादाराचे होस्टनाव टाका"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"वायरलेस डिस्प्ले प्रमाणिकरणाचे पर्याय दाखवा"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"वाय-फाय लॉगिंग स्‍तर वाढवा, वाय-फाय सिलेक्टरमध्‍ये प्रति SSID RSSI दर्शवा"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम केले असताना, वाय-फाय सिग्‍नल कमी असताना, मोबाइलकडे डेटा कनेक्‍शन सोपवण्यासाठी वाय-फाय अधिक अॅग्रेसिव्ह असेल."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"वाय-फाय रोम स्‍कॅनला इंटरफेसवर उपस्‍थित असलेल्‍या रहदारी डेटाच्या प्रमाणावर आधारित अनुमती द्या/अनुमती देऊ नका"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लॉगर बफर आकार"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"प्रति लॉग बफर लॉगर आकार निवडा"</string>
diff --git a/packages/SettingsLib/res/values-ms/strings.xml b/packages/SettingsLib/res/values-ms/strings.xml
index 51ab84e05de6..a69024c50d05 100644
--- a/packages/SettingsLib/res/values-ms/strings.xml
+++ b/packages/SettingsLib/res/values-ms/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Perangkaian"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Pensijilan paparan wayarles"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Dayakan Pengelogan Berjela-jela Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Penyerahan Wi-Fi ke mudah alih agresif"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sentiasa benarkan Imbasan Perayauan Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Data mudah alih sentiasa aktif"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Pecutan perkakasan penambatan"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Masukkan nama hos pembekal DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Tunjukkan pilihan untuk pensijilan paparan wayarles"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tingkatkan tahap pengelogan Wi-Fi, tunjuk setiap SSID RSSI dalam Pemilih Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Apabila didayakan, Wi-Fi akan menjadi lebih agresif dalam menyerahkan sambungan data ke mudah alih, apabila isyarat Wi-Fi rendah"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Benarkan/Jangan benarkan Imbasan Perayauan Wi-Fi berdasarkan jumlah trafik data yang ada pada antara muka"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Saiz penimbal pengelog"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pilih saiz Pengelog bagi setiap penimbal log"</string>
diff --git a/packages/SettingsLib/res/values-my/strings.xml b/packages/SettingsLib/res/values-my/strings.xml
index c643c595a6ef..5e78249ca172 100644
--- a/packages/SettingsLib/res/values-my/strings.xml
+++ b/packages/SettingsLib/res/values-my/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ချိတ်ဆက်ဆောင်ရွက်ခြင်း"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ကြိုးမဲ့ပြသမှု အသိအမှတ်ပြုလက်မှတ်"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi Verbose မှတ်တမ်းတင်ခြင်းအား ဖွင့်မည်"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi‑Fi မှ မိုဘိုင်းသို့ လွှဲပြောင်းရန်"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi ရွမ်းရှာဖွေမှုကို အမြဲတမ်း ခွင့်ပြုမည်"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"မိုဘိုင်းဒေတာကို အမြဲဖွင့်ထားရန်"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ဖုန်းကို မိုဒမ်အဖြစ်အသုံးပြုမှု စက်ပစ္စည်းဖြင့် အရှိန်မြှင့်တင်ခြင်း"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ဝန်ဆောင်မှုပေးသူ၏ အင်တာနက်လက်ခံဝန်ဆောင်ပေးသူအမည်ကို ထည့်ပါ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ကြိုးမဲ့ အခင်းအကျင်း အသိအမှတ်ပြုလက်မှတ်အတွက် ရွေးချယ်စရာများပြရန်"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi မှတ်တမ်းတင်ခြင်း နှုန်းအားမြင့်ကာ၊ Wi‑Fi ရွေးရာတွင် SSID RSSI ဖြင့်ပြပါ"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ဖွင့်ထားပါက Wi‑Fi လွှင့်အား နည်းချိန်တွင် Wi‑Fi မှ မိုဘိုင်းသို့ ဒေတာချိတ်ဆက်မှုကို လွှဲပြောင်းရာ၌ ပိုမိုထိရောက်ပါသည်"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"မျက်နှာပြင်တွင် ဖော်ပြသည့် အချက်လက် အသွားအလာ ပမာဏပေါ်တွင် အခြေခံ၍ WIFI ရွမ်းရှာဖွေမှုအား ဖွင့်/ပိတ်မည်"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"လော့ဂါး ဘာဖား ဆိုက်များ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"လော့ ဘာဖားတွက် လော့ဂါးဆိုက် ရွေး"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 0cea1a78e503..d45bbc3bbe80 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Nettverk"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Trådløs skjermsertifisering"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktiver detaljert Wi-Fi-loggføring"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiv overføring fra Wi-Fi til mobil"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillat alltid skanning for Wi-Fi-roaming"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata er alltid aktiv"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvareakselerasjon for internettdeling"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Skriv inn vertsnavnet til DNS-leverandøren"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Vis alternativer for sertifisering av trådløs skjerm"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Øk Wi-Fi-loggenivå – vis per SSID RSSI i Wi-Fi-velgeren"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Hvis dette slås på, overfører Wi-Fi-nettverket datatilkoblingen til mobil mer aggressivt når Wi-Fi-signalet er svakt"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillat / ikke tillat skanning for Wi-Fi-roaming basert på mengden datatrafikk til stede i grensesnittet"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Bufferstørrelser for logg"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Velg loggstørrelse per loggbuffer"</string>
diff --git a/packages/SettingsLib/res/values-ne/strings.xml b/packages/SettingsLib/res/values-ne/strings.xml
index d0ec0f5ee01d..d26541ca167e 100644
--- a/packages/SettingsLib/res/values-ne/strings.xml
+++ b/packages/SettingsLib/res/values-ne/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"नेटवर्किङ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ताररहित प्रदर्शन प्रमाणीकरण"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi-Fi वर्बोज लग सक्षम पार्नुहोस्"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"आक्रामक ढंगले Wi‑Fi बाट मोबाइलमा हस्तान्तरण"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi घुम्ने स्क्यान गर्न सधैँ अनुमति दिनुहोस्"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"मोबाइल डेटा सधैँ सक्रिय राख्नुहोस्"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"टेदरिङको लागि हार्डवेयरको प्रवेग"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS प्रदायकको होस्टनाम प्रविष्ट गर्नुहोस्"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ताररहित प्रदर्शन प्रमाणीकरणका लागि विकल्पहरू देखाउनुहोस्"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi लग स्तर बढाउनुहोस्, Wi-Fi चयनकर्तामा प्रति SSID RSSI देखाइन्छ"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"सक्षम गरिएको अवस्थामा, Wi-Fi सिग्नल न्यून हुँदा, Wi-Fi ले बढी आक्रामक ढंगले मोबाइलमा डेटा जडान हस्तान्तरण गर्नेछ"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Wi-Fi घुम्ने स्क्यान इन्टरफेसमा रहेको डेटा यातायातको मात्रामा आधारित अनुमति दिनुहोस्/नदिनुहोस्"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"लगर बफर आकारहरू"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"लग बफर प्रति लगर आकार चयन गर्नुहोस्"</string>
diff --git a/packages/SettingsLib/res/values-nl/strings.xml b/packages/SettingsLib/res/values-nl/strings.xml
index 87d20c2e4ae3..ce25cc74fae7 100644
--- a/packages/SettingsLib/res/values-nl/strings.xml
+++ b/packages/SettingsLib/res/values-nl/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Netwerken"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificering van draadloze weergave"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Uitgebreide wifi-logregistratie insch."</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agressieve handover van wifi naar mobiel"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Altijd roamingscans voor wifi toestaan"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobiele data altijd actief"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardwareversnelling voor tethering"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Geef hostnaam van DNS-provider op"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Opties weergeven voor certificering van draadloze weergave"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Logniveau voor wifi verhogen, weergeven per SSID RSSI in wifi-kiezer"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Indien ingeschakeld, is wifi agressiever bij het overgeven van de gegevensverbinding aan mobiel wanneer het wifi-signaal zwak is"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Roamingscans voor wifi (niet) toestaan op basis van de hoeveelheid dataverkeer die aanwezig is bij de interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Logger-buffergrootten"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Kies Logger-grootten per logbuffer"</string>
diff --git a/packages/SettingsLib/res/values-pa/strings.xml b/packages/SettingsLib/res/values-pa/strings.xml
index d870a99d9647..d64c30f4246c 100644
--- a/packages/SettingsLib/res/values-pa/strings.xml
+++ b/packages/SettingsLib/res/values-pa/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ਨੈੱਟਵਰਕਿੰਗ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"ਵਾਈ-ਫਾਈ ਵਰਬੋਸ ਲੌਗਿੰਗ ਚਾਲੂ ਕਰੋ"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ਆਕਰਮਣਸ਼ੀਲ ਵਾਈ‑ਫਾਈ ਤੋਂ ਮੋਬਾਈਲ ਹੈਂਡਓਵਰ"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ਹਮੇਸ਼ਾਂ ਵਾਈ‑ਫਾਈ ਰੋਮ ਸਕੈਨਾਂ ਦੀ ਆਗਿਆ ਦਿਓ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ਮੋਬਾਈਲ ਡਾਟਾ ਹਮੇਸ਼ਾਂ ਕਿਰਿਆਸ਼ੀਲ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ਟੈਦਰਿੰਗ ਹਾਰਡਵੇਅਰ ਐਕਸੈੱਲਰੇਸ਼ਨ"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ਪ੍ਰਦਾਨਕ ਦਾ ਹੋਸਟਨਾਮ ਦਾਖਲ ਕਰੋ"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"ਵਾਇਰਲੈੱਸ ਡਿਸਪਲੇ ਪ੍ਰਮਾਣੀਕਰਨ ਲਈ ਚੋਣਾਂ ਪ੍ਰਦਰਸ਼ਿਤ ਕਰੋ"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"ਵਾਈ‑ਫਾਈ ਲੌਗਿੰਗ ਪੱਧਰ ਵਧਾਓ, ਵਾਈ‑ਫਾਈ Picker ਵਿੱਚ ਪ੍ਰਤੀ SSID RSSI ਦਿਖਾਓ"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ਜਦੋਂ ਯੋਗ ਬਣਾਇਆ ਹੋਵੇ, ਤਾਂ ਵਾਈ‑ਫਾਈ ਸਿਗਨਲ ਘੱਟ ਹੋਣ \'ਤੇ ਵਾਈ‑ਫਾਈ ਡਾਟਾ ਕਨੈਕਸ਼ਨ ਮੋਬਾਈਲ ਨੂੰ ਹੈਂਡ ਓਵਰ ਕਰਨ ਵਿੱਚ ਵੱਧ ਆਕਰਮਣਸ਼ੀਲ ਹੋਵੇਗਾ।"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ਇੰਟਰਫੇਸ ਤੇ ਮੌਜੂਦ ਡਾਟਾ ਟ੍ਰੈਫਿਕ ਦੀ ਮਾਤਰਾ ਦੇ ਆਧਾਰ ਤੇ ਵਾਈ-ਫਾਈ ਰੋਮ ਸਕੈਨ ਦੀ ਆਗਿਆ ਦਿਓ/ਅਸਵੀਕਾਰ ਕਰੋ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ਲੌਗਰ ਬਫ਼ਰ ਆਕਾਰ"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ਪ੍ਰਤੀ ਲੌਗ ਬਫ਼ਰ ਲੌਗਰ ਆਕਾਰ ਚੁਣੋ"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index 7b66aa53bfbe..d50528dae95d 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Sieci"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Wyświetlacz bezprzewodowy"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Szczegółowy dziennik Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Przełączaj z Wi-Fi na sieć komórkową"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Zawsze szukaj Wi-Fi w roamingu"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilna transmisja danych zawsze aktywna"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Akceleracja sprzętowa tetheringu"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Wpisz nazwę hosta dostawcy DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaż opcje certyfikacji wyświetlacza bezprzewodowego"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zwiększ poziom rejestrowania Wi‑Fi, pokazuj według RSSI SSID w selektorze Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Po włączeniu połączenie danych będzie bardziej agresywnie przełączać się z Wi-Fi na sieć komórkową przy słabym sygnale Wi-Fi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Zezwalaj/nie zezwalaj na wyszukiwanie sieci Wi-Fi w roamingu w zależności od natężenia ruchu"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Rozmiary bufora Rejestratora"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Wybierz rozmiary Rejestratora/bufor dziennika"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index d99097a9b82f..67fda0390e50 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança agressiva de Wi-Fi para móvel"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quando ativada, o Wi-Fi será mais agressivo em passar a conexão de dados para móvel, quando o sinal de Wi-Fi estiver fraco"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
diff --git a/packages/SettingsLib/res/values-pt-rPT/strings.xml b/packages/SettingsLib/res/values-pt-rPT/strings.xml
index 8c7fbba34e12..d7496454c471 100644
--- a/packages/SettingsLib/res/values-pt-rPT/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rPT/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de display sem fios"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar o registo verboso de Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança brusca de Wi‑Fi para rede móvel"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Permitir sempre a deteção de Wi-Fi em roaming"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware para ligação (à Internet) via telemóvel"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduza o nome de anfitrião do fornecedor DNS."</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções da certificação de display sem fios"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de reg. de Wi-Fi, mostrar por RSSI de SSID no Selec. de Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Se estiver ativado, o Wi-Fi será mais agressivo ao transmitir a lig. de dados para a rede móvel quando o sinal Wi-Fi estiver fraco"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/impedir a deteção de Wi-Fi em roaming com base na quantidade de tráfego de dados presente na interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos da memória intermédia do registo"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Selec. tam. reg. p/ mem. int. reg."</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index d99097a9b82f..67fda0390e50 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Redes"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificação de Display sem fio"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Ativar registro extenso de Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mudança agressiva de Wi-Fi para móvel"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Sempre permitir verif. de roaming de Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dados móveis sempre ativos"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Aceleração de hardware de tethering"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Informe o nome do host do provedor de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Mostrar opções de certificação de Display sem fio"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Aumentar o nível de registro do Wi-Fi; mostrar conforme o RSSI de SSID na Seleção de Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Quando ativada, o Wi-Fi será mais agressivo em passar a conexão de dados para móvel, quando o sinal de Wi-Fi estiver fraco"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permitir/proibir verificações de roaming de Wi-Fi com base no volume do tráfego de dados presente na interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Tamanhos de buffer de logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Sel. tam. de logger/buffer de log"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index 1c6755077feb..1e91d8264f07 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Conectare la rețele"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certificare Ecran wireless"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Înregistrare prin Wi-Fi de volume mari de date"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Predare agresivă de la Wi-Fi la mobilă"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Se permite întotdeauna scanarea traficului Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Date mobile permanent active"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Accelerare hardware pentru tethering"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Introduceți numele de gazdă al furnizorului de DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Afișați opțiunile pentru certificarea Ecran wireless"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Măriți niv. de înr. prin Wi‑Fi, afișați în fcț. de SSID RSSI în Selectorul Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Când este activată, Wi-Fi va fi mai agresivă la predarea conexiunii de date către rețeaua mobilă când semnalul Wi-Fi este slab"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Permiteți/Nu permiteți scanarea traficului Wi-Fi în funcție de traficul de date din interfață"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Dimensiunile tamponului jurnalului"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Dimensiuni jurnal / tampon jurnal"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index 4b1159441e97..693332f52e8f 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Сети"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Серт. беспроводн. мониторов"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Подробный журнал Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Переключаться на мобильную сеть"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Всегда включать поиск сетей Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Не отключать мобильный Интернет"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Аппаратное ускорение в режиме модема"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введите имя хоста поставщика услуг DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показывать параметры сертификации беспроводных мониторов"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"При выборе Wi‑Fi указывать в журнале RSSI для каждого SSID"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Принудительно переключаться на мобильную сеть, если сигнал Wi-Fi слабый"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Включать или отключать поиск сетей Wi-Fi во время передачи данных в зависимости от объема трафика"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Размер буфера журнала"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Выберите размер буфера журнала"</string>
diff --git a/packages/SettingsLib/res/values-si/strings.xml b/packages/SettingsLib/res/values-si/strings.xml
index 2ffe814dd476..6abd14da6f26 100644
--- a/packages/SettingsLib/res/values-si/strings.xml
+++ b/packages/SettingsLib/res/values-si/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"ජාලකරණය"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"නොරැහැන් සංදර්ශක සහතිකය"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"විස්තරාත්මක Wi‑Fi ලොග් කිරීම සබල කරන්න"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ආක්‍රමණික Wi‑Fi සිට ජංගම බාර දීම"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi රෝම් පරිලෝකන වෙතට සැමවිට අවසර දෙන්න"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"ජංගම දත්ත සැමවිට ක්‍රියාකාරීය"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ටෙදරින් දෘඪාංග ත්වරණය"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS සැපයුම්කරුගේ සත්කාරක නම ඇතුළු කරන්න"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"නොරැහැන් සංදර්ශක සහතිකය සඳහා විකල්ප පෙන්වන්න"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ලොග් මට්ටම වැඩි කරන්න, Wi‑Fi තෝරනයෙහි SSID RSSI අනුව පෙන්වන්න"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"සබල විට Wi‑Fi සිග්නලය අඩු විට Wi‑Fi දත්ත සම්බන්ධතාවය ජංගම වෙත භාර දීමට වඩා ආක්‍රමණික වේ"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"අතුරු මුහුණතෙහි ඇති දත්ත තදබදය අනුව Wi‑Fi රෝම් පරිලෝකන වෙත ඉඩ දෙන්න/නොදෙන්න"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ලෝගයේ අන්තරාවක ප්‍රමාණය"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"ලොග අන්තරාවකට ලෝගයේ ප්‍රමාණය තෝරන්න"</string>
diff --git a/packages/SettingsLib/res/values-sk/strings.xml b/packages/SettingsLib/res/values-sk/strings.xml
index 0cefd71832c4..8cc2dac2d304 100644
--- a/packages/SettingsLib/res/values-sk/strings.xml
+++ b/packages/SettingsLib/res/values-sk/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Siete"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikácia bezdrôtového zobrazenia"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Podrobné denníky Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agres. odovzdávať Wi‑Fi na mobilnú sieť"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vždy povoliť funkciu Wi‑Fi Roam Scans"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobilné dáta ponechať vždy aktívne"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardvérovú akcelerácia pre tethering"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Zadajte názov hostiteľa poskytovateľa DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Zobraziť možnosti certifikácie bezdrôtového zobrazenia"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Zvýšiť úroveň denníkov Wi‑Fi, zobrazovať podľa SSID RSSI pri výbere siete Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Keď túto možnosť zapnete, Wi‑Fi bude agresívnejšie odovzdávať dátové pripojenie na mobilnú sieť vtedy, keď bude slabý signál Wi‑Fi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Povoliť alebo zakázať funkciu Wifi Roam Scans na základe objemu prenosu údajov v rozhraní"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Vyrovnávacia pamäť nástroja denníkov"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Veľkosť vyrovnávacej pamäte nástroja denníkov"</string>
diff --git a/packages/SettingsLib/res/values-sl/strings.xml b/packages/SettingsLib/res/values-sl/strings.xml
index 0864d5b921f2..af8eb6e11d6f 100644
--- a/packages/SettingsLib/res/values-sl/strings.xml
+++ b/packages/SettingsLib/res/values-sl/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Omrežja"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Potrdilo brezžičnega zaslona"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Omogoči podrob. zapis. dnevnika za Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Odločen prehod iz Wi-Fi-ja v mobil. omr."</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vedno omogoči iskanje omrežij Wi-Fi za gostovanje"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Prenos podatkov v mobilnem omrežju je vedno aktiven"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Strojno pospeševanje za internetno povezavo prek mobilnega telefona"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Vnesite ime gostitelja pri ponudniku strežnika DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Pokaži možnosti za potrdilo brezžičnega zaslona"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Povečaj raven zapis. dnev. za Wi-Fi; v izbir. Wi‑Fi-ja pokaži glede na SSID RSSI"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Če je ta možnost omogočena, Wi-Fi odločneje preda podatkovno povezavo mobilnemu omrežju, ko je signal Wi-Fi šibek."</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Omogoči/onemogoči iskanje omrežij Wi-Fi za gostovanje glede na količino podatkovnega prometa pri vmesniku"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Velikosti medpomn. zapisov. dnevnika"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Izberite velikost medpomnilnika dnevnika"</string>
diff --git a/packages/SettingsLib/res/values-sq/strings.xml b/packages/SettingsLib/res/values-sq/strings.xml
index 63da6ffd2a63..88b1057739bc 100644
--- a/packages/SettingsLib/res/values-sq/strings.xml
+++ b/packages/SettingsLib/res/values-sq/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Rrjetet"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifikimi i ekranit valor"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivizo hyrjen Wi-Fi Verbose"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Dorëzimi agresiv i Wi‑Fi te rrjeti celular"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Lejo gjithmonë skanimet për Wi-Fi edhe kur je në lëvizje"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Të dhënat celulare gjithmonë aktive"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Përshpejtimi i harduerit për ndarjen"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Fut emrin e pritësit të ofruesit të DNS-së"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Shfaq opsionet për certifikimin e ekranit valor"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Rrit nivelin regjistrues të Wi‑Fi duke shfaqur SSID RSSI-në te Zgjedhësi i Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kur ky funksion aktivizohet, Wi‑Fi bëhet më agresiv në kalimin e lidhjes së të dhënave te rrjeti celular, në rastet kur sinjali Wi‑Fi është i dobët"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Lejo/Ndalo skanimet për Wi‑Fi në roaming, bazuar në sasinë e trafikut të të dhënave të pranishme në ndërfaqe"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Madhësitë e regjistruesit"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Përzgjidh madhësitë e regjistruesit"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index 4c7aed8e29a3..362fc1fb77dd 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Умрежавање"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сертификација бежичног екрана"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Омогући детаљнију евиденцију за Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Агресиван прелаз са Wi‑Fi мреже на мобилну"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Увек дозволи скенирање Wi‑Fi-ја у ромингу"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Мобилни подаци су увек активни"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Хардверско убрзање привезивања"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Унесите име хоста добављача услуге DNS-а"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Приказ опција за сертификацију бежичног екрана"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Повећава ниво евидентирања за Wi‑Fi. Приказ по SSID RSSI-у у бирачу Wi‑Fi мреже"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Кад се омогући, Wi‑Fi ће бити агресивнији при пребацивању мреже за пренос података на мобилну ако је Wi‑Fi сигнал слаб"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволи/забрани скенирање Wi-Fi-ја у ромингу на основу присутног протока података на интерфејсу"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Величине бафера података у програму за евидентирање"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Изаберите величине по баферу евиденције"</string>
diff --git a/packages/SettingsLib/res/values-sv/strings.xml b/packages/SettingsLib/res/values-sv/strings.xml
index e44dcd8dde6d..230dfeefdd8e 100644
--- a/packages/SettingsLib/res/values-sv/strings.xml
+++ b/packages/SettingsLib/res/values-sv/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Nätverk"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certifiering för Wi-Fi-skärmdelning"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Aktivera utförlig loggning för Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Aggressiv överlämning fr. Wi-Fi t. mobil"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Tillåt alltid sökning efter Wi-Fi-roaming"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobildata alltid aktiverad"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Maskinvaruacceleration för internetdelning"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ange värdnamn för DNS-leverantör"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Visa certifieringsalternativ för Wi-Fi-skärmdelning"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Öka loggningsnivån för Wi-Fi, visa per SSID RSSI i Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"När funktionen har aktiverats kommer dataanslutningen lämnas över från Wi-Fi till mobilen på ett aggressivare sätt när Wi-Fi-signalen är svag"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Tillåt/tillåt inte sökning efter Wi-Fi-roaming utifrån mängden datatrafik i gränssnittet"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Buffertstorlekar för logg"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Välj loggstorlekar per loggbuffert"</string>
diff --git a/packages/SettingsLib/res/values-sw/strings.xml b/packages/SettingsLib/res/values-sw/strings.xml
index 66cfda8b8079..1d462603750b 100644
--- a/packages/SettingsLib/res/values-sw/strings.xml
+++ b/packages/SettingsLib/res/values-sw/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Mtandao"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Chaguo za cheti cha kuonyesha pasiwaya"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Washa Uwekaji kumbukumbu za WiFi kutumia Sauti"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Ukabidhi hima kutoka Wifi kwenda mtandao wa simu"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Ruhusu Uchanganuzi wa Matumizi ya Mitandao mingine"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Iendelee kutumia data ya simu"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Kuongeza kasi kwa kutumia maunzi ili kusambaza mtandao"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Weka jina la mpangishi wa huduma za DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Onyesha chaguo za cheti cha kuonyesha pasiwaya"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Ongeza hatua ya uwekaji kumbukumbu ya Wi-Fi, onyesha kwa kila SSID RSSI kwenye Kichukuzi cha Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Ikiwashwa, Wi-Fi itakabidhi kwa hima muunganisho wa data kwa mtandao wa simu, wakati mtandao wa Wi-Fi si thabiti"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ruhusu au Zuia Uchanganuzi wa Matumizi ya Mitandao mingine ya Wifi kulingana na kiasi cha trafiki ya data kilicho kwenye kiolesura"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Ukubwa wa kiweka bafa ya kumbukumbu"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chagua ukubwa wa kila Kumbukumbu"</string>
diff --git a/packages/SettingsLib/res/values-ta/strings.xml b/packages/SettingsLib/res/values-ta/strings.xml
index dd218c61ab15..e9fd79bfe9a7 100644
--- a/packages/SettingsLib/res/values-ta/strings.xml
+++ b/packages/SettingsLib/res/values-ta/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"நெட்வொர்க்கிங்"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"வயர்லெஸ் காட்சிக்கான சான்றிதழ்"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"வைஃபை அதிவிவர நுழைவை இயக்கு"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"ஒத்துழைக்காத வைஃபையிலிருந்து மொபைல் தரவிற்கு மாறு"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"எப்போதும் வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"மொபைல் டேட்டாவை எப்போதும் இயக்கத்திலேயே வை"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"வன்பொருள் விரைவுப்படுத்துதல் இணைப்பு முறை"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS வழங்குநரின் ஹோஸ்ட் பெயரை உள்ளிடவும்"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"வயர்லெஸ் காட்சி சான்றுக்கான விருப்பங்களைக் காட்டு"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wifi நுழைவு அளவை அதிகரித்து, வைஃபை தேர்வியில் ஒவ்வொன்றிற்கும் SSID RSSI ஐ காட்டுக"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"இயக்கப்பட்டதும், வைஃபை சிக்னல் குறையும் போது, வைஃபை முழுமையாக ஒத்துழைக்காமல் இருந்தால் மொபைல் தரவிற்கு மாறும்"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"இடைமுகத்தில் உள்ள ட்ராஃபிக் தரவின் அளவைப் பொறுத்து வைஃபை ரோமிங் ஸ்கேன்களை அனுமதி/அனுமதிக்காதே"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"லாகர் பஃபர் அளவுகள்"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"லாக் பஃபர் ஒன்றிற்கு லாகர் அளவுகளைத் தேர்வுசெய்க"</string>
diff --git a/packages/SettingsLib/res/values-te/strings.xml b/packages/SettingsLib/res/values-te/strings.xml
index b21eb8c8f8c0..c2b738ac9898 100644
--- a/packages/SettingsLib/res/values-te/strings.xml
+++ b/packages/SettingsLib/res/values-te/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"నెట్‌వర్కింగ్"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"వైర్‌లెస్ ప్రదర్శన ప్రమాణీకరణ"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Wi‑Fi విశదీకృత లాగింగ్‌ను ప్రారంభించండి"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"మొబైల్‌కి మార్చేలా చురుకైన Wi‑Fi"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi‑Fi సంచార స్కాన్‌లను ఎల్లప్పుడూ అనుమతించు"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"మొబైల్ డేటాని ఎల్లప్పుడూ సక్రియంగా ఉంచు"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"టెథెరింగ్ హార్డ్‌వేర్ వేగవృద్ధి"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS ప్రదాత యొక్క హోస్ట్‌పేరును నమోదు చేయండి"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"వైర్‌లెస్ ప్రదర్శన సర్టిఫికెట్ కోసం ఎంపికలను చూపు"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi‑Fi ఎంపికలో SSID RSSI ప్రకారం చూపబడే Wi‑Fi లాగింగ్ స్థాయిని పెంచండి"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"ప్రారంభించబడినప్పుడు, Wi‑Fi సిగ్నల్ బలహీనంగా ఉంటే డేటా కనెక్షన్‌ను మొబైల్‌కి మార్చేలా Wi‑Fi చురుగ్గా వ్యవహరిస్తుంది"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"ఇంటర్‌ఫేస్‌లో ఉండే డేటా ట్రాఫిక్ పరిమాణం ఆధారంగా Wi‑Fi సంచార స్కాన్‌లను అనుమతించు/నిరాకరించు"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"లాగర్ బఫర్ పరిమాణాలు"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"లాగ్ బఫర్‌కి లాగర్ పరిమా. ఎంచుకోండి"</string>
diff --git a/packages/SettingsLib/res/values-th/strings.xml b/packages/SettingsLib/res/values-th/strings.xml
index 447b188a4b89..57b12a5601a7 100644
--- a/packages/SettingsLib/res/values-th/strings.xml
+++ b/packages/SettingsLib/res/values-th/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"เครือข่าย"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"การรับรองการแสดงผลแบบไร้สาย"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"เปิดใช้การบันทึกรายละเอียด Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"สลับ Wi‑Fi เป็นมือถือเมื่อสัญญาณอ่อน"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"ใช้การสแกน Wi-Fi ข้ามเครือข่ายเสมอ"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"เปิดใช้อินเทอร์เน็ตมือถือเสมอ"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"การเร่งฮาร์ดแวร์การเชื่อมต่ออินเทอร์เน็ตผ่านมือถือ"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"ป้อนชื่อโฮสต์ของผู้ให้บริการ DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"แสดงตัวเลือกสำหรับการรับรองการแสดงผล แบบไร้สาย"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"เพิ่มระดับการบันทึก Wi‑Fi แสดงต่อ SSID RSSI ในตัวเลือก Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"เมื่อเปิดใช้แล้ว Wi-Fi จะส่งผ่านการเชื่อมต่อข้อมูลไปยังเครือข่ายมือถือเมื่อสัญญาณ Wi-Fi อ่อน"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"อนุญาต/ไม่อนุญาตการสแกน Wi-Fi ข้ามเครือข่าย ตามปริมาณข้อมูลการเข้าชมที่ปรากฏในอินเทอร์เฟซ"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"ขนาดบัฟเฟอร์ของ Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"เลือกขนาด Logger ต่อบัฟเฟอร์ไฟล์บันทึก"</string>
diff --git a/packages/SettingsLib/res/values-tl/strings.xml b/packages/SettingsLib/res/values-tl/strings.xml
index a5e0b8960239..72261afd43ea 100644
--- a/packages/SettingsLib/res/values-tl/strings.xml
+++ b/packages/SettingsLib/res/values-tl/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Networking"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Certification ng wireless display"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"I-enable ang Pagla-log sa Wi‑Fi Verbose"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Agresibong paglipat ng Wi‑Fi sa mobile"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Palaging payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Palaging aktibo ang mobile data"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Hardware acceleration para sa pag-tether"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Ilagay ang hostname ng DNS provider"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Ipakita ang mga opsyon para sa certification ng wireless display"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Pataasin ang antas ng Wi‑Fi logging, ipakita sa bawat SSID RSSI sa Wi‑Fi Picker"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Kapag na-enable, magiging mas agresibo ang Wi‑Fi sa paglipat sa koneksyon ng mobile data kapag mahina ang signal ng Wi‑Fi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Payagan/Huwag payagan ang Mga Pag-scan sa Roaming ng Wi‑Fi batay sa dami ng trapiko ng data na mayroon sa interface"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Mga laki ng buffer ng Logger"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Pumili ng mga laki ng Logger bawat log buffer"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index e6bba5be7a4a..948e4e5c9465 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Ağ işlemleri"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Kablosuz ekran sertifikası"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Kablosuz Ayrıntılı Günlük Kaydını etkinleştir"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Kablosuzdan mobil ağa agresif geçiş"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Kablosuz Dolaşım Taramalarına daima izin ver"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil veri her zaman etkin"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tethering donanım hızlandırıcısı"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS sağlayıcının ana makine adını gir"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Kablosuz ekran sertifikası seçeneklerini göster"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Kablosuz günlük kaydı seviyesini artır. Kablosuz Seçici\'de her bir SSID RSSI için göster."</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Etkinleştirildiğinde, kablosuz ağ sinyali zayıfken veri bağlantısının mobil ağa geçirilmesinde daha agresif olunur"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Arayüzde mevcut veri trafiği miktarına bağlı olarak Kablosuz Dolaşım Taramalarına İzin Verin/Vermeyin"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Günlük Kaydedici arabellek boyutları"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Gün. arabel. başına Gün. Kayd. boyutunu seç"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index 65f39edd1f5a..664fda7a2413 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Мережі"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Сертифікація бездрот. екрана"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Докладний запис у журнал Wi-Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Перемикатися з Wi-Fi на мобільну мережу"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Завжди шукати мережі Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Не вимикати мобільне передавання даних"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Апаратне прискорення під час використання телефона в режимі модема"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Введіть ім’я хосту постачальника послуг DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Показати параметри сертифікації бездротового екрана"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Показувати в журналі RSSI для кожного SSID під час вибору Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Примусово перемикатися на мобільну мережу, коли сигнал Wi-Fi слабкий"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Дозволити чи заборонити Wi-Fi шукати роумінг на основі обсягу трафіку даних в інтерфейсі"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Розміри буфера журналу"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Виберіть розміри буфера журналу"</string>
diff --git a/packages/SettingsLib/res/values-ur/strings.xml b/packages/SettingsLib/res/values-ur/strings.xml
index 7830bb86ce72..226b862fc6fb 100644
--- a/packages/SettingsLib/res/values-ur/strings.xml
+++ b/packages/SettingsLib/res/values-ur/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"نیٹ ورکنگ"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"وائرلیس ڈسپلے سرٹیفیکیشن"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"‏Wi‑Fi وربوس لاگنگ فعال کریں"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"‏Wi‑Fi سے موبائل کو جارحانہ ہینڈ اوور"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"‏ہمیشہ Wi‑Fi روم اسکینز کی اجازت دیں"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"موبائل ڈیٹا ہمیشہ فعال رکھیں"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"ٹیدرنگ ہارڈویئر سرعت کاری"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"‏DNS فراہم کنندہ کے میزبان کا نام درج کریں"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"وائرلیس ڈسپلے سرٹیفیکیشن کیلئے اختیارات دکھائیں"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"‏Wi‑Fi لاگنگ لیول میں اضافہ کریں، Wi‑Fi منتخب کنندہ میں فی SSID RSSI دکھائیں"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"‏فعال کئے جانے پر، جب Wi‑Fi سگنل کمزور ہوگا، تو Wi‑Fi موبائل پر ڈیٹا کنکشن بھیجنے کیلئے مزید جارحانہ کارروائی کرے گا"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"‏انٹرفیس پر موجود ڈیٹا ٹریفک کی مقدار کی بنیاد پر Wi‑Fi روم اسکینز کی اجازت دیں/اجازت نہ دیں"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"لاگر بفر کے سائز"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"فی لاگ بفر لاگر کے سائز منتخب کریں"</string>
diff --git a/packages/SettingsLib/res/values-uz/strings.xml b/packages/SettingsLib/res/values-uz/strings.xml
index acaaaf1b8f5d..fdb3ef478467 100644
--- a/packages/SettingsLib/res/values-uz/strings.xml
+++ b/packages/SettingsLib/res/values-uz/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Tarmoqlar"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Simsiz monitor sertifikatlari"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Batafsil Wi-Fi jurnali"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Mobil internetga o‘tish"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Wi-Fi tarmoqlarini qidirishga doim ruxsat"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Mobil internet doim yoniq tursin"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Modem rejimida apparatli tezlashtirish"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"DNS provayderining host nomini kiriting"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Simsiz monitorlarni sertifikatlash parametrini ko‘rsatish"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Wi-Fi ulanishini tanlashda har bir SSID uchun jurnalda ko‘rsatilsin"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Agar ushbu funksiya yoqilsa, Wi-Fi signali past bo‘lganda internetga ulanish majburiy ravishda mobil internetga o‘tkaziladi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Ma’lumotlarni uzatish vaqtida trafik hajmiga qarab Wi-Fi tarmoqlarni qidirish funksiyasini yoqish yoki o‘chirish"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Jurnal buferi hajmi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Jurnal xotirasi hajmini tanlang"</string>
diff --git a/packages/SettingsLib/res/values-vi/strings.xml b/packages/SettingsLib/res/values-vi/strings.xml
index 7732b54c2c6d..a7a585583a84 100644
--- a/packages/SettingsLib/res/values-vi/strings.xml
+++ b/packages/SettingsLib/res/values-vi/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Mạng"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Chứng nhận hiển thị không dây"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Bật ghi nhật ký chi tiết Wi‑Fi"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Chuyển vùng Wi‑Fi tích cực sang mạng DĐ"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Luôn cho phép quét chuyển vùng Wi‑Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Dữ liệu di động luôn hiện hoạt"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"Tăng tốc phần cứng cho chia sẻ kết nối"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Nhập tên máy chủ của nhà cung cấp DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Hiển thị tùy chọn chứng nhận hiển thị không dây"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"Tăng mức ghi nhật ký Wi‑Fi, hiển thị mỗi SSID RSSI trong bộ chọn Wi‑Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Khi được bật, Wi‑Fi sẽ tích cực hơn trong việc chuyển vùng kết nối dữ liệu sang mạng di động khi tín hiệu Wi‑Fi yếu"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Cho phép/Không cho phép quét chuyển vùng Wi‑Fi dựa trên lưu lượng truy cập dữ liệu có tại giao diện"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Kích cỡ tải trình ghi"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Chọn kích thước Trình ghi/lần tải nhật ký"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index f036eae1ff0c..5a1d0671cba6 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"网络"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"无线显示认证"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"启用WLAN详细日志记录功能"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"主动从 WLAN 网络切换到移动数据网络"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允许WLAN漫游扫描"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"始终开启移动数据网络"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"网络共享硬件加速"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"输入 DNS 提供商的主机名"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"显示无线显示认证选项"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"提升WLAN日志记录级别(在WLAN选择器中显示每个SSID的RSSI)"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"开启此设置后,系统会在 WLAN 信号较弱时,主动将网络模式从 WLAN 网络切换到移动数据网络"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根据接口中目前的数据流量允许/禁止WLAN漫游扫描"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"日志记录器缓冲区大小"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"选择每个日志缓冲区的日志记录器大小"</string>
diff --git a/packages/SettingsLib/res/values-zh-rHK/strings.xml b/packages/SettingsLib/res/values-zh-rHK/strings.xml
index d57a8fd01196..acc3bb83226c 100644
--- a/packages/SettingsLib/res/values-zh-rHK/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rHK/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"網絡"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細記錄"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"加強 Wi-Fi 至流動數據轉換"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"永遠允許 Wi-Fi 漫遊掃描"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"一律保持啟用流動數據"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"網絡共享硬件加速"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入網域名稱系統 (DNS) 供應商的主機名稱"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"啟用後,Wi-Fi 連線會在訊號不穩定的情況下更積極轉換成流動數據連線"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 WiFi 漫遊掃描"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"記錄器緩衝區空間"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個記錄緩衝區的記錄器空間"</string>
diff --git a/packages/SettingsLib/res/values-zh-rTW/strings.xml b/packages/SettingsLib/res/values-zh-rTW/strings.xml
index 5a329fa9c25f..775b92877628 100644
--- a/packages/SettingsLib/res/values-zh-rTW/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rTW/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"網路連線"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"無線螢幕分享認證"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"啟用 Wi‑Fi 詳細紀錄設定"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Wi-Fi 至行動數據轉換強化"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"一律允許 Wi-Fi 漫遊掃描"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"行動數據連線一律保持啟用狀態"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"數據連線硬體加速"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"輸入 DNS 供應商的主機名稱"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"顯示無線螢幕分享認證的選項"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"讓 Wi‑Fi 記錄功能升級,在 Wi‑Fi 選擇器中依每個 SSID RSSI 顯示 Wi‑Fi 詳細紀錄"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"啟用時,Wi-Fi 連線在訊號不穩的情況下會更積極轉換成行動數據連線"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"根據介面中目前的數據流量允許/禁止 Wi-Fi 漫遊掃描"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"紀錄器緩衝區空間"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"選取每個紀錄緩衝區的紀錄器空間"</string>
diff --git a/packages/SettingsLib/res/values-zu/strings.xml b/packages/SettingsLib/res/values-zu/strings.xml
index 3649ba24ebd0..13b16037a549 100644
--- a/packages/SettingsLib/res/values-zu/strings.xml
+++ b/packages/SettingsLib/res/values-zu/strings.xml
@@ -196,7 +196,6 @@
<string name="debug_networking_category" msgid="7044075693643009662">"Ukunethiwekha"</string>
<string name="wifi_display_certification" msgid="8611569543791307533">"Ukunikezwa isitifiketi sokubukeka okungenantambo"</string>
<string name="wifi_verbose_logging" msgid="4203729756047242344">"Nika amandlaukungena kwe-Wi-Fi Verbose"</string>
- <string name="wifi_aggressive_handover" msgid="5309131983693661320">"Ukudluliselwa okunamandla kakhulu kwe-Wi-Fi ukuya kuselula"</string>
<string name="wifi_allow_scan_with_traffic" msgid="3601853081178265786">"Vumela njalo ukuskena kokuzula kwe-Wi-Fi"</string>
<string name="mobile_data_always_on" msgid="8774857027458200434">"Idatha yeselula ihlala isebenza"</string>
<string name="tethering_hardware_offload" msgid="7470077827090325814">"I-Tethering hardware acceleration"</string>
@@ -223,7 +222,6 @@
<string name="private_dns_mode_provider_hostname_hint" msgid="2487492386970928143">"Faka igama lomsingathi womhlinzeki we-DNS"</string>
<string name="wifi_display_certification_summary" msgid="1155182309166746973">"Bonisa izinketho zokunikeza isitifiketi ukubukeka okungenantambo"</string>
<string name="wifi_verbose_logging_summary" msgid="6615071616111731958">"khuphula izinga lokungena le-Wi-Fi, bonisa nge-SSID RSSI engayodwana kusikhethi se-Wi-Fi"</string>
- <string name="wifi_aggressive_handover_summary" msgid="7266329646559808827">"Uma inikwe amandla, i-Wi-Fi izoba namandla kakhulu ekudluliseleni ukuxhumeka kwedatha kuselula, uma isignali ye-Wi-Fi iphansi"</string>
<string name="wifi_allow_scan_with_traffic_summary" msgid="2575101424972686310">"Vumela/Ungavumeli ukuskena kokuzula kwe-Wi-Fi okususelwa kunani ledatha yethrafikhi ekhona ekusebenzisaneni"</string>
<string name="select_logd_size_title" msgid="7433137108348553508">"Amasayizi weloga ngebhafa"</string>
<string name="select_logd_size_dialog_title" msgid="1206769310236476760">"Khetha amasayizi weloga ngebhafa ngayinye yelogu"</string>
diff --git a/packages/SettingsLib/res/values/dimens.xml b/packages/SettingsLib/res/values/dimens.xml
index bd963e96dcab..ddb49b6c3874 100644
--- a/packages/SettingsLib/res/values/dimens.xml
+++ b/packages/SettingsLib/res/values/dimens.xml
@@ -74,4 +74,13 @@
fraction of a pixel.-->
<fraction name="battery_subpixel_smoothing_left">0%</fraction>
<fraction name="battery_subpixel_smoothing_right">0%</fraction>
+
+ <!-- Zen mode panel: condition item button padding -->
+ <dimen name="zen_mode_condition_detail_button_padding">8dp</dimen>
+ <!-- Zen mode panel: spacing between condition items -->
+ <dimen name="zen_mode_condition_detail_item_spacing">12dp</dimen>
+ <!-- Zen mode panel: spacing between two-line condition upper and lower lines -->
+ <dimen name="zen_mode_condition_detail_item_interline_spacing">4dp</dimen>
+ <!-- Zen mode panel: bottom padding, a bit less than qs_panel_padding -->
+ <dimen name="zen_mode_condition_detail_bottom_padding">4dp</dimen>
</resources>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 042767d39f84..5dcc927cc5d5 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -1025,4 +1025,9 @@
<item quantity="other">%1$d devices connected</item>
</plurals>
+ <!-- Content description of zen mode time condition plus button (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_manual_zen_more_time">More time.</string>
+ <!-- Content description of zen mode time condition minus button (not shown on the screen). [CHAR LIMIT=NONE] -->
+ <string name="accessibility_manual_zen_less_time">Less time.</string>
+
</resources>
diff --git a/packages/SettingsLib/res/values/styles.xml b/packages/SettingsLib/res/values/styles.xml
index 3f312f4efda3..bae838749966 100644
--- a/packages/SettingsLib/res/values/styles.xml
+++ b/packages/SettingsLib/res/values/styles.xml
@@ -21,4 +21,10 @@
<style name="TextAppearanceMedium">
<item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
</style>
+
+ <style name="BorderlessButton">
+ <item name="android:padding">12dp</item>
+ <item name="android:background">@drawable/btn_borderless_rect</item>
+ <item name="android:gravity">center</item>
+ </style>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java b/packages/SettingsLib/src/com/android/settingslib/notification/ZenRadioLayout.java
index 360907b0d22b..1140028b1ca4 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenRadioLayout.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/ZenRadioLayout.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2017 The Android Open Source Project
+ * Copyright (C) 2018 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
@@ -12,7 +12,7 @@
* permissions and limitations under the License.
*/
-package com.android.systemui.volume;
+package com.android.settingslib.notification;
import android.content.Context;
import android.util.AttributeSet;
@@ -22,7 +22,7 @@ import android.widget.LinearLayout;
/**
* Specialized layout for zen mode that allows the radio buttons to reside within
- * a RadioGroup, but also makes sure that all the heights off the radio buttons align
+ * a RadioGroup, but also makes sure that all the heights of the radio buttons align
* with the corresponding content in the second child of this view.
*/
public class ZenRadioLayout extends LinearLayout {
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 80ac82576d13..4b2e62c80281 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -323,7 +323,7 @@
</activity>
<!-- Springboard for launching the share activity -->
- <receiver android:name=".screenshot.GlobalScreenshot$ShareReceiver"
+ <receiver android:name=".screenshot.GlobalScreenshot$ScreenshotActionReceiver"
android:process=":screenshot"
android:exported="false" />
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml
new file mode 100644
index 000000000000..ed637a7adcbf
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_animation.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+<animator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="133"
+ android:valueType="intType"
+ android:valueFrom="@dimen/car_user_switcher_container_height"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml
new file mode 100644
index 000000000000..227c981cb72a
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_icon_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:valueType="floatType"
+ android:valueFrom="180"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml
new file mode 100644
index 000000000000..5901ff41735c
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_name_animation.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="alpha"
+ android:valueType="floatType"
+ android:valueFrom="0"
+ android:valueTo="1" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml
new file mode 100644
index 000000000000..41cbe4b104c3
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_pages_animation.xml
@@ -0,0 +1,23 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:duration="83"
+ android:propertyName="alpha"
+ android:valueType="floatType"
+ android:valueFrom="1"
+ android:valueTo="0" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml
new file mode 100644
index 000000000000..341e7e0cdfe9
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_close_pod_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:ordering="together" >
+
+ <objectAnimator
+ android:duration="50"
+ android:propertyName="alpha"
+ android:valueType="floatType"
+ android:valueFrom="1"
+ android:valueTo="0" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml
new file mode 100644
index 000000000000..6ae74131584d
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_animation.xml
@@ -0,0 +1,20 @@
+<!-- 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.
+-->
+<animator xmlns:android="http://schemas.android.com/apk/res/android"
+ android:duration="200"
+ android:valueType="intType"
+ android:valueFrom="0"
+ android:valueTo="@dimen/car_user_switcher_container_height"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml
new file mode 100644
index 000000000000..06ac9e359b57
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_icon_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:duration="167"
+ android:propertyName="rotation"
+ android:valueType="floatType"
+ android:valueFrom="0"
+ android:valueTo="180"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml
new file mode 100644
index 000000000000..4baefb83a4ef
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_name_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:duration="83"
+ android:startOffset="83"
+ android:propertyName="alpha"
+ android:valueType="floatType"
+ android:valueFrom="1"
+ android:valueTo="0" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml
new file mode 100644
index 000000000000..2d0deb95da59
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_pages_animation.xml
@@ -0,0 +1,24 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <objectAnimator
+ android:duration="83"
+ android:startOffset="83"
+ android:propertyName="alpha"
+ android:valueType="floatType"
+ android:valueFrom="0"
+ android:valueTo="1" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml b/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml
new file mode 100644
index 000000000000..3315220a60ef
--- /dev/null
+++ b/packages/SystemUI/res/anim/car_user_switcher_open_pod_animation.xml
@@ -0,0 +1,33 @@
+<!-- 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.
+-->
+<set xmlns:android="http://schemas.android.com/apk/res/android"
+ android:ordering="together" >
+
+ <objectAnimator
+ android:duration="167"
+ android:startOffset="67"
+ android:propertyName="translationY"
+ android:valueType="floatType"
+ android:valueFrom="@dimen/car_user_switcher_container_anim_height"
+ android:valueTo="0"
+ android:interpolator="@android:interpolator/fast_out_slow_in" />
+ <objectAnimator
+ android:duration="83"
+ android:startOffset="117"
+ android:propertyName="alpha"
+ android:valueType="floatType"
+ android:valueFrom="0"
+ android:valueTo="1" />
+</set> \ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/car_ic_arrow.xml b/packages/SystemUI/res/drawable/car_ic_arrow.xml
index 2c5ad27fe292..d400ed8c7707 100644
--- a/packages/SystemUI/res/drawable/car_ic_arrow.xml
+++ b/packages/SystemUI/res/drawable/car_ic_arrow.xml
@@ -1,5 +1,5 @@
<!--
- ~ Copyright (C) 2015 The Android Open Source Project
+ ~ 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.
diff --git a/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml b/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml
new file mode 100644
index 000000000000..33a512e31675
--- /dev/null
+++ b/packages/SystemUI/res/drawable/car_ic_arrow_drop_up.xml
@@ -0,0 +1,24 @@
+<!--
+ ~ Copyright (C) 2015 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
+ -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="48.0dp"
+ android:height="48.0dp"
+ android:viewportWidth="48.0"
+ android:viewportHeight="48.0">
+ <path
+ android:fillColor="#FFFFFFFF"
+ android:pathData="M14 28l10-10 10 10z"/>
+</vector>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
index 2f16516a6fea..0ee40d7ae47b 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod.xml
@@ -15,27 +15,40 @@
limitations under the License.
-->
-<LinearLayout
+<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"
+ android:clipChildren="false"
+ android:alpha="0"
android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="center" >
+ android:layout_height="@dimen/car_fullscreen_user_pod_height"
+ android:layout_gravity="center_horizontal|bottom" >
<ImageView android:id="@+id/user_avatar"
- android:layout_gravity="center"
+ android:layout_centerHorizontal="true"
+ android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_image_top"
android:layout_width="@dimen/car_fullscreen_user_pod_image_avatar_width"
- android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height" />
+ android:layout_height="@dimen/car_fullscreen_user_pod_image_avatar_height"
+ android:layout_above="@id/user_name" />
<TextView android:id="@+id/user_name"
android:layout_width="@dimen/car_fullscreen_user_pod_width"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/car_fullscreen_user_pod_margin_name_top"
android:layout_marginBottom="@dimen/car_fullscreen_user_pod_margin_name_bottom"
- android:textSize="@dimen/car_fullscreen_user_pod_text_size"
+ android:textSize="@dimen/car_fullscreen_user_pod_name_text_size"
android:textColor="@color/qs_user_detail_name"
android:ellipsize="end"
android:singleLine="true"
android:gravity="center_horizontal"
- android:layout_gravity="center_horizontal" />
-</LinearLayout>
+ android:layout_above="@id/device_name" />
+
+ <TextView android:id="@+id/device_name"
+ android:layout_width="@dimen/car_fullscreen_user_pod_width"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/car_fullscreen_user_pod_device_text_size"
+ android:textColor="@color/qs_user_detail_name"
+ android:ellipsize="end"
+ android:singleLine="true"
+ android:gravity="center_horizontal"
+ android:layout_alignParentBottom="true" />
+</RelativeLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
index 99d010f2ac2b..d666a203298f 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_pod_container.xml
@@ -16,10 +16,10 @@
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:gravity="center"
- android:layout_gravity="center" >
+ android:gravity="center" >
<!-- car_fullscreen_user_pods will be dynamically added here. -->
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
index 257e2814bb65..478b65642689 100644
--- a/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
+++ b/packages/SystemUI/res/layout/car_fullscreen_user_switcher.xml
@@ -54,13 +54,13 @@
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/car_margin"
android:layout_marginRight="@dimen/car_margin"
+ android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
android:layout_centerInParent="true" />
<com.android.systemui.statusbar.car.PageIndicator
android:id="@+id/user_switcher_page_indicator"
android:layout_width="match_parent"
android:layout_height="@dimen/car_page_indicator_dot_diameter"
- android:layout_marginTop="@dimen/car_page_indicator_margin_top"
android:layout_below="@+id/user_grid" />
<Button
diff --git a/packages/SystemUI/res/layout/car_qs_footer.xml b/packages/SystemUI/res/layout/car_qs_footer.xml
index 044090be9f5d..3afd4ea33039 100644
--- a/packages/SystemUI/res/layout/car_qs_footer.xml
+++ b/packages/SystemUI/res/layout/car_qs_footer.xml
@@ -35,7 +35,6 @@
android:layout_centerVertical="true"
android:layout_width="@dimen/car_qs_footer_icon_width"
android:layout_height="@dimen/car_qs_footer_icon_height"
- android:layout_marginRight="@dimen/car_qs_footer_user_switch_margin_right"
android:background="@drawable/ripple_drawable"
android:focusable="true">
@@ -47,6 +46,18 @@
android:scaleType="fitCenter"/>
</com.android.systemui.statusbar.phone.MultiUserSwitch>
+ <ImageView
+ android:id="@+id/user_switch_expand_icon"
+ android:layout_height="match_parent"
+ android:layout_width="@dimen/car_qs_footer_user_switch_icon_width"
+ android:layout_centerVertical="true"
+ android:layout_toEndOf="@+id/multi_user_switch"
+ android:layout_marginLeft="@dimen/car_qs_footer_user_switch_icon_margin"
+ android:layout_marginRight="@dimen/car_qs_footer_user_switch_icon_margin"
+ android:src="@drawable/car_ic_arrow_drop_up"
+ android:scaleType="fitCenter">
+ </ImageView>
+
<TextView android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
@@ -54,7 +65,7 @@
android:textColor="@color/car_qs_footer_user_name_color"
android:gravity="start|center_vertical"
android:layout_centerVertical="true"
- android:layout_toEndOf="@id/multi_user_switch" />
+ android:layout_toEndOf="@id/user_switch_expand_icon" />
<com.android.systemui.statusbar.phone.SettingsButton
android:id="@+id/settings_button"
diff --git a/packages/SystemUI/res/layout/car_qs_panel.xml b/packages/SystemUI/res/layout/car_qs_panel.xml
index 4cb0fd5fecfb..7844cac43f9a 100644
--- a/packages/SystemUI/res/layout/car_qs_panel.xml
+++ b/packages/SystemUI/res/layout/car_qs_panel.xml
@@ -16,6 +16,7 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/quick_settings_container"
+ android:clipChildren="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/car_qs_background_primary"
@@ -26,10 +27,32 @@
<include layout="@layout/car_status_bar_header"/>
<include layout="@layout/car_qs_footer"/>
- <com.android.systemui.statusbar.car.UserGridView
- android:id="@+id/user_grid"
+ <RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/user_switcher_container"
+ android:clipChildren="false"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginLeft="@dimen/car_margin"
- android:layout_marginRight="@dimen/car_margin" />
+ android:layout_height="@dimen/car_user_switcher_container_height"
+ android:layout_gravity="center_horizontal" >
+
+ <com.android.systemui.statusbar.car.UserGridView
+ android:id="@+id/user_grid"
+ android:clipChildren="false"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginLeft="@dimen/car_margin"
+ android:layout_marginRight="@dimen/car_margin"
+ android:layout_marginBottom="@dimen/car_user_grid_margin_bottom"
+ android:layout_above="@id/user_switcher_page_indicator" />
+
+ <com.android.systemui.statusbar.car.PageIndicator
+ android:id="@+id/user_switcher_page_indicator"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/car_page_indicator_dot_diameter"
+ android:layout_marginBottom="@dimen/car_page_indicator_margin_bottom"
+ android:alpha="0"
+ android:layout_alignParentBottom="true" />
+
+ </RelativeLayout>
+
</LinearLayout>
diff --git a/packages/SystemUI/res/layout/zen_mode_panel.xml b/packages/SystemUI/res/layout/zen_mode_panel.xml
index 3826bdddb1b0..58624135b85f 100644
--- a/packages/SystemUI/res/layout/zen_mode_panel.xml
+++ b/packages/SystemUI/res/layout/zen_mode_panel.xml
@@ -93,7 +93,7 @@
</RelativeLayout>
- <com.android.systemui.volume.ZenRadioLayout
+ <com.android.settingslib.notification.ZenRadioLayout
android:id="@+id/zen_conditions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -111,7 +111,7 @@
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"/>
- </com.android.systemui.volume.ZenRadioLayout>
+ </com.android.settingslib.notification.ZenRadioLayout>
<TextView
android:id="@+id/zen_alarm_warning"
diff --git a/packages/SystemUI/res/values/dimens_car.xml b/packages/SystemUI/res/values/dimens_car.xml
index 8853587dba47..f3c9f89bad41 100644
--- a/packages/SystemUI/res/values/dimens_car.xml
+++ b/packages/SystemUI/res/values/dimens_car.xml
@@ -18,20 +18,23 @@
<resources>
<dimen name="car_margin">148dp</dimen>
+ <dimen name="car_fullscreen_user_pod_margin_image_top">24dp</dimen>
<dimen name="car_fullscreen_user_pod_margin_name_top">24dp</dimen>
- <dimen name="car_fullscreen_user_pod_margin_name_bottom">64dp</dimen>
+ <dimen name="car_fullscreen_user_pod_margin_name_bottom">20dp</dimen>
<dimen name="car_fullscreen_user_pod_margin_between">24dp</dimen>
<dimen name="car_fullscreen_user_pod_icon_text_size">96dp</dimen>
<dimen name="car_fullscreen_user_pod_image_avatar_width">192dp</dimen>
<dimen name="car_fullscreen_user_pod_image_avatar_height">192dp</dimen>
<dimen name="car_fullscreen_user_pod_width">264dp</dimen>
- <dimen name="car_fullscreen_user_pod_text_size">40sp</dimen> <!-- B1 -->
+ <dimen name="car_fullscreen_user_pod_height">356dp</dimen>
+ <dimen name="car_fullscreen_user_pod_name_text_size">40sp</dimen> <!-- B1 -->
+ <dimen name="car_fullscreen_user_pod_device_text_size">@dimen/car_body2_size</dimen>
<dimen name="car_navigation_button_width">64dp</dimen>
<dimen name="car_navigation_bar_width">760dp</dimen>
<dimen name="car_page_indicator_dot_diameter">12dp</dimen>
- <dimen name="car_page_indicator_margin_top">32dp</dimen>
+ <dimen name="car_page_indicator_margin_bottom">24dp</dimen>
<dimen name="car_user_switcher_progress_bar_height">6dp</dimen>
<dimen name="car_user_switcher_progress_bar_margin_top">@dimen/status_bar_height</dimen>
@@ -47,8 +50,14 @@
<dimen name="car_qs_footer_padding_start">46dp</dimen>
<dimen name="car_qs_footer_icon_width">56dp</dimen>
<dimen name="car_qs_footer_icon_height">56dp</dimen>
- <dimen name="car_qs_footer_user_switch_margin_right">46dp</dimen>
+ <dimen name="car_qs_footer_user_switch_icon_margin">5dp</dimen>
+ <dimen name="car_qs_footer_user_switch_icon_width">36dp</dimen>
<dimen name="car_qs_footer_user_name_text_size">@dimen/car_body2_size</dimen>
+ <dimen name="car_user_switcher_container_height">420dp</dimen>
+ <!-- This must be the negative of car_user_switcher_container_height for the animation. -->
+ <dimen name="car_user_switcher_container_anim_height">-420dp</dimen>
+ <dimen name="car_user_grid_margin_bottom">28dp</dimen>
+
<dimen name="car_body2_size">26sp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/integers_car.xml b/packages/SystemUI/res/values/integers_car.xml
index 320ee9f66c79..f84dd4bd5f27 100644
--- a/packages/SystemUI/res/values/integers_car.xml
+++ b/packages/SystemUI/res/values/integers_car.xml
@@ -19,4 +19,5 @@
<integer name="car_user_switcher_timeout_ms">15000</integer>
<!-- This values less than ProgressBar.PROGRESS_ANIM_DURATION for a smooth animation. -->
<integer name="car_user_switcher_anim_update_ms">60</integer>
+ <integer name="car_user_switcher_anim_cascade_delay_ms">27</integer>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ab83bcf23ba5..8d6b38f87801 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -675,6 +675,15 @@
<string name="quick_settings_bluetooth_off_label">Bluetooth Off</string>
<!-- QuickSettings: Bluetooth detail panel, text when there are no items [CHAR LIMIT=NONE] -->
<string name="quick_settings_bluetooth_detail_empty_text">No paired devices available</string>
+ <!-- QuickSettings: Bluetooth secondary label for the battery level of a connected device [CHAR LIMIT=20]-->
+ <string name="quick_settings_bluetooth_secondary_label_battery_level"><xliff:g id="battery_level_as_percentage">%s</xliff:g> battery</string>
+ <!-- QuickSettings: Bluetooth secondary label for an audio device being connected [CHAR LIMIT=20]-->
+ <string name="quick_settings_bluetooth_secondary_label_audio">Audio</string>
+ <!-- QuickSettings: Bluetooth secondary label for a headset being connected [CHAR LIMIT=20]-->
+ <string name="quick_settings_bluetooth_secondary_label_headset">Headset</string>
+ <!-- QuickSettings: Bluetooth secondary label for an input/IO device being connected [CHAR LIMIT=20]-->
+ <string name="quick_settings_bluetooth_secondary_label_input">Input</string>
+
<!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_label">Brightness</string>
<!-- QuickSettings: Rotation Unlocked [CHAR LIMIT=NONE] -->
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index d80a33632f3e..9ff681555706 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -333,6 +333,7 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
*/
private class KeyguardSliceButton extends Button {
+ private static final float SEPARATOR_HEIGHT = 0.7f;
private final Paint mPaint;
private boolean mHasDivider;
@@ -369,7 +370,9 @@ public class KeyguardSliceView extends LinearLayout implements View.OnClickListe
super.onDraw(canvas);
if (mHasDivider) {
final int lineX = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? 0 : getWidth();
- canvas.drawLine(lineX, 0, lineX, getHeight(), mPaint);
+ final int height = (int) (getHeight() * SEPARATOR_HEIGHT);
+ final int startY = getHeight() / 2 - height / 2;
+ canvas.drawLine(lineX, startY, lineX, startY + height, mPaint);
}
}
}
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 2873afbca8e9..2b656c220d63 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -171,15 +171,16 @@ public class KeyguardStatusView extends GridLayout {
}
private void onSliceContentChanged(boolean hasHeader) {
- final float clockScale = hasHeader ? mSmallClockScale : 1;
+ final boolean smallClock = hasHeader || mPulsing;
+ final float clockScale = smallClock ? mSmallClockScale : 1;
float translation = (mClockView.getHeight() - (mClockView.getHeight() * clockScale)) / 2f;
- if (hasHeader) {
+ if (smallClock) {
translation -= mWidgetPadding;
}
mClockView.setTranslationY(translation);
mClockView.setScaleX(clockScale);
mClockView.setScaleY(clockScale);
- mClockSeparator.setVisibility(hasHeader ? VISIBLE : GONE);
+ mClockSeparator.setVisibility(hasHeader && !mPulsing ? VISIBLE : GONE);
}
@Override
@@ -329,6 +330,8 @@ public class KeyguardStatusView extends GridLayout {
public void setPulsing(boolean pulsing) {
mPulsing = pulsing;
+ mKeyguardSlice.setVisibility(pulsing ? GONE : VISIBLE);
+ onSliceContentChanged(mKeyguardSlice.hasHeader());
updateDozeVisibleViews();
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
index 142aab2626a6..23d3ebbbfe80 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFooter.java
@@ -47,7 +47,7 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
private MultiUserSwitch mMultiUserSwitch;
private TextView mUserName;
private ImageView mMultiUserAvatar;
- private UserGridView mUserGridView;
+ private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
public CarQSFooter(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -63,15 +63,15 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
mUserInfoController = Dependency.get(UserInfoController.class);
mMultiUserSwitch.setOnClickListener(v -> {
- if (mUserGridView == null) {
+ if (mUserSwitchCallback == null) {
Log.e(TAG, "CarQSFooter not properly set up; cannot display user switcher.");
return;
}
- if (!mUserGridView.isShowing()) {
- mUserGridView.show();
+ if (!mUserSwitchCallback.isShowing()) {
+ mUserSwitchCallback.show();
} else {
- mUserGridView.hide();
+ mUserSwitchCallback.hide();
}
});
@@ -102,8 +102,8 @@ public class CarQSFooter extends RelativeLayout implements QSFooter,
}
}
- public void setUserGridView(UserGridView view) {
- mUserGridView = view;
+ public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
+ mUserSwitchCallback = callback;
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
index 13298d378845..0ee6d1fb6664 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/car/CarQSFragment.java
@@ -13,6 +13,12 @@
*/
package com.android.systemui.qs.car;
+import android.animation.Animator;
+import android.animation.AnimatorInflater;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.AnimatorSet;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
import android.app.Fragment;
import android.os.Bundle;
import android.support.annotation.Nullable;
@@ -26,18 +32,29 @@ import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.qs.QS;
import com.android.systemui.qs.QSFooter;
+import com.android.systemui.statusbar.car.PageIndicator;
import com.android.systemui.statusbar.car.UserGridView;
import com.android.systemui.statusbar.policy.UserSwitcherController;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* A quick settings fragment for the car. For auto, there is no row for quick settings or ability
* to expand the quick settings panel. Instead, the only thing is that displayed is the
* status bar, and a static row with access to the user switcher and settings.
*/
public class CarQSFragment extends Fragment implements QS {
+ private ViewGroup mPanel;
private View mHeader;
+ private View mUserSwitcherContainer;
private CarQSFooter mFooter;
+ private View mFooterUserName;
+ private View mFooterExpandIcon;
private UserGridView mUserGridView;
+ private PageIndicator mPageIndicator;
+ private AnimatorSet mAnimatorSet;
+ private UserSwitchCallback mUserSwitchCallback;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@@ -48,14 +65,26 @@ public class CarQSFragment extends Fragment implements QS {
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
+ mPanel = (ViewGroup) view;
mHeader = view.findViewById(R.id.header);
mFooter = view.findViewById(R.id.qs_footer);
+ mFooterUserName = mFooter.findViewById(R.id.user_name);
+ mFooterExpandIcon = mFooter.findViewById(R.id.user_switch_expand_icon);
+
+ mUserSwitcherContainer = view.findViewById(R.id.user_switcher_container);
+
+ updateUserSwitcherHeight(0);
mUserGridView = view.findViewById(R.id.user_grid);
mUserGridView.init(null, Dependency.get(UserSwitcherController.class),
- false /* showInitially */);
+ false /* overrideAlpha */);
- mFooter.setUserGridView(mUserGridView);
+ mPageIndicator = view.findViewById(R.id.user_switcher_page_indicator);
+ mPageIndicator.setupWithViewPager(mUserGridView);
+
+ mUserSwitchCallback = new UserSwitchCallback();
+ mFooter.setUserSwitchCallback(mUserSwitchCallback);
+ mUserGridView.setUserSwitchCallback(mUserSwitchCallback);
}
@Override
@@ -82,11 +111,13 @@ public class CarQSFragment extends Fragment implements QS {
@Override
public void setHeaderListening(boolean listening) {
mFooter.setListening(listening);
+ mUserGridView.setListening(listening);
}
@Override
public void setListening(boolean listening) {
mFooter.setListening(listening);
+ mUserGridView.setListening(listening);
}
@Override
@@ -171,4 +202,126 @@ public class CarQSFragment extends Fragment implements QS {
public void setExpandClickListener(OnClickListener onClickListener) {
// No ability to expand the quick settings.
}
+
+ public class UserSwitchCallback {
+ private boolean mShowing;
+
+ public boolean isShowing() {
+ return mShowing;
+ }
+
+ public void show() {
+ mShowing = true;
+ animateHeightChange(true /* opening */);
+ }
+
+ public void hide() {
+ mShowing = false;
+ animateHeightChange(false /* opening */);
+ }
+
+ public void resetShowing() {
+ if (mShowing) {
+ for (int i = 0; i < mUserGridView.getChildCount(); i++) {
+ ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
+ // Need to bring the last child to the front to maintain the order in the pod
+ // container. Why? ¯\_(ツ)_/¯
+ if (podContainer.getChildCount() > 0) {
+ podContainer.getChildAt(podContainer.getChildCount() - 1).bringToFront();
+ }
+ // The alpha values are default to 0, so if the pods have been refreshed, they
+ // need to be set to 1 when showing.
+ for (int j = 0; j < podContainer.getChildCount(); j++) {
+ podContainer.getChildAt(j).setAlpha(1f);
+ }
+ }
+ }
+ }
+ }
+
+ private void updateUserSwitcherHeight(int height) {
+ ViewGroup.LayoutParams layoutParams = mUserSwitcherContainer.getLayoutParams();
+ layoutParams.height = height;
+ mUserSwitcherContainer.requestLayout();
+ }
+
+ private void animateHeightChange(boolean opening) {
+ // Animation in progress; cancel it to avoid contention.
+ if (mAnimatorSet != null){
+ mAnimatorSet.cancel();
+ }
+
+ List<Animator> allAnimators = new ArrayList<>();
+ ValueAnimator heightAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(getContext(),
+ opening ? R.anim.car_user_switcher_open_animation
+ : R.anim.car_user_switcher_close_animation);
+ heightAnimator.addUpdateListener(valueAnimator -> {
+ updateUserSwitcherHeight((Integer) valueAnimator.getAnimatedValue());
+ });
+ allAnimators.add(heightAnimator);
+
+ // The user grid contains pod containers that each contain a number of pods. Animate
+ // all pods to avoid any discrepancy/race conditions with possible changes during the
+ // animation.
+ int cascadeDelay = getResources().getInteger(
+ R.integer.car_user_switcher_anim_cascade_delay_ms);
+ for (int i = 0; i < mUserGridView.getChildCount(); i++) {
+ ViewGroup podContainer = (ViewGroup) mUserGridView.getChildAt(i);
+ for (int j = 0; j < podContainer.getChildCount(); j++) {
+ View pod = podContainer.getChildAt(j);
+ Animator podAnimator = AnimatorInflater.loadAnimator(getContext(),
+ opening ? R.anim.car_user_switcher_open_pod_animation
+ : R.anim.car_user_switcher_close_pod_animation);
+ // Add the cascading delay between pods
+ if (opening) {
+ podAnimator.setStartDelay(podAnimator.getStartDelay() + j * cascadeDelay);
+ }
+ podAnimator.setTarget(pod);
+ allAnimators.add(podAnimator);
+ }
+ }
+
+ Animator nameAnimator = AnimatorInflater.loadAnimator(getContext(),
+ opening ? R.anim.car_user_switcher_open_name_animation
+ : R.anim.car_user_switcher_close_name_animation);
+ nameAnimator.setTarget(mFooterUserName);
+ allAnimators.add(nameAnimator);
+
+ Animator iconAnimator = AnimatorInflater.loadAnimator(getContext(),
+ opening ? R.anim.car_user_switcher_open_icon_animation
+ : R.anim.car_user_switcher_close_icon_animation);
+ iconAnimator.setTarget(mFooterExpandIcon);
+ allAnimators.add(iconAnimator);
+
+ Animator pageAnimator = AnimatorInflater.loadAnimator(getContext(),
+ opening ? R.anim.car_user_switcher_open_pages_animation
+ : R.anim.car_user_switcher_close_pages_animation);
+ pageAnimator.setTarget(mPageIndicator);
+ allAnimators.add(pageAnimator);
+
+ mAnimatorSet = new AnimatorSet();
+ mAnimatorSet.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimatorSet = null;
+ }
+ });
+ mAnimatorSet.playTogether(allAnimators.toArray(new Animator[0]));
+
+ // Setup all values to the start values in the animations, since there are delays, but need
+ // to have all values start at the beginning.
+ setupInitialValues(mAnimatorSet);
+
+ mAnimatorSet.start();
+ }
+
+ private void setupInitialValues(Animator anim) {
+ if (anim instanceof AnimatorSet) {
+ for (Animator a : ((AnimatorSet) anim).getChildAnimations()) {
+ setupInitialValues(a);
+ }
+ } else if (anim instanceof ObjectAnimator) {
+ ((ObjectAnimator) anim).setCurrentFraction(0.0f);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index fff9f8e7e038..2607ebbb72ea 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -18,7 +18,9 @@ package com.android.systemui.qs.tiles;
import static com.android.settingslib.graph.BluetoothDeviceLayerDrawable.createLayerDrawable;
+import android.annotation.Nullable;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothClass;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
@@ -26,7 +28,6 @@ import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.provider.Settings;
import android.service.quicksettings.Tile;
-import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Switch;
@@ -35,6 +36,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settingslib.Utils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.graph.BluetoothDeviceLayerDrawable;
import com.android.systemui.Dependency;
import com.android.systemui.R;
import com.android.systemui.plugins.ActivityStarter;
@@ -126,21 +128,25 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
}
state.slash.isSlashed = !enabled;
state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
+
if (enabled) {
if (connected) {
state.icon = ResourceIcon.get(R.drawable.ic_qs_bluetooth_connected);
- state.secondaryLabel = mController.getLastDeviceName();
- CachedBluetoothDevice lastDevice = mController.getLastDevice();
+ state.contentDescription = mContext.getString(
+ R.string.accessibility_bluetooth_name, state.label);
+
+ final CachedBluetoothDevice lastDevice = mController.getLastDevice();
if (lastDevice != null) {
- int batteryLevel = lastDevice.getBatteryLevel();
+ final int batteryLevel = lastDevice.getBatteryLevel();
if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
- state.icon = new BluetoothBatteryTileIcon(lastDevice,
+ state.icon = new BluetoothBatteryTileIcon(
+ batteryLevel,
mContext.getResources().getFraction(
R.fraction.bt_battery_scale_fraction, 1, 1));
}
}
- state.contentDescription = mContext.getString(
- R.string.accessibility_bluetooth_name, state.secondaryLabel);
+
+ state.label = mController.getLastDeviceName();
} else if (state.isTransient) {
state.icon = ResourceIcon.get(R.drawable.ic_bluetooth_transient_animation);
state.contentDescription = mContext.getString(
@@ -159,11 +165,53 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
state.state = Tile.STATE_INACTIVE;
}
+ state.secondaryLabel = getSecondaryLabel(enabled, connected);
+
state.dualLabelContentDescription = mContext.getResources().getString(
R.string.accessibility_quick_settings_open_settings, getTileLabel());
state.expandedAccessibilityClassName = Switch.class.getName();
}
+ /**
+ * Returns the secondary label to use for the given bluetooth connection in the form of the
+ * battery level or bluetooth profile name. If the bluetooth is disabled, there's no connected
+ * devices, or we can't map the bluetooth class to a profile, this instead returns {@code null}.
+ *
+ * @param enabled whether bluetooth is enabled
+ * @param connected whether there's a device connected via bluetooth
+ */
+ @Nullable
+ private String getSecondaryLabel(boolean enabled, boolean connected) {
+ final CachedBluetoothDevice lastDevice = mController.getLastDevice();
+
+ if (enabled && connected && lastDevice != null) {
+ final int batteryLevel = lastDevice.getBatteryLevel();
+
+ if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
+ return mContext.getString(
+ R.string.quick_settings_bluetooth_secondary_label_battery_level,
+ Utils.formatPercentage(batteryLevel));
+
+ } else {
+ final BluetoothClass bluetoothClass = lastDevice.getBtClass();
+ if (bluetoothClass != null) {
+ if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_A2DP)) {
+ return mContext.getString(
+ R.string.quick_settings_bluetooth_secondary_label_audio);
+ } else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HEADSET)) {
+ return mContext.getString(
+ R.string.quick_settings_bluetooth_secondary_label_headset);
+ } else if (bluetoothClass.doesClassMatch(BluetoothClass.PROFILE_HID)) {
+ return mContext.getString(
+ R.string.quick_settings_bluetooth_secondary_label_input);
+ }
+ }
+ }
+ }
+
+ return null;
+ }
+
@Override
public int getMetricsCategory() {
return MetricsEvent.QS_BLUETOOTH;
@@ -207,20 +255,29 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
return new BluetoothDetailAdapter();
}
+ /**
+ * Bluetooth icon wrapper for Quick Settings with a battery indicator that reflects the
+ * connected device's battery level. This is used instead of
+ * {@link com.android.systemui.qs.tileimpl.QSTileImpl.DrawableIcon} in order to use a context
+ * that reflects dark/light theme attributes.
+ */
private class BluetoothBatteryTileIcon extends Icon {
+ private int mBatteryLevel;
private float mIconScale;
- private CachedBluetoothDevice mDevice;
- BluetoothBatteryTileIcon(CachedBluetoothDevice device, float iconScale) {
+ BluetoothBatteryTileIcon(int batteryLevel, float iconScale) {
+ mBatteryLevel = batteryLevel;
mIconScale = iconScale;
- mDevice = device;
}
@Override
public Drawable getDrawable(Context context) {
// This method returns Pair<Drawable, String> while first value is the drawable
- return com.android.settingslib.bluetooth.Utils.getBtClassDrawableWithDescription(
- context, mDevice, mIconScale).first;
+ return BluetoothDeviceLayerDrawable.createLayerDrawable(
+ context,
+ R.drawable.ic_qs_bluetooth_connected,
+ mBatteryLevel,
+ mIconScale);
}
}
@@ -302,8 +359,7 @@ public class BluetoothTile extends QSTileImpl<BooleanState> {
item.iconResId = R.drawable.ic_qs_bluetooth_connected;
int batteryLevel = device.getBatteryLevel();
if (batteryLevel != BluetoothDevice.BATTERY_LEVEL_UNKNOWN) {
- item.icon = new BluetoothBatteryTileIcon(device,
- 1 /* iconScale */);
+ item.icon = new BluetoothBatteryTileIcon(batteryLevel,1 /* iconScale */);
item.line2 = mContext.getString(
R.string.quick_settings_connected_battery_level,
Utils.formatPercentage(batteryLevel));
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 675aa8f73a09..0132fa850f95 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -185,7 +185,7 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
// The public notification will show similar info but with the actual screenshot omitted
mPublicNotificationBuilder =
- new Notification.Builder(context, NotificationChannels.SCREENSHOTS)
+ new Notification.Builder(context, NotificationChannels.SCREENSHOTS_HEADSUP)
.setContentTitle(r.getString(R.string.screenshot_saving_title))
.setContentText(r.getString(R.string.screenshot_saving_text))
.setSmallIcon(R.drawable.stat_notify_image)
@@ -196,7 +196,8 @@ class SaveImageInBackgroundTask extends AsyncTask<Void, Void, Void> {
com.android.internal.R.color.system_notification_accent_color));
SystemUI.overrideNotificationAppName(context, mPublicNotificationBuilder);
- mNotificationBuilder = new Notification.Builder(context, NotificationChannels.SCREENSHOTS)
+ mNotificationBuilder = new Notification.Builder(context,
+ NotificationChannels.SCREENSHOTS_HEADSUP)
.setTicker(r.getString(R.string.screenshot_saving_ticker)
+ (mTickerAddSpace ? " " : ""))
.setContentTitle(r.getString(R.string.screenshot_saving_title))
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 172c62a99db2..3ec89138d1c0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -53,7 +53,7 @@ public class FullscreenUserSwitcher {
mParent = containerStub.inflate();
mContainer = mParent.findViewById(R.id.container);
mUserGridView = mContainer.findViewById(R.id.user_grid);
- mUserGridView.init(statusBar, mUserSwitcherController, true /* showInitially */);
+ mUserGridView.init(statusBar, mUserSwitcherController, true /* overrideAlpha */);
mUserGridView.setUserSelectionListener(record -> {
if (!record.isCurrent) {
toggleSwitchInProgress(true);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
index e551801ca434..1bd820db3f7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/UserGridView.java
@@ -16,9 +16,6 @@
package com.android.systemui.statusbar.car;
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
@@ -29,62 +26,110 @@ import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
-import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.systemui.Dependency;
import com.android.systemui.R;
+import com.android.systemui.qs.car.CarQSFragment;
import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.policy.UserInfoController;
import com.android.systemui.statusbar.policy.UserSwitcherController;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Vector;
+
/**
* Displays a ViewPager with icons for the users in the system to allow switching between users.
* One of the uses of this is for the lock screen in auto.
*/
-public class UserGridView extends ViewPager {
- private static final int EXPAND_ANIMATION_TIME_MS = 200;
- private static final int HIDE_ANIMATION_TIME_MS = 133;
-
+public class UserGridView extends ViewPager implements
+ UserInfoController.OnUserInfoChangedListener {
private StatusBar mStatusBar;
private UserSwitcherController mUserSwitcherController;
private Adapter mAdapter;
private UserSelectionListener mUserSelectionListener;
- private ValueAnimator mHeightAnimator;
- private int mTargetHeight;
- private int mHeightChildren;
- private boolean mShowing;
+ private UserInfoController mUserInfoController;
+ private Vector mUserContainers;
+ private int mContainerWidth;
+ private boolean mOverrideAlpha;
+ private CarQSFragment.UserSwitchCallback mUserSwitchCallback;
public UserGridView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void init(StatusBar statusBar, UserSwitcherController userSwitcherController,
- boolean showInitially) {
+ boolean overrideAlpha) {
mStatusBar = statusBar;
mUserSwitcherController = userSwitcherController;
mAdapter = new Adapter(mUserSwitcherController);
- addOnLayoutChangeListener(mAdapter);
- setAdapter(mAdapter);
- mShowing = showInitially;
+ mUserInfoController = Dependency.get(UserInfoController.class);
+ mOverrideAlpha = overrideAlpha;
+ // Whenever the container width changes, the containers must be refreshed. Instead of
+ // doing an initial refreshContainers() to populate the containers, this listener will
+ // refresh them on layout change because that affects how the users are split into
+ // containers. Furthermore, at this point, the container width is unknown, so
+ // refreshContainers() cannot populate any containers.
+ addOnLayoutChangeListener(
+ (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> {
+ int newWidth = Math.max(left - right, right - left);
+ if (mContainerWidth != newWidth) {
+ mContainerWidth = newWidth;
+ refreshContainers();
+ }
+ });
}
- public boolean isShowing() {
- return mShowing;
+ private void refreshContainers() {
+ mUserContainers = new Vector();
+
+ Context context = getContext();
+ LayoutInflater inflater = LayoutInflater.from(context);
+
+ for (int i = 0; i < mAdapter.getCount(); i++) {
+ ViewGroup pods = (ViewGroup) inflater.inflate(
+ R.layout.car_fullscreen_user_pod_container, null);
+
+ int iconsPerPage = mAdapter.getIconsPerPage();
+ int limit = Math.min(mUserSwitcherController.getUsers().size(), (i + 1) * iconsPerPage);
+ for (int j = i * iconsPerPage; j < limit; j++) {
+ View v = mAdapter.makeUserPod(inflater, context, j, pods);
+ if (mOverrideAlpha) {
+ v.setAlpha(1f);
+ }
+ pods.addView(v);
+ // This is hacky, but the dividers on the pod container LinearLayout don't seem
+ // to work for whatever reason. Instead, set a right margin on the pod if it's not
+ // the right-most pod and there is more than one pod in the container.
+ if (i < limit - 1 && limit > 1) {
+ ViewGroup.MarginLayoutParams params =
+ (ViewGroup.MarginLayoutParams) v.getLayoutParams();
+ params.setMargins(0, 0, getResources().getDimensionPixelSize(
+ R.dimen.car_fullscreen_user_pod_margin_between), 0);
+ v.setLayoutParams(params);
+ }
+ }
+ mUserContainers.add(pods);
+ }
+
+ mAdapter = new Adapter(mUserSwitcherController);
+ setAdapter(mAdapter);
}
- public void show() {
- mShowing = true;
- animateHeightChange(getMeasuredHeight(), mHeightChildren);
+ @Override
+ public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+ refreshContainers();
}
- public void hide() {
- mShowing = false;
- animateHeightChange(getMeasuredHeight(), 0);
+ public void setUserSwitchCallback(CarQSFragment.UserSwitchCallback callback) {
+ mUserSwitchCallback = callback;
}
public void onUserSwitched(int newUserId) {
@@ -96,6 +141,14 @@ public class UserGridView extends ViewPager {
mUserSelectionListener = userSelectionListener;
}
+ public void setListening(boolean listening) {
+ if (listening) {
+ mUserInfoController.addCallback(this);
+ } else {
+ mUserInfoController.removeCallback(this);
+ }
+ }
+
void showOfflineAuthUi() {
// TODO: Show keyguard UI in-place.
mStatusBar.executeRunnableDismissingKeyguard(null, null, true, true, true);
@@ -115,13 +168,6 @@ public class UserGridView extends ViewPager {
height = Math.max(child.getMeasuredHeight(), height);
}
- mHeightChildren = height;
-
- // Override the height if it's not showing.
- if (!mShowing) {
- height = 0;
- }
-
// Respect the AT_MOST request from parent.
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
height = Math.min(MeasureSpec.getSize(heightMeasureSpec), height);
@@ -132,72 +178,19 @@ public class UserGridView extends ViewPager {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
- private void animateHeightChange(int oldHeight, int newHeight) {
- // If there is no change in height or an animation is already in progress towards the
- // desired height, then there's no need to make any changes.
- if (oldHeight == newHeight || newHeight == mTargetHeight) {
- return;
- }
-
- // Animation in progress is not going towards the new target, so cancel it.
- if (mHeightAnimator != null){
- mHeightAnimator.cancel();
- }
-
- mTargetHeight = newHeight;
- mHeightAnimator = ValueAnimator.ofInt(oldHeight, mTargetHeight);
- mHeightAnimator.addUpdateListener(valueAnimator -> {
- ViewGroup.LayoutParams layoutParams = getLayoutParams();
- layoutParams.height = (Integer) valueAnimator.getAnimatedValue();
- requestLayout();
- });
- mHeightAnimator.addListener(new AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animator) {}
-
- @Override
- public void onAnimationEnd(Animator animator) {
- // ValueAnimator does not guarantee that the update listener will get an update
- // to the final value, so here, the final value is set. Though the final calculated
- // height (mTargetHeight) could be set, WRAP_CONTENT is more appropriate.
- ViewGroup.LayoutParams layoutParams = getLayoutParams();
- layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT;
- requestLayout();
- mHeightAnimator = null;
- }
-
- @Override
- public void onAnimationCancel(Animator animator) {}
-
- @Override
- public void onAnimationRepeat(Animator animator) {}
- });
-
- mHeightAnimator.setInterpolator(new FastOutSlowInInterpolator());
- if (oldHeight < newHeight) {
- // Expanding
- mHeightAnimator.setDuration(EXPAND_ANIMATION_TIME_MS);
- } else {
- // Hiding
- mHeightAnimator.setDuration(HIDE_ANIMATION_TIME_MS);
- }
- mHeightAnimator.start();
- }
-
/**
* This is a ViewPager.PagerAdapter which deletegates the work to a
* UserSwitcherController.BaseUserAdapter. Java doesn't support multiple inheritance so we have
* to use composition instead to achieve the same goal since both the base classes are abstract
* classes and not interfaces.
*/
- private final class Adapter extends PagerAdapter implements View.OnLayoutChangeListener {
+ private final class Adapter extends PagerAdapter {
private final int mPodWidth;
private final int mPodMarginBetween;
private final int mPodImageAvatarWidth;
private final int mPodImageAvatarHeight;
private final WrappedBaseUserAdapter mUserAdapter;
- private int mContainerWidth;
public Adapter(UserSwitcherController controller) {
super();
@@ -229,30 +222,20 @@ public class UserGridView extends ViewPager {
}
@Override
- public Object instantiateItem(ViewGroup container, int position) {
- Context context = getContext();
- LayoutInflater inflater = LayoutInflater.from(context);
-
- ViewGroup pods = (ViewGroup) inflater.inflate(
- R.layout.car_fullscreen_user_pod_container, null);
+ public void finishUpdate(ViewGroup container) {
+ if (mUserSwitchCallback != null) {
+ mUserSwitchCallback.resetShowing();
+ }
+ }
- int iconsPerPage = getIconsPerPage();
- int limit = Math.min(mUserAdapter.getCount(), (position + 1) * iconsPerPage);
- for (int i = position * iconsPerPage; i < limit; i++) {
- View v = makeUserPod(inflater, context, i, pods);
- pods.addView(v);
- // This is hacky, but the dividers on the pod container LinearLayout don't seem
- // to work for whatever reason. Instead, set a right margin on the pod if it's not
- // the right-most pod and there is more than one pod in the container.
- if (i < limit - 1 && limit > 1) {
- LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- params.setMargins(0, 0, mPodMarginBetween, 0);
- v.setLayoutParams(params);
- }
+ @Override
+ public Object instantiateItem(ViewGroup container, int position) {
+ if (position < mUserContainers.size()) {
+ container.addView((View) mUserContainers.get(position));
+ return mUserContainers.get(position);
+ } else {
+ return null;
}
- container.addView(pods);
- return pods;
}
/**
@@ -353,17 +336,10 @@ public class UserGridView extends ViewPager {
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
-
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- mContainerWidth = Math.max(left - right, right - left);
- notifyDataSetChanged();
- }
}
private final class WrappedBaseUserAdapter extends UserSwitcherController.BaseUserAdapter {
- private Adapter mContainer;
+ private final Adapter mContainer;
public WrappedBaseUserAdapter(UserSwitcherController controller, Adapter container) {
super(controller);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 0cc7f5dfbae1..66cb59e3d317 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -72,6 +72,7 @@ import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.StackStateAnimator;
+import java.util.Collection;
import java.util.List;
public class NotificationPanelView extends PanelView implements
@@ -2621,8 +2622,10 @@ public class NotificationPanelView extends PanelView implements
}
}
- public void setPulsing(boolean pulsing) {
- mKeyguardStatusView.setPulsing(pulsing);
+ public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+ mKeyguardStatusView.setPulsing(pulsing != null);
+ mNotificationStackScroller.setPulsing(pulsing, mKeyguardStatusView.getLocationOnScreen()[1]
+ + mKeyguardStatusView.getClockBottom());
}
public void setAmbientIndicationBottomPadding(int ambientIndicationBottomPadding) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
index 6fc5bbdd5977..ee1d08872999 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickScrubController.java
@@ -28,6 +28,7 @@ import android.graphics.Paint;
import android.graphics.Rect;
import android.os.Handler;
import android.os.RemoteException;
+import android.os.SystemProperties;
import android.util.Log;
import android.util.Slog;
import android.view.Display;
@@ -131,7 +132,7 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene
new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velX, float velY) {
- if (mQuickScrubActive) {
+ if (!isQuickScrubEnabled() || mQuickScrubActive) {
return false;
}
float velocityX = mIsRTL ? -velX : velX;
@@ -196,12 +197,13 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene
case MotionEvent.ACTION_DOWN: {
int x = (int) event.getX();
int y = (int) event.getY();
- if (mHomeButtonRect.contains(x, y)) {
+ if (isQuickScrubEnabled() && mHomeButtonRect.contains(x, y)) {
mTouchDownX = x;
mTouchDownY = y;
homeButton.setDelayTouchFeedback(true);
mHandler.postDelayed(mLongPressRunnable, LONG_PRESS_DELAY_MS);
} else {
+ homeButton.setDelayTouchFeedback(false);
mTouchDownX = mTouchDownY = -1;
}
break;
@@ -356,6 +358,10 @@ public class QuickScrubController extends GestureDetector.SimpleOnGestureListene
}
}
+ boolean isQuickScrubEnabled() {
+ return SystemProperties.getBoolean("persist.quickstep.scrub.enabled", false);
+ }
+
private void startQuickScrub() {
if (!mQuickScrubActive) {
mQuickScrubActive = true;
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 c30fb22630da..3b783c2a079a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -4620,8 +4620,7 @@ public class StatusBar extends SystemUI implements DemoMode,
}
private void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
- mStackScroller.setPulsing(pulsing);
- mNotificationPanel.setPulsing(pulsing != null);
+ mNotificationPanel.setPulsing(pulsing);
mVisualStabilityManager.setPulsing(pulsing != null);
mIgnoreTouchWhilePulsing = false;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 443e760d88ae..af3d64be0fd0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -399,6 +399,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private final int mSeparatorWidth;
private final int mSeparatorThickness;
private final Rect mTmpRect = new Rect();
+ private int mClockBottom;
public NotificationStackScrollLayout(Context context) {
this(context, null);
@@ -510,7 +511,9 @@ public class NotificationStackScrollLayout extends ViewGroup
final int darkTop = (int) (mRegularTopPadding + mSeparatorThickness / 2f);
final int darkBottom = darkTop + mSeparatorThickness;
- if (mAmbientState.isDark()) {
+ if (mAmbientState.hasPulsingNotifications()) {
+ // TODO draw divider between notification and shelf
+ } else if (mAmbientState.isDark()) {
// Only draw divider on AOD if we actually have notifications
if (mFirstVisibleBackgroundChild != null) {
canvas.drawRect(darkLeft, darkTop, darkRight, darkBottom, mBackgroundPaint);
@@ -684,7 +687,11 @@ public class NotificationStackScrollLayout extends ViewGroup
}
private void updateAlgorithmHeightAndPadding() {
- mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding;
+ if (mPulsing != null) {
+ mTopPadding = mClockBottom;
+ } else {
+ mTopPadding = mAmbientState.isDark() ? mDarkTopPadding : mRegularTopPadding;
+ }
mAmbientState.setLayoutHeight(getLayoutHeight());
updateAlgorithmLayoutMinHeight();
mAmbientState.setTopPadding(mTopPadding);
@@ -4322,13 +4329,15 @@ public class NotificationStackScrollLayout extends ViewGroup
return mIsExpanded;
}
- public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing) {
+ public void setPulsing(Collection<HeadsUpManager.HeadsUpEntry> pulsing, int clockBottom) {
if (mPulsing == null && pulsing == null) {
return;
}
mPulsing = pulsing;
+ mClockBottom = clockBottom;
mAmbientState.setPulsing(pulsing);
updateNotificationAnimationStates();
+ updateAlgorithmHeightAndPadding();
updateContentHeight();
notifyHeightChangeListener(mShelf);
requestChildrenUpdate();
diff --git a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
index 87bc0e67f7be..14d5c6f52cd0 100644
--- a/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
+++ b/packages/SystemUI/src/com/android/systemui/util/NotificationChannels.java
@@ -31,7 +31,8 @@ import java.util.Arrays;
public class NotificationChannels extends SystemUI {
public static String ALERTS = "ALR";
- public static String SCREENSHOTS = "SCN";
+ public static String SCREENSHOTS_LEGACY = "SCN";
+ public static String SCREENSHOTS_HEADSUP = "SCN_HEADSUP";
public static String GENERAL = "GEN";
public static String STORAGE = "DSK";
public static String TVPIP = "TPP";
@@ -56,10 +57,6 @@ public class NotificationChannels extends SystemUI {
context.getString(R.string.notification_channel_alerts),
NotificationManager.IMPORTANCE_HIGH),
new NotificationChannel(
- SCREENSHOTS,
- context.getString(R.string.notification_channel_screenshot),
- NotificationManager.IMPORTANCE_LOW),
- new NotificationChannel(
GENERAL,
context.getString(R.string.notification_channel_general),
NotificationManager.IMPORTANCE_MIN),
@@ -69,9 +66,18 @@ public class NotificationChannels extends SystemUI {
isTv(context)
? NotificationManager.IMPORTANCE_DEFAULT
: NotificationManager.IMPORTANCE_LOW),
+ createScreenshotChannel(
+ context.getString(R.string.notification_channel_screenshot),
+ nm.getNotificationChannel(SCREENSHOTS_LEGACY)),
batteryChannel
));
+ // Delete older SS channel if present.
+ // Screenshots promoted to heads-up in P, this cleans up the lower priority channel from O.
+ // This line can be deleted in Q.
+ nm.deleteNotificationChannel(SCREENSHOTS_LEGACY);
+
+
if (isTv(context)) {
// TV specific notification channel for TV PIP controls.
// Importance should be {@link NotificationManager#IMPORTANCE_MAX} to have the highest
@@ -83,6 +89,40 @@ public class NotificationChannels extends SystemUI {
}
}
+ /**
+ * Set up screenshot channel, respecting any previously committed user settings on legacy
+ * channel.
+ * @return
+ */
+ @VisibleForTesting static NotificationChannel createScreenshotChannel(
+ String name, NotificationChannel legacySS) {
+ NotificationChannel screenshotChannel = new NotificationChannel(SCREENSHOTS_HEADSUP,
+ name, NotificationManager.IMPORTANCE_HIGH); // pop on screen
+
+ screenshotChannel.setSound(Uri.parse(""), // silent
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_NOTIFICATION).build());
+
+ if (legacySS != null) {
+ // Respect any user modified fields from the old channel.
+ int userlock = legacySS.getUserLockedFields();
+ if ((userlock & NotificationChannel.USER_LOCKED_IMPORTANCE) != 0) {
+ screenshotChannel.setImportance(legacySS.getImportance());
+ }
+ if ((userlock & NotificationChannel.USER_LOCKED_SOUND) != 0) {
+ screenshotChannel.setSound(legacySS.getSound(), legacySS.getAudioAttributes());
+ }
+ if ((userlock & NotificationChannel.USER_LOCKED_VIBRATION) != 0) {
+ screenshotChannel.setVibrationPattern(legacySS.getVibrationPattern());
+ }
+ if ((userlock & NotificationChannel.USER_LOCKED_LIGHTS) != 0) {
+ screenshotChannel.setLightColor(legacySS.getLightColor());
+ }
+ // skip show_badge, irrelevant for system channel
+ }
+
+ return screenshotChannel;
+ }
+
@Override
public void start() {
createAll(mContext);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
index 04bdc04a64d9..80dc2c97e1e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/ChannelsTest.java
@@ -26,11 +26,14 @@ import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
+import android.net.Uri;
+import android.provider.Settings;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.util.NotificationChannels;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,7 +57,7 @@ public class ChannelsTest extends SysuiTestCase {
public void testChannelSetup() {
Set<String> ALL_CHANNELS = new ArraySet<>(Arrays.asList(
NotificationChannels.ALERTS,
- NotificationChannels.SCREENSHOTS,
+ NotificationChannels.SCREENSHOTS_HEADSUP,
NotificationChannels.STORAGE,
NotificationChannels.GENERAL,
NotificationChannels.BATTERY
@@ -66,4 +69,52 @@ public class ChannelsTest extends SysuiTestCase {
assertEquals(ALL_CHANNELS.size(), list.size());
list.forEach((chan) -> assertTrue(ALL_CHANNELS.contains(chan.getId())));
}
+
+ @Test
+ public void testChannelSetup_noLegacyScreenshot() {
+ // Assert old channel cleaned up.
+ // TODO: remove that code + this test after P.
+ NotificationChannels.createAll(mContext);
+ ArgumentCaptor<List> captor = ArgumentCaptor.forClass(List.class);
+ verify(mMockNotificationManager).deleteNotificationChannel(
+ NotificationChannels.SCREENSHOTS_LEGACY);
+ }
+
+ @Test
+ public void testInheritFromLegacy_keepsUserLockedLegacySettings() {
+ NotificationChannel legacyChannel = new NotificationChannel("id", "oldName",
+ NotificationManager.IMPORTANCE_MIN);
+ legacyChannel.setImportance(NotificationManager.IMPORTANCE_NONE);;
+ legacyChannel.setSound(Settings.System.DEFAULT_NOTIFICATION_URI,
+ legacyChannel.getAudioAttributes());
+ legacyChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE |
+ NotificationChannel.USER_LOCKED_SOUND);
+ NotificationChannel newChannel =
+ NotificationChannels.createScreenshotChannel("newName", legacyChannel);
+ // NONE importance user locked, so don't use HIGH for new channel.
+ assertEquals(NotificationManager.IMPORTANCE_NONE, newChannel.getImportance());
+ assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, newChannel.getSound());
+ }
+
+ @Test
+ public void testInheritFromLegacy_dropsUnlockedLegacySettings() {
+ NotificationChannel legacyChannel = new NotificationChannel("id", "oldName",
+ NotificationManager.IMPORTANCE_MIN);
+ NotificationChannel newChannel =
+ NotificationChannels.createScreenshotChannel("newName", legacyChannel);
+ assertEquals(Uri.EMPTY, newChannel.getSound());
+ assertEquals("newName", newChannel.getName());
+ // MIN importance not user locked, so HIGH wins out.
+ assertEquals(NotificationManager.IMPORTANCE_HIGH, newChannel.getImportance());
+ }
+
+ @Test
+ public void testInheritFromLegacy_noLegacyExists() {
+ NotificationChannel newChannel =
+ NotificationChannels.createScreenshotChannel("newName", null);
+ assertEquals(Uri.EMPTY, newChannel.getSound());
+ assertEquals("newName", newChannel.getName());
+ assertEquals(NotificationManager.IMPORTANCE_HIGH, newChannel.getImportance());
+ }
+
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index 9b67f8f32704..4144bbd46fb1 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -5149,6 +5149,11 @@ message MetricsEvent {
// OS: P
FUELGAUGE_RESTRICTED_APP_DETAILS = 1285;
+ // OPEN: Settings > Sound & notification > Do Not Disturb > Turn on now
+ // CATEGORY: SETTINGS
+ // OS: P
+ NOTIFICATION_ZEN_MODE_ENABLE_DIALOG = 1286;
+
// ---- End P Constants, all P constants go above this line ----
// Add new aosp constants above this line.
// END OF AOSP CONSTANTS
diff --git a/services/core/Android.bp b/services/core/Android.bp
index 3369458595a8..8da6d1e48ffe 100644
--- a/services/core/Android.bp
+++ b/services/core/Android.bp
@@ -32,6 +32,7 @@ java_library_static {
static_libs: [
"time_zone_distro",
"time_zone_distro_installer",
+ "android.hardware.authsecret-V1.0-java",
"android.hardware.broadcastradio-V2.0-java",
"android.hardware.health-V1.0-java",
"android.hardware.health-V2.0-java",
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index ef6bc437cb6c..24d493e3013e 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -571,6 +571,8 @@ public class IpSecService extends IIpSecService.Stub {
mConfig = config;
mSpi = spi;
mSocket = socket;
+
+ spi.setOwnedByTransform();
}
public IpSecConfig getConfig() {
@@ -651,16 +653,6 @@ public class IpSecService extends IIpSecService.Stub {
/** always guarded by IpSecService#this */
@Override
public void freeUnderlyingResources() {
- if (mOwnedByTransform) {
- Log.d(TAG, "Cannot release Spi " + mSpi + ": Currently locked by a Transform");
- // Because SPIs are "handed off" to transform, objects, they should never be
- // freed from the SpiRecord once used in a transform. (They refer to the same SA,
- // thus ownership and responsibility for freeing these resources passes to the
- // Transform object). Thus, we should let the user free them without penalty once
- // they are applied in a Transform object.
- return;
- }
-
try {
mSrvConfig
.getNetdInstance()
@@ -694,6 +686,10 @@ public class IpSecService extends IIpSecService.Stub {
mOwnedByTransform = true;
}
+ public boolean getOwnedByTransform() {
+ return mOwnedByTransform;
+ }
+
@Override
public void invalidate() throws RemoteException {
getUserRecord().removeSpiRecord(mResourceId);
@@ -1107,6 +1103,11 @@ public class IpSecService extends IIpSecService.Stub {
// Retrieve SPI record; will throw IllegalArgumentException if not found
SpiRecord s = userRecord.mSpiRecords.getResourceOrThrow(config.getSpiResourceId());
+ // Check to ensure that SPI has not already been used.
+ if (s.getOwnedByTransform()) {
+ throw new IllegalStateException("SPI already in use; cannot be used in new Transforms");
+ }
+
// If no remote address is supplied, then use one from the SPI.
if (TextUtils.isEmpty(config.getDestinationAddress())) {
config.setDestinationAddress(s.getDestinationAddress());
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index dc34567532bd..1eec982a0a9a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4711,7 +4711,8 @@ public class ActivityManagerService extends IActivityManager.Stub
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
- .setMayWait(bOptions, userId)
+ .setActivityOptions(bOptions)
+ .setMayWait(userId)
.execute();
}
@@ -4782,7 +4783,8 @@ public class ActivityManagerService extends IActivityManager.Stub
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
- .setMayWait(bOptions, userId)
+ .setActivityOptions(bOptions)
+ .setMayWait(userId)
.setIgnoreTargetSecurity(ignoreTargetSecurity)
.execute();
} catch (SecurityException e) {
@@ -4818,7 +4820,8 @@ public class ActivityManagerService extends IActivityManager.Stub
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
- .setMayWait(bOptions, userId)
+ .setActivityOptions(bOptions)
+ .setMayWait(userId)
.setProfilerInfo(profilerInfo)
.setWaitResult(res)
.execute();
@@ -4842,7 +4845,8 @@ public class ActivityManagerService extends IActivityManager.Stub
.setRequestCode(requestCode)
.setStartFlags(startFlags)
.setGlobalConfiguration(config)
- .setMayWait(bOptions, userId)
+ .setActivityOptions(bOptions)
+ .setMayWait(userId)
.execute();
}
@@ -4897,7 +4901,8 @@ public class ActivityManagerService extends IActivityManager.Stub
.setVoiceInteractor(interactor)
.setStartFlags(startFlags)
.setProfilerInfo(profilerInfo)
- .setMayWait(bOptions, userId)
+ .setActivityOptions(bOptions)
+ .setMayWait(userId)
.execute();
}
@@ -4912,7 +4917,8 @@ public class ActivityManagerService extends IActivityManager.Stub
.setCallingUid(callingUid)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
- .setMayWait(bOptions, userId)
+ .setActivityOptions(bOptions)
+ .setMayWait(userId)
.execute();
}
@@ -4927,6 +4933,7 @@ public class ActivityManagerService extends IActivityManager.Stub
throw new SecurityException(msg);
}
+ final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
final int recentsUid = mRecentTasks.getRecentsComponentUid();
final ComponentName recentsComponent = mRecentTasks.getRecentsComponent();
final String recentsPackage = recentsComponent.getPackageName();
@@ -4957,7 +4964,8 @@ public class ActivityManagerService extends IActivityManager.Stub
return mActivityStartController.obtainStarter(intent, "startRecentsActivity")
.setCallingUid(recentsUid)
.setCallingPackage(recentsPackage)
- .setMayWait(activityOptions, userId)
+ .setActivityOptions(safeOptions)
+ .setMayWait(userId)
.execute();
}
} finally {
@@ -5045,17 +5053,17 @@ public class ActivityManagerService extends IActivityManager.Stub
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
- ActivityOptions options = ActivityOptions.fromBundle(bOptions);
+ SafeActivityOptions options = SafeActivityOptions.fromBundle(bOptions);
synchronized (this) {
final ActivityRecord r = ActivityRecord.isInStackLocked(callingActivity);
if (r == null) {
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
return false;
}
if (r.app == null || r.app.thread == null) {
// The caller is not running... d'oh!
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
return false;
}
intent = new Intent(intent);
@@ -5100,7 +5108,7 @@ public class ActivityManagerService extends IActivityManager.Stub
if (aInfo == null) {
// Nobody who is next!
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
if (debug) Slog.d(TAG, "Next matching activity: nothing found");
return false;
}
@@ -5162,10 +5170,13 @@ public class ActivityManagerService extends IActivityManager.Stub
enforceCallerIsRecentsOrHasPermission(START_TASKS_FROM_RECENTS,
"startActivityFromRecents()");
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
- return mStackSupervisor.startActivityFromRecents(taskId, bOptions);
+ return mStackSupervisor.startActivityFromRecents(callingPid, callingUid, taskId,
+ SafeActivityOptions.fromBundle(bOptions));
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -5182,7 +5193,8 @@ public class ActivityManagerService extends IActivityManager.Stub
userId, false, ALLOW_FULL_ONLY, reason, null);
// TODO: Switch to user app stacks here.
int ret = mActivityStartController.startActivities(caller, -1, callingPackage,
- intents, resolvedTypes, resultTo, bOptions, userId, reason);
+ intents, resolvedTypes, resultTo, SafeActivityOptions.fromBundle(bOptions), userId,
+ reason);
return ret;
}
@@ -7941,9 +7953,9 @@ public class ActivityManagerService extends IActivityManager.Stub
flags &= ~(PendingIntent.FLAG_NO_CREATE|PendingIntent.FLAG_CANCEL_CURRENT
|PendingIntent.FLAG_UPDATE_CURRENT);
- PendingIntentRecord.Key key = new PendingIntentRecord.Key(
- type, packageName, activity, resultWho,
- requestCode, intents, resolvedTypes, flags, bOptions, userId);
+ PendingIntentRecord.Key key = new PendingIntentRecord.Key(type, packageName, activity,
+ resultWho, requestCode, intents, resolvedTypes, flags,
+ SafeActivityOptions.fromBundle(bOptions), userId);
WeakReference<PendingIntentRecord> ref;
ref = mIntentSenderRecords.get(key);
PendingIntentRecord rec = ref != null ? ref.get() : null;
@@ -10434,9 +10446,13 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public void startInPlaceAnimationOnFrontMostApplication(Bundle opts)
throws RemoteException {
- final ActivityOptions activityOptions = ActivityOptions.fromBundle(opts);
- if (activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE ||
- activityOptions.getCustomInPlaceResId() == 0) {
+ final SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(opts);
+ final ActivityOptions activityOptions = safeOptions != null
+ ? safeOptions.getOptions(mStackSupervisor)
+ : null;
+ if (activityOptions == null
+ || activityOptions.getAnimationType() != ActivityOptions.ANIM_CUSTOM_IN_PLACE
+ || activityOptions.getCustomInPlaceResId() == 0) {
throw new IllegalArgumentException("Expected in-place ActivityOption " +
"with valid animation");
}
@@ -10539,16 +10555,17 @@ public class ActivityManagerService extends IActivityManager.Stub
if (DEBUG_STACK) Slog.d(TAG_STACK, "moveTaskToFront: moving taskId=" + taskId);
synchronized(this) {
- moveTaskToFrontLocked(taskId, flags, bOptions, false /* fromRecents */);
+ moveTaskToFrontLocked(taskId, flags, SafeActivityOptions.fromBundle(bOptions),
+ false /* fromRecents */);
}
}
- void moveTaskToFrontLocked(int taskId, int flags, Bundle bOptions, boolean fromRecents) {
- ActivityOptions options = ActivityOptions.fromBundle(bOptions);
+ void moveTaskToFrontLocked(int taskId, int flags, SafeActivityOptions options,
+ boolean fromRecents) {
if (!checkAppSwitchAllowedLocked(Binder.getCallingPid(),
Binder.getCallingUid(), -1, -1, "Task to front")) {
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
return;
}
final long origId = Binder.clearCallingIdentity();
@@ -10562,7 +10579,10 @@ public class ActivityManagerService extends IActivityManager.Stub
Slog.e(TAG, "moveTaskToFront: Attempt to violate Lock Task Mode");
return;
}
- mStackSupervisor.findTaskToMoveToFront(task, flags, options, "moveTaskToFront",
+ ActivityOptions realOptions = options != null
+ ? options.getOptions(mStackSupervisor)
+ : null;
+ mStackSupervisor.findTaskToMoveToFront(task, flags, realOptions, "moveTaskToFront",
false /* forceNonResizable */);
final ActivityRecord topActivity = task.getTopActivity();
@@ -10576,7 +10596,7 @@ public class ActivityManagerService extends IActivityManager.Stub
} finally {
Binder.restoreCallingIdentity(origId);
}
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
}
/**
@@ -13534,6 +13554,7 @@ public class ActivityManagerService extends IActivityManager.Stub
@Override
public boolean convertToTranslucent(IBinder token, Bundle options) {
+ SafeActivityOptions safeOptions = SafeActivityOptions.fromBundle(options);
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
@@ -13545,7 +13566,7 @@ public class ActivityManagerService extends IActivityManager.Stub
int index = task.mActivities.lastIndexOf(r);
if (index > 0) {
ActivityRecord under = task.mActivities.get(index - 1);
- under.returningOptions = ActivityOptions.fromBundle(options);
+ under.returningOptions = safeOptions.getOptions(r);
}
final boolean translucentChanged = r.changeWindowTranslucency(false);
if (translucentChanged) {
@@ -24909,7 +24930,8 @@ public class ActivityManagerService extends IActivityManager.Stub
synchronized (ActivityManagerService.this) {
return mActivityStartController.startActivitiesInPackage(packageUid, packageName,
- intents, resolvedTypes, /*resultTo*/ null, bOptions, userId);
+ intents, resolvedTypes, null /* resultTo */,
+ SafeActivityOptions.fromBundle(bOptions), userId);
}
}
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index eb14bbda4c4b..bfb563fd93a8 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1591,7 +1591,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
boolean checkStartAnyActivityPermission(Intent intent, ActivityInfo aInfo,
String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, boolean ignoreTargetSecurity, ProcessRecord callerApp,
- ActivityRecord resultRecord, ActivityStack resultStack, ActivityOptions options) {
+ ActivityRecord resultRecord, ActivityStack resultStack) {
final int startAnyPerm = mService.checkPermission(START_ANY_ACTIVITY, callingPid,
callingUid);
if (startAnyPerm == PERMISSION_GRANTED) {
@@ -1645,57 +1645,6 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
Slog.w(TAG, message);
return false;
}
- if (options != null) {
- // If a launch task id is specified, then ensure that the caller is the recents
- // component or has the START_TASKS_FROM_RECENTS permission
- if (options.getLaunchTaskId() != INVALID_TASK_ID
- && !mRecentTasks.isCallerRecents(callingUid)) {
- final int startInTaskPerm = mService.checkPermission(START_TASKS_FROM_RECENTS,
- callingPid, callingUid);
- if (startInTaskPerm == PERMISSION_DENIED) {
- final String msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ") with launchTaskId="
- + options.getLaunchTaskId();
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
- }
- // Check if someone tries to launch an activity on a private display with a different
- // owner.
- final int launchDisplayId = options.getLaunchDisplayId();
- if (launchDisplayId != INVALID_DISPLAY && !isCallerAllowedToLaunchOnDisplay(callingPid,
- callingUid, launchDisplayId, aInfo)) {
- final String msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ") with launchDisplayId="
- + launchDisplayId;
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
- // Check if someone tries to launch an unwhitelisted activity into LockTask mode.
- final boolean lockTaskMode = options.getLockTaskMode();
- if (lockTaskMode && !mService.mLockTaskController.isPackageWhitelisted(
- UserHandle.getUserId(callingUid), aInfo.packageName)) {
- final String msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ") with lockTaskMode=true";
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
-
- // Check permission for remote animations
- final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
- if (adapter != null && mService.checkPermission(
- CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid)
- != PERMISSION_GRANTED) {
- final String msg = "Permission Denial: starting " + intent.toString()
- + " from " + callerApp + " (pid=" + callingPid
- + ", uid=" + callingUid + ") with remoteAnimationAdapter";
- Slog.w(TAG, msg);
- throw new SecurityException(msg);
- }
- }
return true;
}
@@ -2166,8 +2115,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
}
}
- void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options,
- String reason, boolean forceNonResizeable) {
+ void findTaskToMoveToFront(TaskRecord task, int flags, ActivityOptions options, String reason,
+ boolean forceNonResizeable) {
final ActivityStack currentStack = task.getStack();
if (currentStack == null) {
Slog.e(TAG, "findTaskToMoveToFront: can't move task="
@@ -4546,16 +4495,17 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
task.setTaskDockedResizing(true);
}
- int startActivityFromRecents(int taskId, Bundle bOptions) {
+ int startActivityFromRecents(int callingPid, int callingUid, int taskId,
+ SafeActivityOptions options) {
final TaskRecord task;
- final int callingUid;
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 ActivityOptions activityOptions = options != null
+ ? options.getOptions(this)
+ : null;
if (activityOptions != null) {
activityType = activityOptions.getLaunchActivityType();
windowingMode = activityOptions.getLaunchWindowingMode();
@@ -4603,7 +4553,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
sendPowerHintForLaunchStartIfNeeded(true /* forceSend */, targetActivity);
mActivityMetricsLogger.notifyActivityLaunching();
try {
- mService.moveTaskToFrontLocked(task.taskId, 0, bOptions,
+ mService.moveTaskToFrontLocked(task.taskId, 0, options,
true /* fromRecents */);
} finally {
mActivityMetricsLogger.notifyActivityLaunched(START_TASK_TO_FRONT,
@@ -4622,13 +4572,13 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
task.getStack());
return ActivityManager.START_TASK_TO_FRONT;
}
- callingUid = task.mCallingUid;
callingPackage = task.mCallingPackage;
intent = task.intent;
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY);
userId = task.userId;
- int result = mService.getActivityStartController().startActivityInPackage(callingUid,
- callingPackage, intent, null, null, null, 0, 0, bOptions, userId, task,
+ int result = mService.getActivityStartController().startActivityInPackage(
+ task.mCallingUid, callingPid, callingUid, callingPackage, intent, null, null,
+ null, 0, 0, options, userId, task,
"startActivityFromRecents");
if (windowingMode == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
setResizingDuringAnimation(task);
diff --git a/services/core/java/com/android/server/am/ActivityStartController.java b/services/core/java/com/android/server/am/ActivityStartController.java
index aed49e0037e1..f9932b20fb5b 100644
--- a/services/core/java/com/android/server/am/ActivityStartController.java
+++ b/services/core/java/com/android/server/am/ActivityStartController.java
@@ -220,43 +220,44 @@ public class ActivityStartController {
}
}
- final int startActivityInPackage(int uid, String callingPackage,
- Intent intent, String resolvedType, IBinder resultTo,
- String resultWho, int requestCode, int startFlags, Bundle bOptions, int userId,
- TaskRecord inTask, String reason) {
+ final int startActivityInPackage(int uid, int realCallingUid, int realCallingPid,
+ String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
+ String resultWho, int requestCode, int startFlags, SafeActivityOptions options,
+ int userId, TaskRecord inTask, String reason) {
- userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
- Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivityInPackage",
- null);
+ userId = mService.mUserController.handleIncomingUser(realCallingPid, realCallingUid, userId,
+ false, ALLOW_FULL_ONLY, "startActivityInPackage", null);
// TODO: Switch to user app stacks here.
return obtainStarter(intent, reason)
.setCallingUid(uid)
+ .setRealCallingPid(realCallingPid)
+ .setRealCallingUid(realCallingUid)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
.setResultTo(resultTo)
.setResultWho(resultWho)
.setRequestCode(requestCode)
.setStartFlags(startFlags)
- .setMayWait(bOptions, userId)
+ .setActivityOptions(options)
+ .setMayWait(userId)
.setInTask(inTask)
.execute();
}
final int startActivitiesInPackage(int uid, String callingPackage, Intent[] intents,
- String[] resolvedTypes, IBinder resultTo, Bundle bOptions, int userId) {
+ String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options, int userId) {
final String reason = "startActivityInPackage";
userId = mService.mUserController.handleIncomingUser(Binder.getCallingPid(),
Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, reason, null);
// TODO: Switch to user app stacks here.
- int ret = startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo,
- bOptions, userId, reason);
- return ret;
+ return startActivities(null, uid, callingPackage, intents, resolvedTypes, resultTo, options,
+ userId, reason);
}
int startActivities(IApplicationThread caller, int callingUid, String callingPackage,
- Intent[] intents, String[] resolvedTypes, IBinder resultTo, Bundle bOptions, int userId,
- String reason) {
+ Intent[] intents, String[] resolvedTypes, IBinder resultTo, SafeActivityOptions options,
+ int userId, String reason) {
if (intents == null) {
throw new NullPointerException("intents is null");
}
@@ -312,9 +313,9 @@ public class ActivityStartController {
"FLAG_CANT_SAVE_STATE not supported here");
}
- ActivityOptions options = ActivityOptions.fromBundle(
- i == intents.length - 1 ? bOptions : null);
-
+ final SafeActivityOptions checkedOptions = i == intents.length - 1
+ ? options
+ : null;
final int res = obtainStarter(intent, reason)
.setCaller(caller)
.setResolvedType(resolvedTypes[i])
@@ -326,7 +327,7 @@ public class ActivityStartController {
.setCallingPackage(callingPackage)
.setRealCallingPid(realCallingPid)
.setRealCallingUid(realCallingUid)
- .setActivityOptions(options)
+ .setActivityOptions(checkedOptions)
.setComponentSpecified(componentSpecified)
.setOutActivity(outActivity)
.execute();
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 3a13155d88e1..8595aa394800 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -74,6 +74,7 @@ import static com.android.server.am.TaskRecord.REPARENT_KEEP_STACK_AT_FRONT;
import static com.android.server.am.TaskRecord.REPARENT_MOVE_STACK_TO_FRONT;
import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityOptions;
import android.app.IApplicationThread;
@@ -298,7 +299,7 @@ class ActivityStarter {
int realCallingPid;
int realCallingUid;
int startFlags;
- ActivityOptions activityOptions;
+ SafeActivityOptions activityOptions;
boolean ignoreTargetSecurity;
boolean componentSpecified;
ActivityRecord[] outActivity;
@@ -306,13 +307,12 @@ class ActivityStarter {
String reason;
ProfilerInfo profilerInfo;
Configuration globalConfig;
- Bundle waitOptions;
int userId;
WaitResult waitResult;
/**
* Indicates that we should wait for the result of the start request. This flag is set when
- * {@link ActivityStarter#setMayWait(Bundle, int)} is called.
+ * {@link ActivityStarter#setMayWait(int)} is called.
* {@see ActivityStarter#startActivityMayWait}.
*/
boolean mayWait;
@@ -353,7 +353,6 @@ class ActivityStarter {
reason = null;
profilerInfo = null;
globalConfig = null;
- waitOptions = null;
userId = 0;
waitResult = null;
mayWait = false;
@@ -388,7 +387,6 @@ class ActivityStarter {
reason = request.reason;
profilerInfo = request.profilerInfo;
globalConfig = request.globalConfig;
- waitOptions = request.waitOptions;
userId = request.userId;
waitResult = request.waitResult;
mayWait = request.mayWait;
@@ -473,7 +471,7 @@ class ActivityStarter {
mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
- mRequest.waitOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
+ mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
mRequest.inTask, mRequest.reason);
} else {
return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
@@ -513,7 +511,7 @@ class ActivityStarter {
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
- ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
+ SafeActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
ActivityRecord[] outActivity, TaskRecord inTask, String reason) {
if (TextUtils.isEmpty(reason)) {
@@ -555,8 +553,9 @@ class ActivityStarter {
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
- ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
- ActivityRecord[] outActivity, TaskRecord inTask) {
+ SafeActivityOptions options,
+ boolean ignoreTargetSecurity, boolean componentSpecified, ActivityRecord[] outActivity,
+ TaskRecord inTask) {
int err = ActivityManager.START_SUCCESS;
// Pull the optional Ephemeral Installer-only bundle out of the options early.
final Bundle verificationBundle
@@ -603,7 +602,7 @@ class ActivityStarter {
// Transfer the result target from the source activity to the new
// one being started, including any failures.
if (requestCode >= 0) {
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
return ActivityManager.START_FORWARD_AND_REQUEST_CONFLICT;
}
resultRecord = sourceRecord.resultTo;
@@ -691,16 +690,20 @@ class ActivityStarter {
resultStack.sendActivityResultLocked(
-1, resultRecord, resultWho, requestCode, RESULT_CANCELED, null);
}
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
return err;
}
boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
- requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity, callerApp,
- resultRecord, resultStack, options);
+ requestCode, callingPid, callingUid, callingPackage, ignoreTargetSecurity,
+ callerApp, resultRecord, resultStack);
abort |= !mService.mIntentFirewall.checkStartActivity(intent, callingUid,
callingPid, resolvedType, aInfo.applicationInfo);
+ // Merge the two options bundles, while realCallerOptions takes precedence.
+ ActivityOptions checkedOptions = options != null
+ ? options.getOptions(intent, aInfo, callerApp, mSupervisor)
+ : null;
if (mService.mController != null) {
try {
// The Intent we give to the watcher has the extra data
@@ -715,7 +718,7 @@ class ActivityStarter {
mInterceptor.setStates(userId, realCallingPid, realCallingUid, startFlags, callingPackage);
if (mInterceptor.intercept(intent, rInfo, aInfo, resolvedType, inTask, callingPid,
- callingUid, options)) {
+ callingUid, checkedOptions)) {
// activity start was intercepted, e.g. because the target user is currently in quiet
// mode (turn off work) or the target application is suspended
intent = mInterceptor.mIntent;
@@ -725,7 +728,7 @@ class ActivityStarter {
inTask = mInterceptor.mInTask;
callingPid = mInterceptor.mCallingPid;
callingUid = mInterceptor.mCallingUid;
- options = mInterceptor.mActivityOptions;
+ checkedOptions = mInterceptor.mActivityOptions;
}
if (abort) {
@@ -735,7 +738,7 @@ class ActivityStarter {
}
// We pretend to the caller that it was really started, but
// they will just get a cancel result.
- ActivityOptions.abort(options);
+ ActivityOptions.abort(checkedOptions);
return START_ABORTED;
}
@@ -796,7 +799,7 @@ class ActivityStarter {
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
- mSupervisor, options, sourceRecord);
+ mSupervisor, checkedOptions, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
@@ -808,13 +811,16 @@ class ActivityStarter {
}
final ActivityStack stack = mSupervisor.mFocusedStack;
+
+ // If we are starting an activity that is not from the same uid as the currently resumed
+ // one, check whether app switches are allowed.
if (voiceSession == null && (stack.mResumedActivity == null
- || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
+ || stack.mResumedActivity.info.applicationInfo.uid != realCallingUid)) {
if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid,
realCallingPid, realCallingUid, "Activity start")) {
mController.addPendingActivityLaunch(new PendingActivityLaunch(r,
sourceRecord, startFlags, stack, callerApp));
- ActivityOptions.abort(options);
+ ActivityOptions.abort(checkedOptions);
return ActivityManager.START_SWITCHES_CANCELED;
}
}
@@ -833,9 +839,10 @@ class ActivityStarter {
mController.doPendingActivityLaunches(false);
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags,
- true /* doResume */, options, inTask, outActivity);
+ true /* doResume */, checkedOptions, inTask, outActivity);
}
+
/**
* Creates a launch intent for the given auxiliary resolution data.
*/
@@ -900,8 +907,8 @@ class ActivityStarter {
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
IBinder resultTo, String resultWho, int requestCode, int startFlags,
ProfilerInfo profilerInfo, WaitResult outResult,
- Configuration globalConfig, Bundle bOptions, boolean ignoreTargetSecurity, int userId,
- TaskRecord inTask, String reason) {
+ Configuration globalConfig, SafeActivityOptions options, boolean ignoreTargetSecurity,
+ int userId, TaskRecord inTask, String reason) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {
throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -953,7 +960,6 @@ class ActivityStarter {
// Collect information about the target of the Intent.
ActivityInfo aInfo = mSupervisor.resolveActivity(intent, rInfo, startFlags, profilerInfo);
- ActivityOptions options = ActivityOptions.fromBundle(bOptions);
synchronized (mService) {
final int realCallingPid = Binder.getCallingPid();
final int realCallingUid = Binder.getCallingUid();
@@ -993,7 +999,7 @@ class ActivityStarter {
Slog.w(TAG, "Unable to find app for caller " + caller
+ " (pid=" + callingPid + ") when starting: "
+ intent.toString());
- ActivityOptions.abort(options);
+ SafeActivityOptions.abort(options);
return ActivityManager.START_PERMISSION_DENIED;
}
}
@@ -1039,12 +1045,10 @@ class ActivityStarter {
}
final ActivityRecord[] outRecord = new ActivityRecord[1];
- int res = startActivity(caller, intent, ephemeralIntent, resolvedType,
- aInfo, rInfo, voiceSession, voiceInteractor,
- resultTo, resultWho, requestCode, callingPid,
- callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
- options, ignoreTargetSecurity, componentSpecified, outRecord, inTask,
- reason);
+ int res = startActivity(caller, intent, ephemeralIntent, resolvedType, aInfo, rInfo,
+ voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid,
+ callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options,
+ ignoreTargetSecurity, componentSpecified, outRecord, inTask, reason);
Binder.restoreCallingIdentity(origId);
@@ -1248,7 +1252,7 @@ class ActivityStarter {
outActivity[0] = reusedActivity;
}
- return START_TASK_TO_FRONT;
+ return START_DELIVERED_TO_TOP;
}
}
@@ -2447,11 +2451,15 @@ class ActivityStarter {
return this;
}
- ActivityStarter setActivityOptions(ActivityOptions options) {
+ ActivityStarter setActivityOptions(SafeActivityOptions options) {
mRequest.activityOptions = options;
return this;
}
+ ActivityStarter setActivityOptions(Bundle bOptions) {
+ return setActivityOptions(SafeActivityOptions.fromBundle(bOptions));
+ }
+
ActivityStarter setIgnoreTargetSecurity(boolean ignoreTargetSecurity) {
mRequest.ignoreTargetSecurity = ignoreTargetSecurity;
return this;
@@ -2487,19 +2495,13 @@ class ActivityStarter {
return this;
}
- ActivityStarter setWaitOptions(Bundle options) {
- mRequest.waitOptions = options;
- return this;
- }
-
ActivityStarter setUserId(int userId) {
mRequest.userId = userId;
return this;
}
- ActivityStarter setMayWait(Bundle options, int userId) {
+ ActivityStarter setMayWait(int userId) {
mRequest.mayWait = true;
- mRequest.waitOptions = options;
mRequest.userId = userId;
return this;
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 26d65bc7414c..0da7e0ec2f6d 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -408,9 +408,11 @@ class AppErrors {
final Set<String> cats = task.intent.getCategories();
if (cats != null && cats.contains(Intent.CATEGORY_LAUNCHER)) {
mService.getActivityStartController().startActivityInPackage(
- task.mCallingUid, task.mCallingPackage, task.intent, null, null,
- null, 0, 0, ActivityOptions.makeBasic().toBundle(), task.userId,
- null, "AppErrors");
+ task.mCallingUid, callingPid, callingUid, task.mCallingPackage,
+ task.intent, null, null, null, 0, 0,
+ new SafeActivityOptions(ActivityOptions.makeBasic()),
+ task.userId, null,
+ "AppErrors");
}
}
}
diff --git a/services/core/java/com/android/server/am/AppTaskImpl.java b/services/core/java/com/android/server/am/AppTaskImpl.java
index f821f6bdb925..5f5a504bb014 100644
--- a/services/core/java/com/android/server/am/AppTaskImpl.java
+++ b/services/core/java/com/android/server/am/AppTaskImpl.java
@@ -20,6 +20,7 @@ import static com.android.server.am.ActivityStackSupervisor.MATCH_TASK_IN_STACKS
import static com.android.server.am.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.app.IAppTask;
import android.app.IApplicationThread;
import android.content.Intent;
@@ -93,10 +94,13 @@ class AppTaskImpl extends IAppTask.Stub {
public void moveToFront() {
checkCaller();
// Will bring task to front if it already has a root activity.
+ final int callingPid = Binder.getCallingPid();
+ final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
try {
synchronized (this) {
- mService.mStackSupervisor.startActivityFromRecents(mTaskId, null);
+ mService.mStackSupervisor.startActivityFromRecents(callingPid, callingUid, mTaskId,
+ null);
}
} finally {
Binder.restoreCallingIdentity(origId);
@@ -127,7 +131,8 @@ class AppTaskImpl extends IAppTask.Stub {
.setCaller(appThread)
.setCallingPackage(callingPackage)
.setResolvedType(resolvedType)
- .setMayWait(bOptions, callingUser)
+ .setActivityOptions(bOptions)
+ .setMayWait(callingUser)
.setInTask(tr)
.execute();
}
diff --git a/services/core/java/com/android/server/am/PendingIntentRecord.java b/services/core/java/com/android/server/am/PendingIntentRecord.java
index c26e7703a1ca..8e9d85d60479 100644
--- a/services/core/java/com/android/server/am/PendingIntentRecord.java
+++ b/services/core/java/com/android/server/am/PendingIntentRecord.java
@@ -16,10 +16,12 @@
package com.android.server.am;
+import static android.app.ActivityManager.START_SUCCESS;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
import android.app.ActivityManager;
+import android.app.ActivityOptions;
import android.content.IIntentSender;
import android.content.IIntentReceiver;
import android.app.PendingIntent;
@@ -65,7 +67,7 @@ final class PendingIntentRecord extends IIntentSender.Stub {
final int requestCode;
final Intent requestIntent;
final String requestResolvedType;
- final Bundle options;
+ final SafeActivityOptions options;
Intent[] allIntents;
String[] allResolvedTypes;
final int flags;
@@ -75,7 +77,7 @@ final class PendingIntentRecord extends IIntentSender.Stub {
private static final int ODD_PRIME_NUMBER = 37;
Key(int _t, String _p, ActivityRecord _a, String _w,
- int _r, Intent[] _i, String[] _it, int _f, Bundle _o, int _userId) {
+ int _r, Intent[] _i, String[] _it, int _f, SafeActivityOptions _o, int _userId) {
type = _t;
packageName = _p;
activity = _a;
@@ -310,17 +312,16 @@ final class PendingIntentRecord extends IIntentSender.Stub {
if (userId == UserHandle.USER_CURRENT) {
userId = owner.mUserController.getCurrentOrTargetUserId();
}
- int res = 0;
+ int res = START_SUCCESS;
switch (key.type) {
case ActivityManager.INTENT_SENDER_ACTIVITY:
- if (options == null) {
- options = key.options;
- } else if (key.options != null) {
- Bundle opts = new Bundle(key.options);
- opts.putAll(options);
- options = opts;
- }
try {
+ SafeActivityOptions mergedOptions = key.options;
+ if (mergedOptions == null) {
+ mergedOptions = SafeActivityOptions.fromBundle(options);
+ } else {
+ mergedOptions.setCallerOptions(ActivityOptions.fromBundle(options));
+ }
if (key.allIntents != null && key.allIntents.length > 1) {
Intent[] allIntents = new Intent[key.allIntents.length];
String[] allResolvedTypes = new String[key.allIntents.length];
@@ -332,14 +333,14 @@ final class PendingIntentRecord extends IIntentSender.Stub {
}
allIntents[allIntents.length-1] = finalIntent;
allResolvedTypes[allResolvedTypes.length-1] = resolvedType;
- owner.getActivityStartController().startActivitiesInPackage(uid,
- key.packageName, allIntents, allResolvedTypes, resultTo,
- options, userId);
+ res = owner.getActivityStartController().startActivitiesInPackage(
+ uid, key.packageName, allIntents, allResolvedTypes,
+ resultTo, mergedOptions, userId);
} else {
- owner.getActivityStartController().startActivityInPackage(uid,
- key.packageName, finalIntent, resolvedType, resultTo,
- resultWho, requestCode, 0, options, userId, null,
- "PendingIntentRecord");
+ res = owner.getActivityStartController().startActivityInPackage(uid,
+ callingPid, callingUid, key.packageName, finalIntent,
+ resolvedType, resultTo, resultWho, requestCode, 0,
+ mergedOptions, userId, null, "PendingIntentRecord");
}
} catch (RuntimeException e) {
Slog.w(TAG, "Unable to send startActivity intent", e);
diff --git a/services/core/java/com/android/server/am/SafeActivityOptions.java b/services/core/java/com/android/server/am/SafeActivityOptions.java
new file mode 100644
index 000000000000..d08111ec0aa5
--- /dev/null
+++ b/services/core/java/com/android/server/am/SafeActivityOptions.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2018 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.am;
+
+import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
+import static android.Manifest.permission.START_TASKS_FROM_RECENTS;
+import static android.content.pm.PackageManager.PERMISSION_DENIED;
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static android.view.Display.INVALID_DISPLAY;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.am.TaskRecord.INVALID_TASK_ID;
+
+import android.annotation.Nullable;
+import android.app.ActivityOptions;
+import android.app.PendingIntent;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.util.Slog;
+import android.view.RemoteAnimationAdapter;
+
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Wraps {@link ActivityOptions}, records binder identity, and checks permission when retrieving
+ * the inner options. Also supports having two set of options: Once from the original caller, and
+ * once from the caller that is overriding it, which happens when sending a {@link PendingIntent}.
+ */
+class SafeActivityOptions {
+
+ private static final String TAG = TAG_WITH_CLASS_NAME ? "SafeActivityOptions" : TAG_AM;
+
+ private final int mOriginalCallingPid;
+ private final int mOriginalCallingUid;
+ private int mRealCallingPid;
+ private int mRealCallingUid;
+ private final @Nullable ActivityOptions mOriginalOptions;
+ private @Nullable ActivityOptions mCallerOptions;
+
+ /**
+ * Constructs a new instance from a bundle and records {@link Binder#getCallingPid}/
+ * {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when constructing
+ * this object.
+ *
+ * @param bOptions The {@link ActivityOptions} as {@link Bundle}.
+ */
+ static SafeActivityOptions fromBundle(Bundle bOptions) {
+ return bOptions != null
+ ? new SafeActivityOptions(ActivityOptions.fromBundle(bOptions))
+ : null;
+ }
+
+ /**
+ * Constructs a new instance and records {@link Binder#getCallingPid}/
+ * {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when constructing
+ * this object.
+ *
+ * @param options The options to wrap.
+ */
+ SafeActivityOptions(@Nullable ActivityOptions options) {
+ mOriginalCallingPid = Binder.getCallingPid();
+ mOriginalCallingUid = Binder.getCallingUid();
+ mOriginalOptions = options;
+ }
+
+ /**
+ * Overrides options with options from a caller and records {@link Binder#getCallingPid}/
+ * {@link Binder#getCallingUid}. Thus, calling identity MUST NOT be cleared when calling this
+ * method.
+ */
+ void setCallerOptions(@Nullable ActivityOptions options) {
+ mRealCallingPid = Binder.getCallingPid();
+ mRealCallingUid = Binder.getCallingUid();
+ mCallerOptions = options;
+ }
+
+ /**
+ * Performs permission check and retrieves the options.
+ *
+ * @param r The record of the being started activity.
+ */
+ ActivityOptions getOptions(ActivityRecord r) throws SecurityException {
+ return getOptions(r.intent, r.info, r.app, r.mStackSupervisor);
+ }
+
+ /**
+ * Performs permission check and retrieves the options when options are not being used to launch
+ * a specific activity (i.e. a task is moved to front).
+ */
+ ActivityOptions getOptions(ActivityStackSupervisor supervisor) throws SecurityException {
+ return getOptions(null, null, null, supervisor);
+ }
+
+ /**
+ * Performs permission check and retrieves the options.
+ *
+ * @param intent The intent that is being launched.
+ * @param aInfo The info of the activity being launched.
+ * @param callerApp The record of the caller.
+ */
+ ActivityOptions getOptions(@Nullable Intent intent, @Nullable ActivityInfo aInfo,
+ @Nullable ProcessRecord callerApp,
+ ActivityStackSupervisor supervisor) throws SecurityException {
+ if (mOriginalOptions != null) {
+ checkPermissions(intent, aInfo, callerApp, supervisor, mOriginalOptions,
+ mOriginalCallingPid, mOriginalCallingUid);
+ }
+ if (mCallerOptions != null) {
+ checkPermissions(intent, aInfo, callerApp, supervisor, mCallerOptions,
+ mRealCallingPid, mRealCallingUid);
+ }
+ return mergeActivityOptions(mOriginalOptions, mCallerOptions);
+ }
+
+ /**
+ * @see ActivityOptions#popAppVerificationBundle
+ */
+ Bundle popAppVerificationBundle() {
+ return mOriginalOptions != null ? mOriginalOptions.popAppVerificationBundle() : null;
+ }
+
+ private void abort() {
+ if (mOriginalOptions != null) {
+ ActivityOptions.abort(mOriginalOptions);
+ }
+ if (mCallerOptions != null) {
+ ActivityOptions.abort(mCallerOptions);
+ }
+ }
+
+ static void abort(@Nullable SafeActivityOptions options) {
+ if (options != null) {
+ options.abort();
+ }
+ }
+
+ /**
+ * Merges two activity options into one, with {@code options2} taking precedence in case of a
+ * conflict.
+ */
+ @VisibleForTesting
+ @Nullable ActivityOptions mergeActivityOptions(@Nullable ActivityOptions options1,
+ @Nullable ActivityOptions options2) {
+ if (options1 == null) {
+ return options2;
+ }
+ if (options2 == null) {
+ return options1;
+ }
+ final Bundle b1 = options1.toBundle();
+ final Bundle b2 = options2.toBundle();
+ b1.putAll(b2);
+ return ActivityOptions.fromBundle(b1);
+ }
+
+ private void checkPermissions(@Nullable Intent intent, @Nullable ActivityInfo aInfo,
+ @Nullable ProcessRecord callerApp, ActivityStackSupervisor supervisor,
+ ActivityOptions options, int callingPid, int callingUid) {
+ // If a launch task id is specified, then ensure that the caller is the recents
+ // component or has the START_TASKS_FROM_RECENTS permission
+ if (options.getLaunchTaskId() != INVALID_TASK_ID
+ && !supervisor.mRecentTasks.isCallerRecents(callingUid)) {
+ final int startInTaskPerm = supervisor.mService.checkPermission(
+ START_TASKS_FROM_RECENTS, callingPid, callingUid);
+ if (startInTaskPerm == PERMISSION_DENIED) {
+ final String msg = "Permission Denial: starting " + getIntentString(intent)
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ") with launchTaskId="
+ + options.getLaunchTaskId();
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ }
+ // Check if someone tries to launch an activity on a private display with a different
+ // owner.
+ final int launchDisplayId = options.getLaunchDisplayId();
+ if (aInfo != null && launchDisplayId != INVALID_DISPLAY
+ && !supervisor.isCallerAllowedToLaunchOnDisplay(callingPid, callingUid,
+ launchDisplayId, aInfo)) {
+ final String msg = "Permission Denial: starting " + getIntentString(intent)
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ") with launchDisplayId="
+ + launchDisplayId;
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ // Check if someone tries to launch an unwhitelisted activity into LockTask mode.
+ final boolean lockTaskMode = options.getLockTaskMode();
+ if (aInfo != null && lockTaskMode
+ && !supervisor.mService.mLockTaskController.isPackageWhitelisted(
+ UserHandle.getUserId(callingUid), aInfo.packageName)) {
+ final String msg = "Permission Denial: starting " + getIntentString(intent)
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ") with lockTaskMode=true";
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+
+ // Check permission for remote animations
+ final RemoteAnimationAdapter adapter = options.getRemoteAnimationAdapter();
+ if (adapter != null && supervisor.mService.checkPermission(
+ CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid)
+ != PERMISSION_GRANTED) {
+ final String msg = "Permission Denial: starting " + getIntentString(intent)
+ + " from " + callerApp + " (pid=" + callingPid
+ + ", uid=" + callingUid + ") with remoteAnimationAdapter";
+ Slog.w(TAG, msg);
+ throw new SecurityException(msg);
+ }
+ }
+
+ private String getIntentString(Intent intent) {
+ return intent != null ? intent.toString() : "(no intent)";
+ }
+}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b97de6511aed..c77ec20afa3b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -1849,7 +1849,6 @@ public final class DisplayManagerService extends SystemService {
if (packageName != null && !validatePackageName(getCallingUid(), packageName)) {
packageName = null;
}
- Preconditions.checkNotNull(c);
final long token = Binder.clearCallingIdentity();
try {
setBrightnessConfigurationForUserInternal(c, userId, packageName);
diff --git a/services/core/java/com/android/server/display/PersistentDataStore.java b/services/core/java/com/android/server/display/PersistentDataStore.java
index f1ce5c5f0007..cbf46f832186 100644
--- a/services/core/java/com/android/server/display/PersistentDataStore.java
+++ b/services/core/java/com/android/server/display/PersistentDataStore.java
@@ -598,14 +598,20 @@ final class PersistentDataStore {
private boolean setBrightnessConfigurationForUser(BrightnessConfiguration c,
int userSerial, String packageName) {
BrightnessConfiguration currentConfig = mConfigurations.get(userSerial);
- if (currentConfig == null || !currentConfig.equals(c)) {
- if (packageName == null) {
- mPackageNames.remove(userSerial);
+ if (currentConfig != c && (currentConfig == null || !currentConfig.equals(c))) {
+ if (c != null) {
+ if (packageName == null) {
+ mPackageNames.remove(userSerial);
+ } else {
+ mPackageNames.put(userSerial, packageName);
+ }
+ mTimeStamps.put(userSerial, System.currentTimeMillis());
+ mConfigurations.put(userSerial, c);
} else {
- mPackageNames.put(userSerial, packageName);
+ mPackageNames.remove(userSerial);
+ mTimeStamps.delete(userSerial);
+ mConfigurations.remove(userSerial);
}
- mTimeStamps.put(userSerial, System.currentTimeMillis());
- mConfigurations.put(userSerial, c);
return true;
}
return false;
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 0f5cb0a38c83..611f4ec7b865 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -1054,6 +1054,14 @@ public final class JobStatus {
if ((constraints&CONSTRAINT_DEVICE_NOT_DOZING) != 0) {
pw.print(" DEVICE_NOT_DOZING");
}
+ if ((constraints&CONSTRAINT_BACKGROUND_NOT_RESTRICTED) != 0) {
+ pw.print(" BACKGROUND_NOT_RESTRICTED");
+ }
+ if (constraints != 0) {
+ pw.print(" [0x");
+ pw.print(Integer.toHexString(constraints));
+ pw.print("]");
+ }
}
/** Writes constraints to the given repeating proto field. */
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 07ea51be4ba0..a6753ab09103 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -53,6 +53,7 @@ import android.content.pm.UserInfo;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.sqlite.SQLiteDatabase;
+import android.hardware.authsecret.V1_0.IAuthSecret;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -77,10 +78,10 @@ import android.security.KeyStore;
import android.security.keystore.AndroidKeyStoreProvider;
import android.security.keystore.KeyProperties;
import android.security.keystore.KeyProtection;
-import android.security.keystore.KeychainProtectionParams;
import android.security.keystore.UserNotAuthenticatedException;
-import android.security.keystore.WrappedApplicationKey;
-import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.recovery.KeychainProtectionParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
+import android.security.keystore.recovery.KeychainSnapshot;
import android.service.gatekeeper.GateKeeperResponse;
import android.service.gatekeeper.IGateKeeperService;
import android.text.TextUtils;
@@ -126,8 +127,10 @@ import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
+import java.util.NoSuchElementException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -183,6 +186,7 @@ public class LockSettingsService extends ILockSettings.Stub {
private boolean mFirstCallToVold;
protected IGateKeeperService mGateKeeperService;
+ protected IAuthSecret mAuthSecretService;
/**
* The UIDs that are used for system credential storage in keystore.
@@ -613,6 +617,14 @@ public class LockSettingsService extends ILockSettings.Stub {
} catch (RemoteException e) {
Slog.e(TAG, "Failure retrieving IGateKeeperService", e);
}
+ // Find the AuthSecret HAL
+ try {
+ mAuthSecretService = IAuthSecret.getService();
+ } catch (NoSuchElementException e) {
+ Slog.i(TAG, "Device doesn't implement AuthSecret HAL");
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to get AuthSecret HAL", e);
+ }
mDeviceProvisionedObserver.onSystemReady();
// TODO: maybe skip this for split system user mode.
mStorage.prefetchUser(UserHandle.USER_SYSTEM);
@@ -2127,6 +2139,20 @@ public class LockSettingsService extends ILockSettings.Stub {
private SparseArray<AuthenticationToken> mSpCache = new SparseArray();
private void onAuthTokenKnownForUser(@UserIdInt int userId, AuthenticationToken auth) {
+ // Pass the primary user's auth secret to the HAL
+ if (mAuthSecretService != null && mUserManager.getUserInfo(userId).isPrimary()) {
+ try {
+ final byte[] rawSecret = auth.deriveVendorAuthSecret();
+ final ArrayList<Byte> secret = new ArrayList<>(rawSecret.length);
+ for (int i = 0; i < rawSecret.length; ++i) {
+ secret.add(rawSecret[i]);
+ }
+ mAuthSecretService.primaryUserCredential(secret);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Failed to pass primary user secret to AuthSecret HAL", e);
+ }
+ }
+
// Update the SP cache, removing the entry when allowed
synchronized (mSpManager) {
if (shouldCacheSpForUser(userId)) {
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 7a3a746e1868..88b2a3685088 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -121,6 +121,7 @@ public class SyntheticPasswordManager {
private static final byte[] PERSONALIZATION_USER_GK_AUTH = "user-gk-authentication".getBytes();
private static final byte[] PERSONALIZATION_SP_GK_AUTH = "sp-gk-authentication".getBytes();
private static final byte[] PERSONALIZATION_FBE_KEY = "fbe-key".getBytes();
+ private static final byte[] PERSONALIZATION_AUTHSECRET_KEY = "authsecret-hal".getBytes();
private static final byte[] PERSONALIZATION_SP_SPLIT = "sp-split".getBytes();
private static final byte[] PERSONALIZATION_E0 = "e0-encryption".getBytes();
private static final byte[] PERSONALISATION_WEAVER_PASSWORD = "weaver-pwd".getBytes();
@@ -159,6 +160,11 @@ public class SyntheticPasswordManager {
syntheticPassword.getBytes());
}
+ public byte[] deriveVendorAuthSecret() {
+ return SyntheticPasswordCrypto.personalisedHash(PERSONALIZATION_AUTHSECRET_KEY,
+ syntheticPassword.getBytes());
+ }
+
private void initialize(byte[] P0, byte[] P1) {
this.P1 = P1;
this.syntheticPassword = String.valueOf(HexEncoding.encode(
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
index 452c9eea79e8..6fcbcbcbfad9 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/KeySyncTask.java
@@ -16,14 +16,14 @@
package com.android.server.locksettings.recoverablekeystore;
-import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
+import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_LOCKSCREEN;
import android.annotation.Nullable;
import android.content.Context;
-import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.KeychainProtectionParams;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.KeychainProtectionParams;
+import android.security.keystore.recovery.KeychainSnapshot;
+import android.security.keystore.recovery.WrappedApplicationKey;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
index 76508d5817e2..ac3cef2fa7ef 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManager.java
@@ -33,10 +33,10 @@ import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
-import android.security.keystore.KeychainProtectionParams;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.RecoveryController;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeychainProtectionParams;
+import android.security.keystore.recovery.KeychainSnapshot;
+import android.security.keystore.recovery.RecoveryController;
+import android.security.keystore.recovery.WrappedApplicationKey;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
diff --git a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
index 62bb41ec48aa..7cde7ab0589c 100644
--- a/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
+++ b/services/core/java/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorage.java
@@ -17,7 +17,7 @@
package com.android.server.locksettings.recoverablekeystore.storage;
import android.annotation.Nullable;
-import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.recovery.KeychainSnapshot;
import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy;
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 2bd9cab313a7..b4bc7f507701 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -37,6 +37,7 @@ import com.android.server.am.ProcessList;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
+import java.util.Set;
public class NetworkPolicyLogger {
static final String TAG = "NetworkPolicy";
@@ -62,6 +63,7 @@ public class NetworkPolicyLogger {
private static final int EVENT_TEMP_POWER_SAVE_WL_CHANGED = 10;
private static final int EVENT_UID_FIREWALL_RULE_CHANGED = 11;
private static final int EVENT_FIREWALL_CHAIN_ENABLED = 12;
+ private static final int EVENT_UPDATE_METERED_RESTRICTED_PKGS = 13;
static final int NTWK_BLOCKED_POWER = 0;
static final int NTWK_ALLOWED_NON_METERED = 1;
@@ -179,6 +181,14 @@ public class NetworkPolicyLogger {
}
}
+ void meteredRestrictedPkgsChanged(Set<Integer> restrictedUids) {
+ synchronized (mLock) {
+ final String log = "Metered restricted uids: " + restrictedUids;
+ if (LOGD) Slog.d(TAG, log);
+ mEventsBuffer.event(log);
+ }
+ }
+
void dumpLogs(IndentingPrintWriter pw) {
synchronized (mLock) {
pw.println();
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 971ac8b922ef..649096442da8 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -19,6 +19,8 @@ package com.android.server.net;
import android.net.Network;
import android.telephony.SubscriptionPlan;
+import java.util.Set;
+
/**
* Network Policy Manager local system service interface.
*
@@ -71,4 +73,21 @@ public abstract class NetworkPolicyManagerInternal {
* Informs that admin data is loaded and available.
*/
public abstract void onAdminDataAvailable();
+
+ /**
+ * Sets a list of packages which are restricted by admin from accessing metered data.
+ *
+ * @param packageNames the list of restricted packages.
+ * @param userId the userId in which {@param packagesNames} are restricted.
+ */
+ public abstract void setMeteredRestrictedPackages(
+ Set<String> packageNames, int userId);
+
+
+ /**
+ * Similar to {@link #setMeteredRestrictedPackages(Set, int)} but updates the restricted
+ * packages list asynchronously.
+ */
+ public abstract void setMeteredRestrictedPackagesAsync(
+ Set<String> packageNames, int userId);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index e406d51ac823..0e54768bfa87 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -232,6 +232,7 @@ import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -349,6 +350,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
private static final int MSG_POLICIES_CHANGED = 13;
private static final int MSG_RESET_FIREWALL_RULES_BY_UID = 15;
private static final int MSG_SUBSCRIPTION_OVERRIDE = 16;
+ private static final int MSG_METERED_RESTRICTED_PACKAGES_CHANGED = 17;
private static final int UID_MSG_STATE_CHANGED = 100;
private static final int UID_MSG_GONE = 101;
@@ -480,6 +482,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
@GuardedBy("mNetworkPoliciesSecondLock")
private final SparseIntArray mNetIdToSubId = new SparseIntArray();
+ /**
+ * Indicates the uids restricted by admin from accessing metered data. It's a mapping from
+ * userId to restricted uids which belong to that user.
+ */
+ @GuardedBy("mUidRulesFirstLock")
+ private final SparseArray<Set<Integer>> mMeteredRestrictedUids = new SparseArray<>();
+
private final RemoteCallbackList<INetworkPolicyListener>
mListeners = new RemoteCallbackList<>();
@@ -898,6 +907,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// Remove any persistable state for the given user; both cleaning up after a
// USER_REMOVED, and one last sanity check during USER_ADDED
removeUserStateUL(userId, true);
+ // Removing outside removeUserStateUL since that can also be called when
+ // user resets app preferences.
+ mMeteredRestrictedUids.remove(userId);
if (action == ACTION_USER_ADDED) {
// Add apps that are whitelisted by default.
addDefaultRestrictBackgroundWhitelistUidsUL(userId);
@@ -3137,6 +3149,15 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
fout.decreaseIndent();
+ fout.println("Admin restricted uids for metered data:");
+ fout.increaseIndent();
+ size = mMeteredRestrictedUids.size();
+ for (int i = 0; i < size; ++i) {
+ fout.print("u" + mMeteredRestrictedUids.keyAt(i) + ": ");
+ fout.println(mMeteredRestrictedUids.valueAt(i));
+ }
+ fout.decreaseIndent();
+
mLogger.dumpLogs(fout);
}
}
@@ -3705,6 +3726,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
final int oldUidRules = mUidRules.get(uid, RULE_NONE);
final boolean isForeground = isUidForegroundOnRestrictBackgroundUL(uid);
+ final boolean isRestrictedByAdmin = isRestrictedByAdminUL(uid);
final boolean isBlacklisted = (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0;
final boolean isWhitelisted = (uidPolicy & POLICY_ALLOW_METERED_BACKGROUND) != 0;
@@ -3712,7 +3734,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
int newRule = RULE_NONE;
// First step: define the new rule based on user restrictions and foreground state.
- if (isForeground) {
+ if (isRestrictedByAdmin) {
+ newRule = RULE_REJECT_METERED;
+ } else if (isForeground) {
if (isBlacklisted || (mRestrictBackground && !isWhitelisted)) {
newRule = RULE_TEMPORARY_ALLOW_METERED;
} else if (isWhitelisted) {
@@ -3732,6 +3756,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
+ ": isForeground=" +isForeground
+ ", isBlacklisted=" + isBlacklisted
+ ", isWhitelisted=" + isWhitelisted
+ + ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ ", oldRule=" + uidRulesToString(oldRule)
+ ", newRule=" + uidRulesToString(newRule)
+ ", newUidRules=" + uidRulesToString(newUidRules)
@@ -3767,13 +3792,13 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (!isWhitelisted) {
setMeteredNetworkWhitelist(uid, false);
}
- if (isBlacklisted) {
+ if (isBlacklisted || isRestrictedByAdmin) {
setMeteredNetworkBlacklist(uid, true);
}
} else if (hasRule(newRule, RULE_REJECT_METERED)
|| hasRule(oldRule, RULE_REJECT_METERED)) {
// Flip state because app was explicitly added or removed to blacklist.
- setMeteredNetworkBlacklist(uid, isBlacklisted);
+ setMeteredNetworkBlacklist(uid, (isBlacklisted || isRestrictedByAdmin));
if (hasRule(oldRule, RULE_REJECT_METERED) && isWhitelisted) {
// Since blacklist prevails over whitelist, we need to handle the special case
// where app is whitelisted and blacklisted at the same time (although such
@@ -3790,6 +3815,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
+ ": foreground=" + isForeground
+ ", whitelisted=" + isWhitelisted
+ ", blacklisted=" + isBlacklisted
+ + ", isRestrictedByAdmin=" + isRestrictedByAdmin
+ ", newRule=" + uidRulesToString(newUidRules)
+ ", oldRule=" + uidRulesToString(oldUidRules));
}
@@ -4102,6 +4128,12 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mListeners.finishBroadcast();
return true;
}
+ case MSG_METERED_RESTRICTED_PACKAGES_CHANGED: {
+ final int userId = msg.arg1;
+ final Set<String> packageNames = (Set<String>) msg.obj;
+ setMeteredRestrictedPackagesInternal(packageNames, userId);
+ return true;
+ }
default: {
return false;
}
@@ -4605,6 +4637,42 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
public void onAdminDataAvailable() {
mAdminDataAvailableLatch.countDown();
}
+
+ @Override
+ public void setMeteredRestrictedPackages(Set<String> packageNames, int userId) {
+ setMeteredRestrictedPackagesInternal(packageNames, userId);
+ }
+
+ @Override
+ public void setMeteredRestrictedPackagesAsync(Set<String> packageNames, int userId) {
+ mHandler.obtainMessage(MSG_METERED_RESTRICTED_PACKAGES_CHANGED,
+ userId, 0, packageNames).sendToTarget();
+ }
+ }
+
+ private void setMeteredRestrictedPackagesInternal(Set<String> packageNames, int userId) {
+ synchronized (mUidRulesFirstLock) {
+ final Set<Integer> newRestrictedUids = new ArraySet<>();
+ for (String packageName : packageNames) {
+ final int uid = getUidForPackage(packageName, userId);
+ if (uid >= 0) {
+ newRestrictedUids.add(uid);
+ }
+ }
+ final Set<Integer> oldRestrictedUids = mMeteredRestrictedUids.get(userId);
+ mMeteredRestrictedUids.put(userId, newRestrictedUids);
+ handleRestrictedPackagesChangeUL(oldRestrictedUids, newRestrictedUids);
+ mLogger.meteredRestrictedPkgsChanged(newRestrictedUids);
+ }
+ }
+
+ private int getUidForPackage(String packageName, int userId) {
+ try {
+ return mContext.getPackageManager().getPackageUidAsUser(packageName,
+ PackageManager.MATCH_KNOWN_PACKAGES, userId);
+ } catch (NameNotFoundException e) {
+ return -1;
+ }
}
private int parseSubId(NetworkState state) {
@@ -4642,6 +4710,32 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ private void handleRestrictedPackagesChangeUL(Set<Integer> oldRestrictedUids,
+ Set<Integer> newRestrictedUids) {
+ if (oldRestrictedUids == null) {
+ for (int uid : newRestrictedUids) {
+ updateRulesForDataUsageRestrictionsUL(uid);
+ }
+ return;
+ }
+ for (int uid : oldRestrictedUids) {
+ if (!newRestrictedUids.contains(uid)) {
+ updateRulesForDataUsageRestrictionsUL(uid);
+ }
+ }
+ for (int uid : newRestrictedUids) {
+ if (!oldRestrictedUids.contains(uid)) {
+ updateRulesForDataUsageRestrictionsUL(uid);
+ }
+ }
+ }
+
+ private boolean isRestrictedByAdminUL(int uid) {
+ final Set<Integer> restrictedUids = mMeteredRestrictedUids.get(
+ UserHandle.getUserId(uid));
+ return restrictedUids != null && restrictedUids.contains(uid);
+ }
+
private static boolean hasRule(int uidRules, int rule) {
return (uidRules & rule) != 0;
}
diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
index 253d4f5b22bb..321af43d9c3d 100644
--- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
+++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java
@@ -169,8 +169,9 @@ final class OverlayManagerServiceImpl {
}
final PackageInfo targetPackage = mPackageManager.getPackageInfo(packageName, userId);
- updateAllOverlaysForTarget(packageName, userId, targetPackage);
- mListener.onOverlaysChanged(packageName, userId);
+ if (updateAllOverlaysForTarget(packageName, userId, targetPackage)) {
+ mListener.onOverlaysChanged(packageName, userId);
+ }
}
void onTargetPackageChanged(@NonNull final String packageName, final int userId) {
@@ -210,7 +211,9 @@ final class OverlayManagerServiceImpl {
Slog.d(TAG, "onTargetPackageRemoved packageName=" + packageName + " userId=" + userId);
}
- updateAllOverlaysForTarget(packageName, userId, null);
+ if (updateAllOverlaysForTarget(packageName, userId, null)) {
+ mListener.onOverlaysChanged(packageName, userId);
+ }
}
/**
diff --git a/services/core/java/com/android/server/om/OverlayManagerSettings.java b/services/core/java/com/android/server/om/OverlayManagerSettings.java
index c059b3784743..7d00423a2c41 100644
--- a/services/core/java/com/android/server/om/OverlayManagerSettings.java
+++ b/services/core/java/com/android/server/om/OverlayManagerSettings.java
@@ -230,7 +230,7 @@ final class OverlayManagerSettings {
}
mItems.remove(moveIdx);
- final int newParentIdx = select(newParentPackageName, userId);
+ final int newParentIdx = select(newParentPackageName, userId) + 1;
mItems.add(newParentIdx, itemToMove);
return moveIdx != newParentIdx;
}
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 1717b3d1a5f7..14995b3827e1 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -560,7 +560,6 @@ public class LauncherAppsService extends SystemService {
private boolean startShortcutIntentsAsPublisher(@NonNull Intent[] intents,
@NonNull String publisherPackage, Bundle startActivityOptions, int userId) {
final int code;
- final long ident = injectClearCallingIdentity();
try {
code = mActivityManagerInternal.startActivitiesAsPackage(publisherPackage,
userId, intents, startActivityOptions);
@@ -575,8 +574,6 @@ public class LauncherAppsService extends SystemService {
Slog.d(TAG, "SecurityException while launching intent", e);
}
return false;
- } finally {
- injectRestoreCallingIdentity(ident);
}
}
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index faf6114237cd..da1bdc7bb15a 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -5421,13 +5421,13 @@ Slog.e("TODD",
if (isCallerInstantApp) {
return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
}
- s1 = ((SharedUserSetting)obj).signatures.mSignatures;
+ s1 = ((SharedUserSetting)obj).signatures.mSigningDetails.signatures;
} else if (obj instanceof PackageSetting) {
final PackageSetting ps = (PackageSetting) obj;
if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
}
- s1 = ps.signatures.mSignatures;
+ s1 = ps.signatures.mSigningDetails.signatures;
} else {
return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
}
@@ -5440,13 +5440,13 @@ Slog.e("TODD",
if (isCallerInstantApp) {
return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
}
- s2 = ((SharedUserSetting)obj).signatures.mSignatures;
+ s2 = ((SharedUserSetting)obj).signatures.mSigningDetails.signatures;
} else if (obj instanceof PackageSetting) {
final PackageSetting ps = (PackageSetting) obj;
if (filterAppAccessLPr(ps, callingUid, callingUserId)) {
return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
}
- s2 = ps.signatures.mSignatures;
+ s2 = ps.signatures.mSigningDetails.signatures;
} else {
return PackageManager.SIGNATURE_UNKNOWN_PACKAGE;
}
@@ -8233,19 +8233,15 @@ Slog.e("TODD",
&& ps.timeStamp == lastModifiedTime
&& !isCompatSignatureUpdateNeeded(pkg)
&& !isRecoverSignatureUpdateNeeded(pkg)) {
- if (ps.signatures.mSignatures != null
- && ps.signatures.mSignatures.length != 0
- && ps.signatures.mSignatureSchemeVersion != SignatureSchemeVersion.UNKNOWN) {
+ if (ps.signatures.mSigningDetails.signatures != null
+ && ps.signatures.mSigningDetails.signatures.length != 0
+ && ps.signatures.mSigningDetails.signatureSchemeVersion
+ != SignatureSchemeVersion.UNKNOWN) {
// Optimization: reuse the existing cached signing data
// if the package appears to be unchanged.
- try {
- pkg.mSigningDetails = new PackageParser.SigningDetails(ps.signatures.mSignatures,
- ps.signatures.mSignatureSchemeVersion);
- return;
- } catch (CertificateException e) {
- Slog.e(TAG, "Attempt to read public keys from persisted signatures failed for "
- + ps.name, e);
- }
+ pkg.mSigningDetails =
+ new PackageParser.SigningDetails(ps.signatures.mSigningDetails);
+ return;
}
Slog.w(TAG, "PackageSetting for " + ps.name
@@ -8573,8 +8569,9 @@ Slog.e("TODD",
if (scanSystemPartition && !isSystemPkgUpdated && pkgAlreadyExists
&& !pkgSetting.isSystem()) {
// if the signatures don't match, wipe the installed application and its data
- if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSigningDetails.signatures)
- != PackageManager.SIGNATURE_MATCH) {
+ if (compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
+ pkg.mSigningDetails.signatures)
+ != PackageManager.SIGNATURE_MATCH) {
logCriticalInfo(Log.WARN,
"System package signature mismatch;"
+ " name: " + pkgSetting.name);
@@ -9936,14 +9933,14 @@ Slog.e("TODD",
if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, pkg)) {
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
- pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+ pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
} else {
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
throw new PackageManagerException(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
"Package " + pkg.packageName + " upgrade keys do not match the "
+ "previously installed version");
} else {
- pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+ pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
String msg = "System package " + pkg.packageName
+ " signature changed; retaining data.";
reportSettingsProblem(Log.WARN, msg);
@@ -9963,21 +9960,22 @@ Slog.e("TODD",
}
// We just determined the app is signed correctly, so bring
// over the latest parsed certs.
- pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+ pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
} catch (PackageManagerException e) {
if ((parseFlags & PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
throw e;
}
// The signature has changed, but this package is in the system
// image... let's recover!
- pkgSetting.signatures.mSignatures = pkg.mSigningDetails.signatures;
+ pkgSetting.signatures.mSigningDetails = pkg.mSigningDetails;
// However... if this package is part of a shared user, but it
// doesn't match the signature of the shared user, let's fail.
// What this means is that you can't change the signatures
// associated with an overall shared user, which doesn't seem all
// that unreasonable.
if (signatureCheckPs.sharedUser != null) {
- if (compareSignatures(signatureCheckPs.sharedUser.signatures.mSignatures,
+ if (compareSignatures(
+ signatureCheckPs.sharedUser.signatures.mSigningDetails.signatures,
pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH) {
throw new PackageManagerException(
INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
@@ -10804,9 +10802,12 @@ Slog.e("TODD",
if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
// Exempt SharedUsers signed with the platform key.
PackageSetting platformPkgSetting = mSettings.mPackages.get("android");
- if ((platformPkgSetting.signatures.mSignatures != null) &&
- (compareSignatures(platformPkgSetting.signatures.mSignatures,
- pkg.mSigningDetails.signatures) != PackageManager.SIGNATURE_MATCH)) {
+ if ((platformPkgSetting.signatures.mSigningDetails
+ != PackageParser.SigningDetails.UNKNOWN)
+ && (compareSignatures(
+ platformPkgSetting.signatures.mSigningDetails.signatures,
+ pkg.mSigningDetails.signatures)
+ != PackageManager.SIGNATURE_MATCH)) {
throw new PackageManagerException("Apps that share a user with a " +
"privileged app must themselves be marked as privileged. " +
pkg.packageName + " shares privileged user " +
@@ -14248,9 +14249,10 @@ Slog.e("TODD",
Object obj = mSettings.getUserIdLPr(callingUid);
if (obj != null) {
if (obj instanceof SharedUserSetting) {
- callerSignature = ((SharedUserSetting)obj).signatures.mSignatures;
+ callerSignature =
+ ((SharedUserSetting)obj).signatures.mSigningDetails.signatures;
} else if (obj instanceof PackageSetting) {
- callerSignature = ((PackageSetting)obj).signatures.mSignatures;
+ callerSignature = ((PackageSetting)obj).signatures.mSigningDetails.signatures;
} else {
throw new SecurityException("Bad object " + obj + " for uid " + callingUid);
}
@@ -14262,7 +14264,7 @@ Slog.e("TODD",
// not signed with the same cert as the caller.
if (installerPackageSetting != null) {
if (compareSignatures(callerSignature,
- installerPackageSetting.signatures.mSignatures)
+ installerPackageSetting.signatures.mSigningDetails.signatures)
!= PackageManager.SIGNATURE_MATCH) {
throw new SecurityException(
"Caller does not have same cert as new installer package "
@@ -14279,7 +14281,7 @@ Slog.e("TODD",
// okay to change it.
if (setting != null) {
if (compareSignatures(callerSignature,
- setting.signatures.mSignatures)
+ setting.signatures.mSigningDetails.signatures)
!= PackageManager.SIGNATURE_MATCH) {
throw new SecurityException(
"Caller does not have same cert as old installer package "
@@ -16787,7 +16789,8 @@ Slog.e("TODD",
sourcePackageSetting, scanFlags))) {
sigsOk = ksms.checkUpgradeKeySetLocked(sourcePackageSetting, pkg);
} else {
- sigsOk = compareSignatures(sourcePackageSetting.signatures.mSignatures,
+ sigsOk = compareSignatures(
+ sourcePackageSetting.signatures.mSigningDetails.signatures,
pkg.mSigningDetails.signatures) == PackageManager.SIGNATURE_MATCH;
}
if (!sigsOk) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 7b96ca67d38f..cfc12de02267 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -509,7 +509,7 @@ public class PackageManagerServiceUtils {
private static boolean matchSignaturesCompat(String packageName,
PackageSignatures packageSignatures, PackageParser.SigningDetails parsedSignatures) {
ArraySet<Signature> existingSet = new ArraySet<Signature>();
- for (Signature sig : packageSignatures.mSignatures) {
+ for (Signature sig : packageSignatures.mSigningDetails.signatures) {
existingSet.add(sig);
}
ArraySet<Signature> scannedCompatSet = new ArraySet<Signature>();
@@ -526,7 +526,7 @@ public class PackageManagerServiceUtils {
// make sure the expanded scanned set contains all signatures in the existing one
if (scannedCompatSet.equals(existingSet)) {
// migrate the old signatures to the new scheme
- packageSignatures.assignSignatures(parsedSignatures);
+ packageSignatures.mSigningDetails = parsedSignatures;
return true;
}
return false;
@@ -561,8 +561,8 @@ public class PackageManagerServiceUtils {
try {
PackageParser.collectCertificates(disabledPkgSetting.pkg,
PackageParser.PARSE_IS_SYSTEM_DIR);
- if (compareSignatures(pkgSetting.signatures.mSignatures,
- disabledPkgSetting.signatures.mSignatures)
+ if (compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
+ disabledPkgSetting.signatures.mSigningDetails.signatures)
!= PackageManager.SIGNATURE_MATCH) {
logCriticalInfo(Log.ERROR, "Updated system app mismatches cert on /system: " +
pkgSetting.name);
@@ -593,9 +593,9 @@ public class PackageManagerServiceUtils {
throws PackageManagerException {
final String packageName = pkgSetting.name;
boolean compatMatch = false;
- if (pkgSetting.signatures.mSignatures != null) {
+ if (pkgSetting.signatures.mSigningDetails.signatures != null) {
// Already existing package. Make sure signatures match
- boolean match = compareSignatures(pkgSetting.signatures.mSignatures,
+ boolean match = compareSignatures(pkgSetting.signatures.mSigningDetails.signatures,
parsedSignatures.signatures)
== PackageManager.SIGNATURE_MATCH;
if (!match && compareCompat) {
@@ -605,7 +605,7 @@ public class PackageManagerServiceUtils {
}
if (!match && compareRecover) {
match = matchSignaturesRecover(
- packageName, pkgSetting.signatures.mSignatures,
+ packageName, pkgSetting.signatures.mSigningDetails.signatures,
parsedSignatures.signatures);
}
@@ -620,17 +620,21 @@ public class PackageManagerServiceUtils {
}
}
// Check for shared user signatures
- if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
+ if (pkgSetting.sharedUser != null
+ && pkgSetting.sharedUser.signatures.mSigningDetails.signatures != null) {
// Already existing package. Make sure signatures match
- boolean match = compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
- parsedSignatures.signatures) == PackageManager.SIGNATURE_MATCH;
+ boolean match =
+ compareSignatures(
+ pkgSetting.sharedUser.signatures.mSigningDetails.signatures,
+ parsedSignatures.signatures) == PackageManager.SIGNATURE_MATCH;
if (!match && compareCompat) {
match = matchSignaturesCompat(
packageName, pkgSetting.sharedUser.signatures, parsedSignatures);
}
if (!match && compareRecover) {
match = matchSignaturesRecover(packageName,
- pkgSetting.sharedUser.signatures.mSignatures, parsedSignatures.signatures);
+ pkgSetting.sharedUser.signatures.mSigningDetails.signatures,
+ parsedSignatures.signatures);
compatMatch |= match;
}
if (!match) {
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index e3c4c4358e10..18356c570d01 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -233,7 +233,7 @@ public abstract class PackageSettingBase extends SettingBase {
}
public Signature[] getSignatures() {
- return signatures.mSignatures;
+ return signatures.mSigningDetails.signatures;
}
/**
diff --git a/services/core/java/com/android/server/pm/PackageSignatures.java b/services/core/java/com/android/server/pm/PackageSignatures.java
index d567d5c11cb2..d471fc837334 100644
--- a/services/core/java/com/android/server/pm/PackageSignatures.java
+++ b/services/core/java/com/android/server/pm/PackageSignatures.java
@@ -22,91 +22,148 @@ import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlSerializer;
+import android.annotation.NonNull;
import android.content.pm.PackageParser;
import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
import android.content.pm.Signature;
import android.util.Log;
import java.io.IOException;
+import java.security.cert.CertificateException;
import java.util.ArrayList;
class PackageSignatures {
- Signature[] mSignatures;
- @SignatureSchemeVersion int mSignatureSchemeVersion;
+
+ @NonNull PackageParser.SigningDetails mSigningDetails;
PackageSignatures(PackageSignatures orig) {
- if (orig != null && orig.mSignatures != null) {
- mSignatures = orig.mSignatures.clone();
- mSignatureSchemeVersion = orig.mSignatureSchemeVersion;
+ if (orig != null && orig.mSigningDetails != PackageParser.SigningDetails.UNKNOWN) {
+ mSigningDetails = new PackageParser.SigningDetails(orig.mSigningDetails);
+ } else {
+ mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
}
}
PackageSignatures(PackageParser.SigningDetails signingDetails) {
- assignSignatures(signingDetails);
+ mSigningDetails = signingDetails;
}
PackageSignatures() {
+ mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
}
void writeXml(XmlSerializer serializer, String tagName,
- ArrayList<Signature> pastSignatures) throws IOException {
- if (mSignatures == null) {
+ ArrayList<Signature> writtenSignatures) throws IOException {
+ if (mSigningDetails.signatures == null) {
return;
}
serializer.startTag(null, tagName);
- serializer.attribute(null, "count",
- Integer.toString(mSignatures.length));
- serializer.attribute(null, "schemeVersion", Integer.toString(mSignatureSchemeVersion));
- for (int i=0; i<mSignatures.length; i++) {
+ serializer.attribute(null, "count", Integer.toString(mSigningDetails.signatures.length));
+ serializer.attribute(null, "schemeVersion",
+ Integer.toString(mSigningDetails.signatureSchemeVersion));
+ writeCertsListXml(serializer, writtenSignatures, mSigningDetails.signatures, null);
+
+ // if we have past signer certificate information, write it out
+ if (mSigningDetails.pastSigningCertificates != null) {
+ serializer.startTag(null, "pastSigs");
+ serializer.attribute(null, "count",
+ Integer.toString(mSigningDetails.pastSigningCertificates.length));
+ writeCertsListXml(
+ serializer, writtenSignatures, mSigningDetails.pastSigningCertificates,
+ mSigningDetails.pastSigningCertificatesFlags);
+ serializer.endTag(null, "pastSigs");
+ }
+ serializer.endTag(null, tagName);
+ }
+
+ private void writeCertsListXml(XmlSerializer serializer, ArrayList<Signature> writtenSignatures,
+ Signature[] signatures, int[] flags) throws IOException {
+ for (int i=0; i<signatures.length; i++) {
serializer.startTag(null, "cert");
- final Signature sig = mSignatures[i];
+ final Signature sig = signatures[i];
final int sigHash = sig.hashCode();
- final int numPast = pastSignatures.size();
+ final int numWritten = writtenSignatures.size();
int j;
- for (j=0; j<numPast; j++) {
- Signature pastSig = pastSignatures.get(j);
- if (pastSig.hashCode() == sigHash && pastSig.equals(sig)) {
+ for (j=0; j<numWritten; j++) {
+ Signature writtenSig = writtenSignatures.get(j);
+ if (writtenSig.hashCode() == sigHash && writtenSig.equals(sig)) {
serializer.attribute(null, "index", Integer.toString(j));
break;
}
}
- if (j >= numPast) {
- pastSignatures.add(sig);
- serializer.attribute(null, "index", Integer.toString(numPast));
+ if (j >= numWritten) {
+ writtenSignatures.add(sig);
+ serializer.attribute(null, "index", Integer.toString(numWritten));
serializer.attribute(null, "key", sig.toCharsString());
}
+ if (flags != null) {
+ serializer.attribute(null, "flags", Integer.toString(flags[i]));
+ }
serializer.endTag(null, "cert");
}
- serializer.endTag(null, tagName);
}
- void readXml(XmlPullParser parser, ArrayList<Signature> pastSignatures)
+ void readXml(XmlPullParser parser, ArrayList<Signature> readSignatures)
throws IOException, XmlPullParserException {
+ PackageParser.SigningDetails.Builder builder =
+ new PackageParser.SigningDetails.Builder();
+
String countStr = parser.getAttributeValue(null, "count");
if (countStr == null) {
PackageManagerService.reportSettingsProblem(Log.WARN,
- "Error in package manager settings: <signatures> has"
+ "Error in package manager settings: <sigs> has"
+ " no count at " + parser.getPositionDescription());
XmlUtils.skipCurrentTag(parser);
}
+ final int count = Integer.parseInt(countStr);
+
String schemeVersionStr = parser.getAttributeValue(null, "schemeVersion");
+ int signatureSchemeVersion;
if (schemeVersionStr == null) {
PackageManagerService.reportSettingsProblem(Log.WARN,
- "Error in package manager settings: <signatures> has no schemeVersion at "
+ "Error in package manager settings: <sigs> has no schemeVersion at "
+ parser.getPositionDescription());
- mSignatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
+ signatureSchemeVersion = SignatureSchemeVersion.UNKNOWN;
} else {
- mSignatureSchemeVersion = Integer.parseInt(countStr);
+ signatureSchemeVersion = Integer.parseInt(schemeVersionStr);
}
- final int count = Integer.parseInt(countStr);
- mSignatures = new Signature[count];
+ builder.setSignatureSchemeVersion(signatureSchemeVersion);
+ Signature[] signatures = new Signature[count];
+ int pos = readCertsListXml(parser, readSignatures, signatures, null, builder);
+ builder.setSignatures(signatures);
+ if (pos < count) {
+ // Should never happen -- there is an error in the written
+ // settings -- but if it does we don't want to generate
+ // a bad array.
+ Signature[] newSigs = new Signature[pos];
+ System.arraycopy(signatures, 0, newSigs, 0, pos);
+ builder = builder.setSignatures(newSigs);
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: <sigs> count does not match number of "
+ + " <cert> entries" + parser.getPositionDescription());
+ }
+
+ try {
+ mSigningDetails = builder.build();
+ } catch (CertificateException e) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: <sigs> "
+ + "unable to convert certificate(s) to public key(s).");
+ mSigningDetails = PackageParser.SigningDetails.UNKNOWN;
+ }
+ }
+
+ private int readCertsListXml(XmlPullParser parser, ArrayList<Signature> readSignatures,
+ Signature[] signatures, int[] flags, PackageParser.SigningDetails.Builder builder)
+ throws IOException, XmlPullParserException {
+ int count = signatures.length;
int pos = 0;
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG
- || parser.getDepth() > outerDepth)) {
+ && (type != XmlPullParser.END_TAG
+ || parser.getDepth() > outerDepth)) {
if (type == XmlPullParser.END_TAG
|| type == XmlPullParser.TEXT) {
continue;
@@ -121,83 +178,128 @@ class PackageSignatures {
int idx = Integer.parseInt(index);
String key = parser.getAttributeValue(null, "key");
if (key == null) {
- if (idx >= 0 && idx < pastSignatures.size()) {
- Signature sig = pastSignatures.get(idx);
+ if (idx >= 0 && idx < readSignatures.size()) {
+ Signature sig = readSignatures.get(idx);
if (sig != null) {
- mSignatures[pos] = pastSignatures.get(idx);
+ signatures[pos] = readSignatures.get(idx);
pos++;
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> "
- + "index " + index + " is not defined at "
- + parser.getPositionDescription());
+ + "index " + index + " is not defined at "
+ + parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> "
- + "index " + index + " is out of bounds at "
- + parser.getPositionDescription());
+ + "index " + index + " is out of bounds at "
+ + parser.getPositionDescription());
}
} else {
- while (pastSignatures.size() <= idx) {
- pastSignatures.add(null);
+ while (readSignatures.size() <= idx) {
+ readSignatures.add(null);
}
Signature sig = new Signature(key);
- pastSignatures.set(idx, sig);
- mSignatures[pos] = sig;
+ readSignatures.set(idx, sig);
+ signatures[pos] = sig;
pos++;
}
} catch (NumberFormatException e) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> "
- + "index " + index + " is not a number at "
- + parser.getPositionDescription());
+ + "index " + index + " is not a number at "
+ + parser.getPositionDescription());
} catch (IllegalArgumentException e) {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> "
- + "index " + index + " has an invalid signature at "
- + parser.getPositionDescription() + ": "
- + e.getMessage());
+ + "index " + index + " has an invalid signature at "
+ + parser.getPositionDescription() + ": "
+ + e.getMessage());
+ }
+
+ if (flags != null) {
+ String flagsStr = parser.getAttributeValue(null, "flags");
+ if (flagsStr != null) {
+ try {
+ flags[pos] = Integer.parseInt(flagsStr);
+ } catch (NumberFormatException e) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: <cert> "
+ + "flags " + flagsStr + " is not a number at "
+ + parser.getPositionDescription());
+ }
+ } else {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: <cert> has no"
+ + " flags at " + parser.getPositionDescription());
+ }
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: <cert> has"
- + " no index at " + parser.getPositionDescription());
+ + " no index at " + parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
"Error in package manager settings: too "
- + "many <cert> tags, expected " + count
- + " at " + parser.getPositionDescription());
+ + "many <cert> tags, expected " + count
+ + " at " + parser.getPositionDescription());
+ }
+ } else if (tagName.equals("pastSigs")) {
+ if (flags == null) {
+ // we haven't encountered pastSigs yet, go ahead
+ String countStr = parser.getAttributeValue(null, "count");
+ if (countStr == null) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: <pastSigs> has"
+ + " no count at " + parser.getPositionDescription());
+ XmlUtils.skipCurrentTag(parser);
+ }
+ try {
+ final int pastSigsCount = Integer.parseInt(countStr);
+ Signature[] pastSignatures = new Signature[pastSigsCount];
+ int[] pastSignaturesFlags = new int[pastSigsCount];
+ int pastSigsPos = readCertsListXml(parser, readSignatures, pastSignatures,
+ pastSignaturesFlags, builder);
+ builder = builder
+ .setPastSigningCertificates(pastSignatures)
+ .setPastSigningCertificatesFlags(pastSignaturesFlags);
+
+ if (pastSigsPos < pastSigsCount) {
+ // Should never happen -- there is an error in the written
+ // settings -- but if it does we don't want to generate
+ // a bad array.
+ Signature[] newSigs = new Signature[pastSigsPos];
+ System.arraycopy(pastSignatures, 0, newSigs, 0, pastSigsPos);
+ int[] newFlags = new int[pastSigsPos];
+ System.arraycopy(pastSignaturesFlags, 0, newFlags, 0, pastSigsPos);
+ builder = builder
+ .setPastSigningCertificates(newSigs)
+ .setPastSigningCertificatesFlags(newFlags);
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: <pastSigs> count does not "
+ + "match number of <cert> entries "
+ + parser.getPositionDescription());
+ }
+ } catch (NumberFormatException e) {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Error in package manager settings: <pastSigs> "
+ + "count " + countStr + " is not a number at "
+ + parser.getPositionDescription());
+ }
+ } else {
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "<pastSigs> encountered multiple times under the same <sigs> at "
+ + parser.getPositionDescription());
}
} else {
PackageManagerService.reportSettingsProblem(Log.WARN,
- "Unknown element under <cert>: "
- + parser.getName());
+ "Unknown element under <sigs>: "
+ + parser.getName());
}
XmlUtils.skipCurrentTag(parser);
}
-
- if (pos < count) {
- // Should never happen -- there is an error in the written
- // settings -- but if it does we don't want to generate
- // a bad array.
- Signature[] newSigs = new Signature[pos];
- System.arraycopy(mSignatures, 0, newSigs, 0, pos);
- mSignatures = newSigs;
- }
- }
-
- void assignSignatures(PackageParser.SigningDetails signingDetails) {
- mSignatureSchemeVersion = signingDetails.signatureSchemeVersion;
- if (!signingDetails.hasSignatures()) {
- mSignatures = null;
- return;
- }
- mSignatures = new Signature[signingDetails.signatures.length];
- for (int i=0; i<signingDetails.signatures.length; i++) {
- mSignatures[i] = signingDetails.signatures[i];
- }
+ return pos;
}
@Override
@@ -206,16 +308,26 @@ class PackageSignatures {
buf.append("PackageSignatures{");
buf.append(Integer.toHexString(System.identityHashCode(this)));
buf.append(" version:");
- buf.append(mSignatureSchemeVersion);
+ buf.append(mSigningDetails.signatureSchemeVersion);
buf.append(", signatures:[");
- if (mSignatures != null) {
- for (int i=0; i<mSignatures.length; i++) {
+ if (mSigningDetails.signatures != null) {
+ for (int i = 0; i < mSigningDetails.signatures.length; i++) {
if (i > 0) buf.append(", ");
buf.append(Integer.toHexString(
- mSignatures[i].hashCode()));
+ mSigningDetails.signatures[i].hashCode()));
}
}
buf.append("]}");
+ buf.append(", past signatures:[");
+ if (mSigningDetails.pastSigningCertificates != null) {
+ for (int i = 0; i < mSigningDetails.pastSigningCertificates.length; i++) {
+ if (i > 0) buf.append(", ");
+ buf.append(Integer.toHexString(
+ mSigningDetails.pastSigningCertificates[i].hashCode()));
+ buf.append(" flags: ");
+ buf.append(Integer.toHexString(mSigningDetails.pastSigningCertificatesFlags[i]));
+ }
+ }
return buf.toString();
}
} \ No newline at end of file
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index ecbc45217dbb..8ce412e5783a 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -920,13 +920,13 @@ public final class Settings {
// by that time.
void insertPackageSettingLPw(PackageSetting p, PackageParser.Package pkg) {
// Update signatures if needed.
- if (p.signatures.mSignatures == null) {
- p.signatures.assignSignatures(pkg.mSigningDetails);
+ if (p.signatures.mSigningDetails.signatures == null) {
+ p.signatures.mSigningDetails = pkg.mSigningDetails;
}
// If this app defines a shared user id initialize
// the shared user signatures as well.
- if (p.sharedUser != null && p.sharedUser.signatures.mSignatures == null) {
- p.sharedUser.signatures.assignSignatures(pkg.mSigningDetails);
+ if (p.sharedUser != null && p.sharedUser.signatures.mSigningDetails.signatures == null) {
+ p.sharedUser.signatures.mSigningDetails = pkg.mSigningDetails;
}
addPackageSettingLPw(p, p.sharedUser);
}
diff --git a/services/core/java/com/android/server/timezone/RulesManagerService.java b/services/core/java/com/android/server/timezone/RulesManagerService.java
index 30fc63c2a1b0..be9b204721db 100644
--- a/services/core/java/com/android/server/timezone/RulesManagerService.java
+++ b/services/core/java/com/android/server/timezone/RulesManagerService.java
@@ -143,6 +143,26 @@ public final class RulesManagerService extends IRulesManager.Stub {
return null;
}
+ // Determine the installed distro state. This should be possible regardless of whether
+ // there's an operation in progress.
+ DistroVersion installedDistroVersion;
+ int distroStatus = DISTRO_STATUS_UNKNOWN;
+ DistroRulesVersion installedDistroRulesVersion = null;
+ try {
+ installedDistroVersion = mInstaller.getInstalledDistroVersion();
+ if (installedDistroVersion == null) {
+ distroStatus = DISTRO_STATUS_NONE;
+ installedDistroRulesVersion = null;
+ } else {
+ distroStatus = DISTRO_STATUS_INSTALLED;
+ installedDistroRulesVersion = new DistroRulesVersion(
+ installedDistroVersion.rulesVersion,
+ installedDistroVersion.revision);
+ }
+ } catch (DistroException | IOException e) {
+ Slog.w(TAG, "Failed to read installed distro.", e);
+ }
+
boolean operationInProgress = this.mOperationInProgress.get();
// Determine the staged operation status, if possible.
@@ -168,27 +188,6 @@ public final class RulesManagerService extends IRulesManager.Stub {
Slog.w(TAG, "Failed to read staged distro.", e);
}
}
-
- // Determine the installed distro state, if possible.
- DistroVersion installedDistroVersion;
- int distroStatus = DISTRO_STATUS_UNKNOWN;
- DistroRulesVersion installedDistroRulesVersion = null;
- if (!operationInProgress) {
- try {
- installedDistroVersion = mInstaller.getInstalledDistroVersion();
- if (installedDistroVersion == null) {
- distroStatus = DISTRO_STATUS_NONE;
- installedDistroRulesVersion = null;
- } else {
- distroStatus = DISTRO_STATUS_INSTALLED;
- installedDistroRulesVersion = new DistroRulesVersion(
- installedDistroVersion.rulesVersion,
- installedDistroVersion.revision);
- }
- } catch (DistroException | IOException e) {
- Slog.w(TAG, "Failed to read installed distro.", e);
- }
- }
return new RulesState(systemRulesVersion, DISTRO_FORMAT_VERSION_SUPPORTED,
operationInProgress, stagedOperationStatus, stagedDistroRulesVersion,
distroStatus, installedDistroRulesVersion);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index 7a0b1bf46fcf..4f2866bd8363 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -26,6 +26,7 @@ import android.security.keystore.ParcelableKeyGenParameterSpec;
import com.android.internal.R;
import com.android.server.SystemService;
+import java.util.ArrayList;
import java.util.List;
/**
@@ -135,4 +136,14 @@ abstract class BaseIDevicePolicyManager extends IDevicePolicyManager.Stub {
public CharSequence getPrintingDisabledReason() {
return null;
}
+
+ @Override
+ public List<String> setMeteredDataDisabled(ComponentName admin, List<String> packageNames) {
+ return packageNames;
+ }
+
+ @Override
+ public List<String> getMeteredDataDisabled(ComponentName admin) {
+ return new ArrayList<>();
+ }
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 6bee9d67f215..4d6989badda8 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -806,6 +806,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
private static final String TAG_MANDATORY_BACKUP_TRANSPORT = "mandatory_backup_transport";
private static final String TAG_START_USER_SESSION_MESSAGE = "start_user_session_message";
private static final String TAG_END_USER_SESSION_MESSAGE = "end_user_session_message";
+ private static final String TAG_METERED_DATA_DISABLED_PACKAGES
+ = "metered_data_disabled_packages";
DeviceAdminInfo info;
@@ -872,6 +874,9 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
+ // The list of packages which are not allowed to use metered data.
+ List<String> meteredDisabledPackages;
+
final Set<String> accountTypesWithManagementDisabled = new ArraySet<>();
// The list of permitted accessibility services package namesas set by a profile
@@ -1153,6 +1158,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
writePackageListToXml(out, TAG_PERMITTED_NOTIFICATION_LISTENERS,
permittedNotificationListeners);
writePackageListToXml(out, TAG_KEEP_UNINSTALLED_PACKAGES, keepUninstalledPackages);
+ writePackageListToXml(out, TAG_METERED_DATA_DISABLED_PACKAGES, meteredDisabledPackages);
if (hasUserRestrictions()) {
UserRestrictionsUtils.writeRestrictions(
out, userRestrictions, TAG_USER_RESTRICTIONS);
@@ -1349,6 +1355,8 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
permittedNotificationListeners = readPackageList(parser, tag);
} else if (TAG_KEEP_UNINSTALLED_PACKAGES.equals(tag)) {
keepUninstalledPackages = readPackageList(parser, tag);
+ } else if (TAG_METERED_DATA_DISABLED_PACKAGES.equals(tag)) {
+ meteredDisabledPackages = readPackageList(parser, tag);
} else if (TAG_USER_RESTRICTIONS.equals(tag)) {
userRestrictions = UserRestrictionsUtils.readRestrictions(parser);
} else if (TAG_DEFAULT_ENABLED_USER_RESTRICTIONS.equals(tag)) {
@@ -1647,6 +1655,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
policy.mAdminList.remove(i);
policy.mAdminMap.remove(aa.info.getComponent());
pushActiveAdminPackagesLocked(userHandle);
+ pushMeteredDisabledPackagesLocked(userHandle);
}
}
} catch (RemoteException re) {
@@ -3502,6 +3511,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
mInjector.postOnSystemServerInitThreadPool(() -> {
pushActiveAdminPackages();
mUsageStatsManagerInternal.onAdminDataAvailable();
+ pushAllMeteredRestrictedPackages();
mInjector.getNetworkPolicyManagerInternal().onAdminDataAvailable();
});
}
@@ -3517,6 +3527,17 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
}
+ private void pushAllMeteredRestrictedPackages() {
+ synchronized (this) {
+ final List<UserInfo> users = mUserManager.getUsers();
+ for (int i = users.size() - 1; i >= 0; --i) {
+ final int userId = users.get(i).id;
+ mInjector.getNetworkPolicyManagerInternal().setMeteredRestrictedPackagesAsync(
+ getMeteredDisabledPackagesLocked(userId), userId);
+ }
+ }
+ }
+
private void pushActiveAdminPackagesLocked(int userId) {
mUsageStatsManagerInternal.setActiveAdminApps(
getActiveAdminPackagesLocked(userId), userId);
@@ -11031,6 +11052,93 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
}
@Override
+ public List<String> setMeteredDataDisabled(ComponentName who, List<String> packageNames) {
+ Preconditions.checkNotNull(who);
+ Preconditions.checkNotNull(packageNames);
+
+ if (!mHasFeature) {
+ return packageNames;
+ }
+ synchronized (this) {
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ final int callingUserId = mInjector.userHandleGetCallingUserId();
+ final long identity = mInjector.binderClearCallingIdentity();
+ try {
+ final List<String> excludedPkgs
+ = removeInvalidPkgsForMeteredDataRestriction(callingUserId, packageNames);
+ admin.meteredDisabledPackages = packageNames;
+ pushMeteredDisabledPackagesLocked(callingUserId);
+ saveSettingsLocked(callingUserId);
+ return excludedPkgs;
+ } finally {
+ mInjector.binderRestoreCallingIdentity(identity);
+ }
+ }
+ }
+
+ private List<String> removeInvalidPkgsForMeteredDataRestriction(
+ int userId, List<String> pkgNames) {
+ final Set<String> activeAdmins = getActiveAdminPackagesLocked(userId);
+ final List<String> excludedPkgs = new ArrayList<>();
+ for (int i = pkgNames.size() - 1; i >= 0; --i) {
+ final String pkgName = pkgNames.get(i);
+ // If the package is an active admin, don't restrict it.
+ if (activeAdmins.contains(pkgName)) {
+ excludedPkgs.add(pkgName);
+ continue;
+ }
+ // If the package doesn't exist, don't restrict it.
+ try {
+ if (!mInjector.getIPackageManager().isPackageAvailable(pkgName, userId)) {
+ excludedPkgs.add(pkgName);
+ }
+ } catch (RemoteException e) {
+ // Should not happen
+ }
+ }
+ pkgNames.removeAll(excludedPkgs);
+ return excludedPkgs;
+ }
+
+ @Override
+ public List<String> getMeteredDataDisabled(ComponentName who) {
+ Preconditions.checkNotNull(who);
+
+ if (!mHasFeature) {
+ return new ArrayList<>();
+ }
+ synchronized (this) {
+ final ActiveAdmin admin = getActiveAdminForCallerLocked(who,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+ return admin.meteredDisabledPackages == null
+ ? new ArrayList<>() : admin.meteredDisabledPackages;
+ }
+ }
+
+ private void pushMeteredDisabledPackagesLocked(int userId) {
+ mInjector.getNetworkPolicyManagerInternal().setMeteredRestrictedPackages(
+ getMeteredDisabledPackagesLocked(userId), userId);
+ }
+
+ private Set<String> getMeteredDisabledPackagesLocked(int userId) {
+ final DevicePolicyData policy = getUserData(userId);
+ final Set<String> restrictedPkgs = new ArraySet<>();
+ for (int i = policy.mAdminList.size() - 1; i >= 0; --i) {
+ final ActiveAdmin admin = policy.mAdminList.get(i);
+ if (!isActiveAdminWithPolicyForUserLocked(admin,
+ DeviceAdminInfo.USES_POLICY_PROFILE_OWNER, userId)) {
+ // Not a profile or device owner, ignore
+ continue;
+ }
+ if (admin.meteredDisabledPackages != null) {
+ restrictedPkgs.addAll(admin.meteredDisabledPackages);
+ }
+ }
+ return restrictedPkgs;
+ }
+
+ @Override
public void setAffiliationIds(ComponentName admin, List<String> ids) {
if (!mHasFeature) {
return;
@@ -11389,6 +11497,7 @@ public class DevicePolicyManagerService extends BaseIDevicePolicyManager {
resetGlobalProxyLocked(policy);
}
pushActiveAdminPackagesLocked(userHandle);
+ pushMeteredDisabledPackagesLocked(userHandle);
saveSettingsLocked(userHandle);
updateMaximumTimeToLockLocked(userHandle);
policy.mRemovingAdmins.remove(adminReceiver);
diff --git a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
index 589a89bcbddf..b58c7003f39e 100644
--- a/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
+++ b/services/tests/servicestests/src/com/android/server/am/ActivityStarterTests.java
@@ -228,8 +228,8 @@ public class ActivityStarterTests extends ActivityTestsBase {
if (containsConditions(preconditions,PRECONDITION_CANNOT_START_ANY_ACTIVITY)) {
doReturn(false).when(service.mStackSupervisor).checkStartAnyActivityPermission(
- any(), any(), any(), anyInt(), anyInt(), anyInt(), any(), anyBoolean(),
- any(), any(), any(), any());
+ any(), any(), any(), anyInt(), anyInt(), anyInt(), any(),
+ anyBoolean(), any(), any(), any());
}
try {
@@ -278,7 +278,7 @@ public class ActivityStarterTests extends ActivityTestsBase {
.setResultTo(resultTo)
.setRequestCode(requestCode)
.setReason("testLaunchActivityPermissionDenied")
- .setActivityOptions(options)
+ .setActivityOptions(new SafeActivityOptions(options))
.execute();
verify(options, times(1)).abort();
}
diff --git a/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java
new file mode 100644
index 000000000000..168bc1782d56
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/am/SafeActivityOptionsTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2018 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.am;
+
+import static org.junit.Assert.assertEquals;
+
+import android.app.ActivityOptions;
+import android.platform.test.annotations.Presubmit;
+import android.support.test.filters.FlakyTest;
+import android.support.test.filters.MediumTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@MediumTest
+@Presubmit
+@FlakyTest
+@RunWith(AndroidJUnit4.class)
+public class SafeActivityOptionsTest {
+
+ @Test
+ public void testMerge() {
+ final ActivityOptions opts1 = ActivityOptions.makeBasic();
+ opts1.setLaunchDisplayId(5);
+ final ActivityOptions opts2 = ActivityOptions.makeBasic();
+ opts2.setLaunchDisplayId(6);
+ final SafeActivityOptions options = new SafeActivityOptions(opts1);
+ final ActivityOptions result = options.mergeActivityOptions(opts1, opts2);
+ assertEquals(6, result.getLaunchDisplayId());
+ }
+}
diff --git a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
index 9cac536bead6..613d0afea183 100644
--- a/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
+++ b/services/tests/servicestests/src/com/android/server/backup/testutils/PackageManagerStub.java
@@ -87,6 +87,11 @@ public class PackageManagerStub extends PackageManager {
}
@Override
+ public Intent getCarLaunchIntentForPackage(String packageName) {
+ return null;
+ }
+
+ @Override
public int[] getPackageGids(String packageName) throws NameNotFoundException {
return new int[0];
}
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
index 725ede81754a..e8d6ed28ed29 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerTest.java
@@ -126,6 +126,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
permission.MANAGE_DEVICE_ADMINS, permission.MANAGE_PROFILE_AND_DEVICE_OWNERS,
permission.MANAGE_USERS, permission.INTERACT_ACROSS_USERS_FULL);
public static final String NOT_DEVICE_OWNER_MSG = "does not own the device";
+ public static final String NOT_PROFILE_OWNER_MSG = "does not own the profile";
public static final String ONGOING_CALL_MSG = "ongoing call on the device";
// TODO replace all instances of this with explicit {@link #mServiceContext}.
@@ -301,10 +302,10 @@ public class DevicePolicyManagerTest extends DpmTestBase {
// Verify
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
- MockUtils.checkAdminApps(admin1.getPackageName()),
+ MockUtils.checkApps(admin1.getPackageName()),
eq(UserHandle.USER_SYSTEM));
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
- MockUtils.checkAdminApps(admin2.getPackageName(),
+ MockUtils.checkApps(admin2.getPackageName(),
adminAnotherPackage.getPackageName()),
eq(DpmMockContext.CALLER_USER_HANDLE));
verify(getServices().usageStatsManagerInternal).onAdminDataAvailable();
@@ -705,7 +706,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
assertFalse(dpm.isAdminActiveAsUser(admin1, DpmMockContext.CALLER_USER_HANDLE));
verify(getServices().usageStatsManagerInternal).setActiveAdminApps(
- MockUtils.checkAdminApps(admin2.getPackageName()),
+ MockUtils.checkApps(admin2.getPackageName()),
eq(DpmMockContext.CALLER_USER_HANDLE));
// Again broadcast from saveSettingsLocked().
@@ -1360,6 +1361,7 @@ public class DevicePolicyManagerTest extends DpmTestBase {
eq(packageName),
anyInt(),
eq(userId));
+ doReturn(true).when(getServices().ipackageManager).isPackageAvailable(packageName, userId);
// Setup application UID with the PackageManager
doReturn(uid).when(getServices().packageManager).getPackageUidAsUser(
eq(packageName),
@@ -2101,6 +2103,53 @@ public class DevicePolicyManagerTest extends DpmTestBase {
}
}
+ public void testSetGetMeteredDataDisabled() throws Exception {
+ setAsProfileOwner(admin1);
+
+ final ArrayList<String> emptyList = new ArrayList<>();
+ assertEquals(emptyList, dpm.getMeteredDataDisabled(admin1));
+
+ // Setup
+ final ArrayList<String> pkgsToRestrict = new ArrayList<>();
+ final String package1 = "com.example.one";
+ final String package2 = "com.example.two";
+ pkgsToRestrict.add(package1);
+ pkgsToRestrict.add(package2);
+ setupPackageInPackageManager(package1, DpmMockContext.CALLER_USER_HANDLE, 123, 0);
+ setupPackageInPackageManager(package2, DpmMockContext.CALLER_USER_HANDLE, 456, 0);
+ List<String> excludedPkgs = dpm.setMeteredDataDisabled(admin1, pkgsToRestrict);
+
+ // Verify
+ assertEquals(emptyList, excludedPkgs);
+ assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabled(admin1));
+ verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
+ MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
+ eq(DpmMockContext.CALLER_USER_HANDLE));
+
+ // Setup
+ pkgsToRestrict.remove(package1);
+ excludedPkgs = dpm.setMeteredDataDisabled(admin1, pkgsToRestrict);
+
+ // Verify
+ assertEquals(emptyList, excludedPkgs);
+ assertEquals(pkgsToRestrict, dpm.getMeteredDataDisabled(admin1));
+ verify(getServices().networkPolicyManagerInternal).setMeteredRestrictedPackages(
+ MockUtils.checkApps(pkgsToRestrict.toArray(new String[0])),
+ eq(DpmMockContext.CALLER_USER_HANDLE));
+ }
+
+ public void testSetGetMeteredDataDisabled_deviceAdmin() {
+ mContext.callerPermissions.add(permission.MANAGE_DEVICE_ADMINS);
+ dpm.setActiveAdmin(admin1, true);
+ assertTrue(dpm.isAdminActive(admin1));
+ mContext.callerPermissions.remove(permission.MANAGE_DEVICE_ADMINS);
+
+ assertExpectException(SecurityException.class, /* messageRegex= */ NOT_PROFILE_OWNER_MSG,
+ () -> dpm.setMeteredDataDisabled(admin1, new ArrayList<>()));
+ assertExpectException(SecurityException.class, /* messageRegex= */ NOT_PROFILE_OWNER_MSG,
+ () -> dpm.getMeteredDataDisabled(admin1));
+ }
+
public void testCreateAdminSupportIntent() throws Exception {
// Setup device owner.
mContext.binder.callingUid = DpmMockContext.CALLER_SYSTEM_USER_UID;
diff --git a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
index dec962eeefeb..92ea76656693 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/MockUtils.java
@@ -119,25 +119,25 @@ public class MockUtils {
return MockitoHamcrest.argThat(m);
}
- public static Set<String> checkAdminApps(String... adminApps) {
+ public static Set<String> checkApps(String... adminApps) {
final Matcher<Set<String>> m = new BaseMatcher<Set<String>>() {
@Override
public boolean matches(Object item) {
if (item == null) return false;
- final Set<String> actualAdminApps = (Set<String>) item;
- if (adminApps.length != actualAdminApps.size()) {
+ final Set<String> actualApps = (Set<String>) item;
+ if (adminApps.length != actualApps.size()) {
return false;
}
- final Set<String> copyOfAdmins = new ArraySet<>(actualAdminApps);
+ final Set<String> copyOfApps = new ArraySet<>(actualApps);
for (String adminApp : adminApps) {
- copyOfAdmins.remove(adminApp);
+ copyOfApps.remove(adminApp);
}
- return copyOfAdmins.isEmpty();
+ return copyOfApps.isEmpty();
}
@Override
public void describeTo(Description description) {
- description.appendText("Admin apps=" + Arrays.toString(adminApps));
+ description.appendText("Apps=" + Arrays.toString(adminApps));
}
};
return MockitoHamcrest.argThat(m);
diff --git a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
index c5f8c90dd6c6..675000e91a1c 100644
--- a/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/PersistentDataStoreTest.java
@@ -171,6 +171,23 @@ public class PersistentDataStoreTest {
newDataStore.getBrightnessConfiguration(0 /*userSerial*/));
}
+ @Test
+ public void testNullBrightnessConfiguration() {
+ final float[] lux = { 0f, 10f };
+ final float[] nits = {1f, 100f };
+ final BrightnessConfiguration config = new BrightnessConfiguration.Builder(lux, nits)
+ .setDescription("a description")
+ .build();
+ mDataStore.loadIfNeeded();
+ assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/));
+
+ mDataStore.setBrightnessConfigurationForUser(config, 0, "packagename");
+ assertNotNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/));
+
+ mDataStore.setBrightnessConfigurationForUser(null, 0, "packagename");
+ assertNull(mDataStore.getBrightnessConfiguration(0 /*userSerial*/));
+ }
+
public class TestInjector extends PersistentDataStore.Injector {
private InputStream mReadStream;
private OutputStream mWriteStream;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
index 272b5d899d4b..e8648701bd0d 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/BaseLockSettingsServiceTests.java
@@ -31,6 +31,7 @@ import android.app.admin.DevicePolicyManagerInternal;
import android.app.trust.TrustManager;
import android.content.ComponentName;
import android.content.pm.UserInfo;
+import android.hardware.authsecret.V1_0.IAuthSecret;
import android.os.FileUtils;
import android.os.IProgressListener;
import android.os.RemoteException;
@@ -80,6 +81,7 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase {
DevicePolicyManagerInternal mDevicePolicyManagerInternal;
KeyStore mKeyStore;
MockSyntheticPasswordManager mSpManager;
+ IAuthSecret mAuthSecretService;
@Override
protected void setUp() throws Exception {
@@ -115,17 +117,21 @@ public class BaseLockSettingsServiceTests extends AndroidTestCase {
};
mSpManager = new MockSyntheticPasswordManager(mContext, mStorage, mGateKeeperService,
mUserManager);
+ mAuthSecretService = mock(IAuthSecret.class);
mService = new LockSettingsServiceTestable(mContext, mLockPatternUtils, mStorage,
mGateKeeperService, mKeyStore, setUpStorageManagerMock(), mActivityManager,
- mSpManager);
+ mSpManager, mAuthSecretService);
when(mUserManager.getUserInfo(eq(PRIMARY_USER_ID))).thenReturn(PRIMARY_USER_INFO);
mPrimaryUserProfiles.add(PRIMARY_USER_INFO);
installChildProfile(MANAGED_PROFILE_USER_ID);
installAndTurnOffChildProfile(TURNED_OFF_PROFILE_USER_ID);
- when(mUserManager.getUsers(anyBoolean())).thenReturn(mPrimaryUserProfiles);
when(mUserManager.getProfiles(eq(PRIMARY_USER_ID))).thenReturn(mPrimaryUserProfiles);
when(mUserManager.getUserInfo(eq(SECONDARY_USER_ID))).thenReturn(SECONDARY_USER_INFO);
+ final ArrayList<UserInfo> allUsers = new ArrayList<>(mPrimaryUserProfiles);
+ allUsers.add(SECONDARY_USER_INFO);
+ when(mUserManager.getUsers(anyBoolean())).thenReturn(allUsers);
+
when(mActivityManager.unlockUser(anyInt(), any(), any(), any())).thenAnswer(
new Answer<Boolean>() {
@Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
index 4ad9f19735c4..d2caa0af0ba2 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/CachedSyntheticPasswordTests.java
@@ -22,6 +22,7 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW
import static com.android.server.testutils.TestUtils.assertExpectException;
import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.atLeastOnce;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
@@ -31,6 +32,10 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.internal.widget.VerifyCredentialResponse;
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationResult;
+import java.util.ArrayList;
+
+import org.mockito.ArgumentCaptor;
+
/**
* Run the synthetic password tests with caching enabled.
*
@@ -88,6 +93,26 @@ public class CachedSyntheticPasswordTests extends SyntheticPasswordTests {
.getResponseCode());
}
+ public void testUntrustedCredentialChangeMaintainsAuthSecret() throws RemoteException {
+ final String PASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-password";
+ final String NEWPASSWORD = "testUntrustedCredentialChangeMaintainsAuthSecret-newpassword";
+
+ initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+ // Untrusted change password
+ mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, null,
+ PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+
+ // Verify the password
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+
+ // Ensure the same secret was passed each time
+ ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
+ verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
+ assertEquals(1, secret.getAllValues().stream().distinct().count());
+ }
+
public void testUntrustedCredentialChangeBlockedIfSpNotCached() throws RemoteException {
final String PASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-password";
final String NEWPASSWORD = "testUntrustedCredentialChangeBlockedIfSpNotCached-newpassword";
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
index 0916a335b51e..fe683abe7e1b 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/LockSettingsServiceTestable.java
@@ -20,6 +20,7 @@ import static org.mockito.Mockito.mock;
import android.app.IActivityManager;
import android.content.Context;
+import android.hardware.authsecret.V1_0.IAuthSecret;
import android.os.Handler;
import android.os.Looper;
import android.os.Process;
@@ -42,10 +43,12 @@ public class LockSettingsServiceTestable extends LockSettingsService {
private LockPatternUtils mLockPatternUtils;
private IStorageManager mStorageManager;
private SyntheticPasswordManager mSpManager;
+ private IAuthSecret mAuthSecretService;
public MockInjector(Context context, LockSettingsStorage storage, KeyStore keyStore,
IActivityManager activityManager, LockPatternUtils lockPatternUtils,
- IStorageManager storageManager, SyntheticPasswordManager spManager) {
+ IStorageManager storageManager, SyntheticPasswordManager spManager,
+ IAuthSecret authSecretService) {
super(context);
mLockSettingsStorage = storage;
mKeyStore = keyStore;
@@ -109,10 +112,11 @@ public class LockSettingsServiceTestable extends LockSettingsService {
protected LockSettingsServiceTestable(Context context, LockPatternUtils lockPatternUtils,
LockSettingsStorage storage, FakeGateKeeperService gatekeeper, KeyStore keystore,
IStorageManager storageManager, IActivityManager mActivityManager,
- SyntheticPasswordManager spManager) {
+ SyntheticPasswordManager spManager, IAuthSecret authSecretService) {
super(new MockInjector(context, storage, keystore, mActivityManager, lockPatternUtils,
- storageManager, spManager));
+ storageManager, spManager, authSecretService));
mGateKeeperService = gatekeeper;
+ mAuthSecretService = authSecretService;
}
@Override
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
index b07d6ac5dc04..294c3e99ad7e 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/SyntheticPasswordTests.java
@@ -24,6 +24,10 @@ import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSW
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_ENABLED_KEY;
import static com.android.internal.widget.LockPatternUtils.SYNTHETIC_PASSWORD_HANDLE_KEY;
+import static org.mockito.Mockito.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import android.app.admin.PasswordMetrics;
@@ -36,6 +40,10 @@ import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationRe
import com.android.server.locksettings.SyntheticPasswordManager.AuthenticationToken;
import com.android.server.locksettings.SyntheticPasswordManager.PasswordData;
+import java.util.ArrayList;
+
+import org.mockito.ArgumentCaptor;
+
/**
* runtest frameworks-services -c com.android.server.locksettings.SyntheticPasswordTests
@@ -169,6 +177,46 @@ public class SyntheticPasswordTests extends BaseLockSettingsServiceTests {
assertNotEquals(sid, mGateKeeperService.getSecureUserId(PRIMARY_USER_ID));
}
+ public void testSyntheticPasswordChangeCredentialKeepsAuthSecret() throws RemoteException {
+ final String PASSWORD = "testSyntheticPasswordChangeCredentialKeepsAuthSecret-password";
+ final String NEWPASSWORD = "testSyntheticPasswordChangeCredentialKeepsAuthSecret-new";
+
+ initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+ mService.setLockCredential(NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, PASSWORD,
+ PASSWORD_QUALITY_ALPHABETIC, PRIMARY_USER_ID);
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ NEWPASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+
+ // Check the same secret was passed each time
+ ArgumentCaptor<ArrayList<Byte>> secret = ArgumentCaptor.forClass(ArrayList.class);
+ verify(mAuthSecretService, atLeastOnce()).primaryUserCredential(secret.capture());
+ assertEquals(1, secret.getAllValues().stream().distinct().count());
+ }
+
+ public void testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret() throws RemoteException {
+ final String PASSWORD = "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-password";
+ final String NEWPASSWORD = "testSyntheticPasswordVerifyPassesPrimaryUserAuthSecret-new";
+
+ initializeCredentialUnderSP(PASSWORD, PRIMARY_USER_ID);
+ reset(mAuthSecretService);
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, PRIMARY_USER_ID)
+ .getResponseCode());
+ verify(mAuthSecretService).primaryUserCredential(any(ArrayList.class));
+ }
+
+ public void testSecondaryUserDoesNotPassAuthSecret() throws RemoteException {
+ final String PASSWORD = "testSecondaryUserDoesNotPassAuthSecret-password";
+ final String NEWPASSWORD = "testSecondaryUserDoesNotPassAuthSecret-new";
+
+ initializeCredentialUnderSP(PASSWORD, SECONDARY_USER_ID);
+ assertEquals(VerifyCredentialResponse.RESPONSE_OK, mService.verifyCredential(
+ PASSWORD, LockPatternUtils.CREDENTIAL_TYPE_PASSWORD, 0, SECONDARY_USER_ID)
+ .getResponseCode());
+ verify(mAuthSecretService, never()).primaryUserCredential(any(ArrayList.class));
+ }
+
public void testManagedProfileUnifiedChallengeMigration() throws RemoteException {
final String UnifiedPassword = "testManagedProfileUnifiedChallengeMigration-pwd";
disableSyntheticPassword();
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
index 7eec4fea64dc..6edaf87e135f 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/KeySyncTaskTest.java
@@ -16,11 +16,11 @@
package com.android.server.locksettings.recoverablekeystore;
-import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
+import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_LOCKSCREEN;
-import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD;
-import static android.security.keystore.KeychainProtectionParams.TYPE_PATTERN;
-import static android.security.keystore.KeychainProtectionParams.TYPE_PIN;
+import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PASSWORD;
+import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PATTERN;
+import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PIN;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PASSWORD;
import static com.android.internal.widget.LockPatternUtils.CREDENTIAL_TYPE_PATTERN;
@@ -40,9 +40,9 @@ import android.content.Context;
import android.security.keystore.AndroidKeyStoreSecretKey;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
-import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.KeychainSnapshot;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.KeychainSnapshot;
+import android.security.keystore.recovery.WrappedApplicationKey;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 970bc33337da..a3a2e4764edc 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -16,8 +16,8 @@
package com.android.server.locksettings.recoverablekeystore;
-import static android.security.keystore.KeychainProtectionParams.TYPE_LOCKSCREEN;
-import static android.security.keystore.KeychainProtectionParams.TYPE_PASSWORD;
+import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_LOCKSCREEN;
+import static android.security.keystore.recovery.KeychainProtectionParams.TYPE_PASSWORD;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertArrayEquals;
@@ -42,9 +42,9 @@ import android.os.UserHandle;
import android.security.keystore.AndroidKeyStoreSecretKey;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
-import android.security.keystore.KeyDerivationParams;
-import android.security.keystore.KeychainProtectionParams;
-import android.security.keystore.WrappedApplicationKey;
+import android.security.keystore.recovery.KeyDerivationParams;
+import android.security.keystore.recovery.KeychainProtectionParams;
+import android.security.keystore.recovery.WrappedApplicationKey;
import android.support.test.filters.SmallTest;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
index 56b44e2fa17c..89c5c6c8a072 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/storage/RecoverySnapshotStorageTest.java
@@ -3,7 +3,7 @@ package com.android.server.locksettings.recoverablekeystore.storage;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
-import android.security.keystore.KeychainSnapshot;
+import android.security.keystore.recovery.KeychainSnapshot;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
index 49601c32cdc2..5c7348c68240 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageParserTest.java
@@ -497,7 +497,9 @@ public class PackageParserTest {
new PackageParser.SigningDetails(
new Signature[] { new Signature(new byte[16]) },
2,
- new ArraySet<>());
+ new ArraySet<>(),
+ null,
+ null);
pkg.mExtras = new Bundle();
pkg.mRestrictedAccountType = "foo19";
pkg.mRequiredAccountType = "foo20";
diff --git a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
index d09d0c8d9e5c..1cfae1ef1a6d 100644
--- a/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/timezone/RulesManagerServiceTest.java
@@ -289,11 +289,13 @@ public class RulesManagerServiceTest {
// Request the rules state while the async operation is "happening".
RulesState actualRulesState = mRulesManagerService.getRulesState();
+ DistroRulesVersion expectedInstalledDistroRulesVersion =
+ new DistroRulesVersion(installedRulesVersion, revision);
RulesState expectedRuleState = new RulesState(
systemRulesVersion, RulesManagerService.DISTRO_FORMAT_VERSION_SUPPORTED,
true /* operationInProgress */,
RulesState.STAGED_OPERATION_UNKNOWN, null /* stagedDistroRulesVersion */,
- RulesState.DISTRO_STATUS_UNKNOWN, null /* installedDistroRulesVersion */);
+ RulesState.DISTRO_STATUS_INSTALLED, expectedInstalledDistroRulesVersion);
assertEquals(expectedRuleState, actualRulesState);
}
diff --git a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
index f8db4faaa81f..794d0336904a 100644
--- a/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/WindowAnimationSpecTest.java
@@ -54,7 +54,7 @@ public class WindowAnimationSpecTest {
@Test
public void testApply_clipNone() {
Rect windowCrop = new Rect(0, 0, 20, 20);
- Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+ Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_NONE);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
@@ -99,7 +99,8 @@ public class WindowAnimationSpecTest {
public void testApply_clipBeforeNoStackBounds() {
// Stack bounds is (0, 0, 0, 0) animation clip is (0, 0, 20, 20)
Rect windowCrop = new Rect(0, 0, 20, 20);
- Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+ Animation a = createClipRectAnimation(windowCrop, windowCrop);
+ a.initialize(0, 0, 0, 0);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
null, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
@@ -110,7 +111,7 @@ public class WindowAnimationSpecTest {
public void testApply_clipBeforeSmallerAnimationClip() {
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 5, 5)
Rect windowCrop = new Rect(0, 0, 5, 5);
- Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+ Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
@@ -122,11 +123,17 @@ public class WindowAnimationSpecTest {
public void testApply_clipBeforeSmallerStackClip() {
// Stack bounds is (0, 0, 10, 10) animation clip is (0, 0, 20, 20)
Rect windowCrop = new Rect(0, 0, 20, 20);
- Animation a = new ClipRectAnimation(windowCrop, windowCrop);
+ Animation a = createClipRectAnimation(windowCrop, windowCrop);
WindowAnimationSpec windowAnimationSpec = new WindowAnimationSpec(a, null,
mStackBounds, false /* canSkipFirstFrame */, STACK_CLIP_BEFORE_ANIM);
windowAnimationSpec.apply(mTransaction, mSurfaceControl, 0);
verify(mTransaction).setWindowCrop(eq(mSurfaceControl),
argThat(rect -> rect.equals(mStackBounds)));
}
+
+ private Animation createClipRectAnimation(Rect fromClip, Rect toClip) {
+ Animation a = new ClipRectAnimation(fromClip, toClip);
+ a.initialize(0, 0, 0, 0);
+ return a;
+ }
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 649d4783cc7a..cbc9428bcf56 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -275,7 +275,6 @@ public class CarrierConfigManager {
*
* @see SubscriptionManager#getSubscriptionPlans(int)
* @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
- * @hide
*/
@SystemApi
public static final String KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING =
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 57f4cf28d90d..debf43da79b4 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -462,8 +462,6 @@ public class SubscriptionManager {
* <p>
* Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
* the user is interested in.
- *
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
@SystemApi
@@ -481,8 +479,6 @@ public class SubscriptionManager {
* <p>
* Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to indicate which subscription
* the user is interested in.
- *
- * @hide
*/
@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@SystemApi
@@ -1698,7 +1694,6 @@ public class SubscriptionManager {
* </ul>
*
* @param subId the subscriber this relationship applies to
- * @hide
*/
@SystemApi
public @NonNull List<SubscriptionPlan> getSubscriptionPlans(int subId) {
@@ -1728,7 +1723,6 @@ public class SubscriptionManager {
* @param plans the list of plans. The first plan is always the primary and
* most important plan. Any additional plans are secondary and
* may not be displayed or used by decision making logic.
- * @hide
*/
@SystemApi
public void setSubscriptionPlans(int subId, @NonNull List<SubscriptionPlan> plans) {
@@ -1769,7 +1763,6 @@ public class SubscriptionManager {
* be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
- * @hide
*/
@SystemApi
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
@@ -1804,7 +1797,6 @@ public class SubscriptionManager {
* be automatically cleared, or {@code 0} to leave in the
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
- * @hide
*/
@SystemApi
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
diff --git a/telephony/java/android/telephony/SubscriptionPlan.java b/telephony/java/android/telephony/SubscriptionPlan.java
index 265e3e7c8a01..941165212aa7 100644
--- a/telephony/java/android/telephony/SubscriptionPlan.java
+++ b/telephony/java/android/telephony/SubscriptionPlan.java
@@ -43,7 +43,6 @@ import java.util.Iterator;
*
* @see SubscriptionManager#setSubscriptionPlans(int, java.util.List)
* @see SubscriptionManager#getSubscriptionPlans(int)
- * @hide
*/
@SystemApi
public final class SubscriptionPlan implements Parcelable {
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index ea0817551369..fa19ea069044 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -17,6 +17,7 @@
package android.telephony.data;
import android.annotation.CallSuper;
+import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.app.Service;
import android.content.Intent;
@@ -32,6 +33,8 @@ import android.telephony.Rlog;
import android.telephony.SubscriptionManager;
import android.util.SparseArray;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -56,6 +59,33 @@ public abstract class DataService extends Service {
public static final String DATA_SERVICE_INTERFACE = "android.telephony.data.DataService";
public static final String DATA_SERVICE_EXTRA_SLOT_ID = "android.telephony.data.extra.SLOT_ID";
+ /** {@hide} */
+ @IntDef(prefix = "REQUEST_REASON_", value = {
+ REQUEST_REASON_NORMAL,
+ REQUEST_REASON_HANDOVER,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SetupDataReason {}
+
+ /** {@hide} */
+ @IntDef(prefix = "REQUEST_REASON_", value = {
+ REQUEST_REASON_NORMAL,
+ REQUEST_REASON_SHUTDOWN,
+ REQUEST_REASON_HANDOVER,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface DeactivateDataReason {}
+
+
+ /** The reason of the data request is normal */
+ public static final int REQUEST_REASON_NORMAL = 1;
+
+ /** The reason of the data request is device shutdown */
+ public static final int REQUEST_REASON_SHUTDOWN = 2;
+
+ /** The reason of the data request is IWLAN handover */
+ public static final int REQUEST_REASON_HANDOVER = 3;
+
private static final int DATA_SERVICE_INTERNAL_REQUEST_INITIALIZE_SERVICE = 1;
private static final int DATA_SERVICE_REQUEST_SETUP_DATA_CALL = 2;
private static final int DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL = 3;
@@ -110,13 +140,14 @@ public abstract class DataService extends Service {
* @param dataProfile Data profile used for data call setup. See {@link DataProfile}
* @param isRoaming True if the device is data roaming.
* @param allowRoaming True if data roaming is allowed by the user.
- * @param isHandover True if the request is for IWLAN handover.
- * @param linkProperties If {@code isHandover} is true, this is the link properties of the
- * existing data connection, otherwise null.
+ * @param reason The reason for data setup. Must be {@link #REQUEST_REASON_NORMAL} or
+ * {@link #REQUEST_REASON_HANDOVER}.
+ * @param linkProperties If {@code reason} is {@link #REQUEST_REASON_HANDOVER}, this is the
+ * link properties of the existing data connection, otherwise null.
* @param callback The result callback for this request.
*/
public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, boolean isHandover,
+ boolean allowRoaming, @SetupDataReason int reason,
LinkProperties linkProperties, DataServiceCallback callback) {
// The default implementation is to return unsupported.
callback.onSetupDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED, null);
@@ -128,12 +159,12 @@ public abstract class DataService extends Service {
* provided callback to notify the platform.
*
* @param cid Call id returned in the callback of {@link DataServiceProvider#setupDataCall(
- * int, DataProfile, boolean, boolean, boolean, LinkProperties, DataServiceCallback)}.
- * @param reasonRadioShutDown True if the deactivate request reason is device shut down.
- * @param isHandover True if the request is for IWLAN handover.
+ * int, DataProfile, boolean, boolean, int, LinkProperties, DataServiceCallback)}.
+ * @param reason The reason for data deactivation. Must be {@link #REQUEST_REASON_NORMAL},
+ * {@link #REQUEST_REASON_SHUTDOWN} or {@link #REQUEST_REASON_HANDOVER}.
* @param callback The result callback for this request.
*/
- public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
+ public void deactivateDataCall(int cid, @DeactivateDataReason int reason,
DataServiceCallback callback) {
// The default implementation is to return unsupported.
callback.onDeactivateDataCallComplete(DataServiceCallback.RESULT_ERROR_UNSUPPORTED);
@@ -219,32 +250,29 @@ public abstract class DataService extends Service {
public final DataProfile dataProfile;
public final boolean isRoaming;
public final boolean allowRoaming;
- public final boolean isHandover;
+ public final int reason;
public final LinkProperties linkProperties;
public final IDataServiceCallback callback;
SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, boolean isHandover,
- LinkProperties linkProperties, IDataServiceCallback callback) {
+ boolean allowRoaming, int reason, LinkProperties linkProperties,
+ IDataServiceCallback callback) {
this.accessNetworkType = accessNetworkType;
this.dataProfile = dataProfile;
this.isRoaming = isRoaming;
this.allowRoaming = allowRoaming;
this.linkProperties = linkProperties;
- this.isHandover = isHandover;
+ this.reason = reason;
this.callback = callback;
}
}
private static final class DeactivateDataCallRequest {
public final int cid;
- public final boolean reasonRadioShutDown;
- public final boolean isHandover;
+ public final int reason;
public final IDataServiceCallback callback;
- DeactivateDataCallRequest(int cid, boolean reasonRadioShutDown, boolean isHandover,
- IDataServiceCallback callback) {
+ DeactivateDataCallRequest(int cid, int reason, IDataServiceCallback callback) {
this.cid = cid;
- this.reasonRadioShutDown = reasonRadioShutDown;
- this.isHandover = isHandover;
+ this.reason = reason;
this.callback = callback;
}
}
@@ -311,7 +339,7 @@ public abstract class DataService extends Service {
SetupDataCallRequest setupDataCallRequest = (SetupDataCallRequest) message.obj;
service.setupDataCall(setupDataCallRequest.accessNetworkType,
setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
- setupDataCallRequest.allowRoaming, setupDataCallRequest.isHandover,
+ setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
setupDataCallRequest.linkProperties,
new DataServiceCallback(setupDataCallRequest.callback));
@@ -321,8 +349,7 @@ public abstract class DataService extends Service {
DeactivateDataCallRequest deactivateDataCallRequest =
(DeactivateDataCallRequest) message.obj;
service.deactivateDataCall(deactivateDataCallRequest.cid,
- deactivateDataCallRequest.reasonRadioShutDown,
- deactivateDataCallRequest.isHandover,
+ deactivateDataCallRequest.reason,
new DataServiceCallback(deactivateDataCallRequest.callback));
break;
case DATA_SERVICE_REQUEST_SET_INITIAL_ATTACH_APN:
@@ -370,7 +397,8 @@ public abstract class DataService extends Service {
}
}
- private DataService() {
+ /** @hide */
+ protected DataService() {
mHandlerThread = new HandlerThread(TAG);
mHandlerThread.start();
@@ -472,19 +500,18 @@ public abstract class DataService extends Service {
@Override
public void setupDataCall(int accessNetworkType, DataProfile dataProfile,
- boolean isRoaming, boolean allowRoaming, boolean isHandover,
+ boolean isRoaming, boolean allowRoaming, int reason,
LinkProperties linkProperties, IDataServiceCallback callback) {
mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, mSlotId, 0,
new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
- allowRoaming, isHandover, linkProperties, callback))
+ allowRoaming, reason, linkProperties, callback))
.sendToTarget();
}
@Override
- public void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
- IDataServiceCallback callback) {
+ public void deactivateDataCall(int cid, int reason, IDataServiceCallback callback) {
mHandler.obtainMessage(DATA_SERVICE_REQUEST_DEACTIVATE_DATA_CALL, mSlotId, 0,
- new DeactivateDataCallRequest(cid, reasonRadioShutDown, isHandover, callback))
+ new DeactivateDataCallRequest(cid, reason, callback))
.sendToTarget();
}
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 4eaaa252da02..07720b69e45f 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -26,10 +26,9 @@ import android.telephony.data.IDataServiceCallback;
oneway interface IDataService
{
void setupDataCall(int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
- boolean allowRoaming, boolean isHandover, in LinkProperties linkProperties,
+ boolean allowRoaming, int reason, in LinkProperties linkProperties,
IDataServiceCallback callback);
- void deactivateDataCall(int cid, boolean reasonRadioShutDown, boolean isHandover,
- IDataServiceCallback callback);
+ void deactivateDataCall(int cid, int reason, IDataServiceCallback callback);
void setInitialAttachApn(in DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback);
void setDataProfile(in List<DataProfile> dps, boolean isRoaming, IDataServiceCallback callback);
diff --git a/test-mock/src/android/test/mock/MockPackageManager.java b/test-mock/src/android/test/mock/MockPackageManager.java
index 13e3693cada0..41cde175759d 100644
--- a/test-mock/src/android/test/mock/MockPackageManager.java
+++ b/test-mock/src/android/test/mock/MockPackageManager.java
@@ -108,6 +108,12 @@ public class MockPackageManager extends PackageManager {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public Intent getCarLaunchIntentForPackage(String packageName) {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public int[] getPackageGids(String packageName) throws NameNotFoundException {
throw new UnsupportedOperationException();
diff --git a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
index d9d4eeba900f..1618e07a79c0 100644
--- a/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
+++ b/tests/net/java/com/android/server/IpSecServiceParameterizedTest.java
@@ -268,6 +268,31 @@ public class IpSecServiceParameterizedTest {
anyInt());
}
+ public void testCreateTwoTransformsWithSameSpis() throws Exception {
+ IpSecConfig ipSecConfig = new IpSecConfig();
+ addDefaultSpisAndRemoteAddrToIpSecConfig(ipSecConfig);
+ addAuthAndCryptToIpSecConfig(ipSecConfig);
+
+ IpSecTransformResponse createTransformResp =
+ mIpSecService.createTransform(ipSecConfig, new Binder());
+ assertEquals(IpSecManager.Status.OK, createTransformResp.status);
+
+ // Attempting to create transform a second time with the same SPIs should throw an error...
+ try {
+ mIpSecService.createTransform(ipSecConfig, new Binder());
+ fail("IpSecService should have thrown an error for reuse of SPI");
+ } catch (IllegalStateException expected) {
+ }
+
+ // ... even if the transform is deleted
+ mIpSecService.deleteTransform(createTransformResp.resourceId);
+ try {
+ mIpSecService.createTransform(ipSecConfig, new Binder());
+ fail("IpSecService should have thrown an error for reuse of SPI");
+ } catch (IllegalStateException expected) {
+ }
+ }
+
@Test
public void testDeleteTransform() throws Exception {
IpSecConfig ipSecConfig = new IpSecConfig();