OSDN Git Service

Merge "Revert "Temporarily enable screen wakelock logging in WM"" into oc-dev
authorWale Ogunwale <ogunwale@google.com>
Thu, 8 Jun 2017 14:33:03 +0000 (14:33 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Thu, 8 Jun 2017 14:33:10 +0000 (14:33 +0000)
690 files changed:
Android.mk
api/current.txt
api/system-current.txt
api/test-current.txt
cmds/pm/src/com/android/commands/pm/Pm.java
core/java/android/accounts/AccountManager.java
core/java/android/accounts/IAccountManager.aidl
core/java/android/animation/AnimationHandler.java
core/java/android/animation/AnimatorSet.java
core/java/android/animation/ValueAnimator.java
core/java/android/annotation/SystemService.java [new file with mode: 0644]
core/java/android/app/Activity.java
core/java/android/app/ActivityManager.java
core/java/android/app/ActivityOptions.java
core/java/android/app/AlarmManager.java
core/java/android/app/AppOpsManager.java
core/java/android/app/ApplicationPackageManager.java
core/java/android/app/BroadcastOptions.java
core/java/android/app/DownloadManager.java
core/java/android/app/Instrumentation.java
core/java/android/app/KeyguardManager.java
core/java/android/app/Notification.java
core/java/android/app/NotificationChannel.java
core/java/android/app/NotificationManager.java
core/java/android/app/SearchManager.java
core/java/android/app/StatusBarManager.java
core/java/android/app/TimePickerDialog.java
core/java/android/app/UiModeManager.java
core/java/android/app/VrManager.java
core/java/android/app/WallpaperManager.java
core/java/android/app/admin/DevicePolicyManager.java
core/java/android/app/assist/AssistStructure.java
core/java/android/app/backup/BackupManager.java
core/java/android/app/job/JobInfo.java
core/java/android/app/job/JobScheduler.java
core/java/android/app/job/JobServiceEngine.java
core/java/android/app/trust/TrustManager.java
core/java/android/app/usage/IStorageStatsManager.aidl
core/java/android/app/usage/NetworkStatsManager.java
core/java/android/app/usage/StorageStatsManager.java
core/java/android/app/usage/UsageStatsManager.java
core/java/android/appwidget/AppWidgetManager.java
core/java/android/bluetooth/BluetoothManager.java
core/java/android/bluetooth/le/ScanRecord.java
core/java/android/companion/CompanionDeviceManager.java
core/java/android/content/ClipboardManager.java
core/java/android/content/Context.java
core/java/android/content/RestrictionsManager.java
core/java/android/content/pm/IPackageManager.aidl
core/java/android/content/pm/LauncherApps.java
core/java/android/content/pm/PackageInstaller.java
core/java/android/content/pm/PackageManager.java
core/java/android/content/pm/PackageManagerInternal.java
core/java/android/content/pm/PackageParser.java
core/java/android/content/pm/ShortcutManager.java
core/java/android/hardware/ConsumerIrManager.java
core/java/android/hardware/SensorManager.java
core/java/android/hardware/SerialManager.java
core/java/android/hardware/camera2/CameraManager.java
core/java/android/hardware/display/DisplayManager.java
core/java/android/hardware/fingerprint/FingerprintManager.java
core/java/android/hardware/hdmi/HdmiControlManager.java
core/java/android/hardware/input/InputManager.java
core/java/android/hardware/location/ContextHubManager.java
core/java/android/hardware/radio/RadioManager.java
core/java/android/hardware/usb/UsbManager.java
core/java/android/net/ConnectivityManager.java
core/java/android/net/EthernetManager.java
core/java/android/net/IpSecManager.java
core/java/android/net/NetworkBadging.java
core/java/android/net/NetworkPolicyManager.java
core/java/android/net/NetworkScoreManager.java
core/java/android/net/TrafficStats.java
core/java/android/net/VpnService.java
core/java/android/net/nsd/NsdManager.java
core/java/android/nfc/IAppCallback.aidl
core/java/android/nfc/NdefRecord.java
core/java/android/nfc/NfcAdapter.java
core/java/android/nfc/NfcManager.java
core/java/android/os/BatteryManager.java
core/java/android/os/BatteryStats.java
core/java/android/os/DropBoxManager.java
core/java/android/os/HardwarePropertiesManager.java
core/java/android/os/IncidentManager.java
core/java/android/os/PowerManager.java
core/java/android/os/RecoverySystem.java
core/java/android/os/UserManager.java
core/java/android/os/Vibrator.java
core/java/android/os/health/SystemHealthManager.java
core/java/android/os/storage/StorageManager.java
core/java/android/print/PrintManager.java
core/java/android/provider/ContactsContract.java
core/java/android/provider/Settings.java
core/java/android/service/autofill/FillContext.java
core/java/android/service/notification/StatusBarNotification.java
core/java/android/service/oemlock/OemLockManager.java
core/java/android/service/persistentdata/PersistentDataBlockManager.java
core/java/android/service/voice/VoiceInteractionSession.java
core/java/android/util/proto/ProtoOutputStream.java
core/java/android/view/AppTransitionAnimationSpec.java
core/java/android/view/IPinnedStackController.aidl
core/java/android/view/IWindowManager.aidl
core/java/android/view/LayoutInflater.java
core/java/android/view/SurfaceView.java
core/java/android/view/ThreadedRenderer.java
core/java/android/view/View.java
core/java/android/view/ViewGroup.java
core/java/android/view/ViewRootImpl.java
core/java/android/view/ViewStructure.java
core/java/android/view/Window.java
core/java/android/view/WindowManager.java
core/java/android/view/WindowManagerInternal.java
core/java/android/view/accessibility/AccessibilityManager.java
core/java/android/view/accessibility/CaptioningManager.java
core/java/android/view/autofill/AutofillManager.java
core/java/android/view/autofill/AutofillPopupWindow.java
core/java/android/view/inputmethod/InputMethodManager.java
core/java/android/view/textclassifier/TextClassificationManager.java
core/java/android/view/textservice/TextServicesManager.java
core/java/android/widget/ActivityChooserView.java
core/java/android/widget/Editor.java
core/java/android/widget/GridView.java
core/java/android/widget/ImageView.java
core/java/android/widget/TextView.java
core/java/com/android/internal/app/IBatteryStats.aidl
core/java/com/android/internal/app/NightDisplayController.java
core/java/com/android/internal/notification/SystemNotificationChannels.java
core/java/com/android/internal/os/BatteryStatsImpl.java
core/java/com/android/internal/os/KernelUidCpuFreqTimeReader.java
core/java/com/android/internal/policy/DecorView.java
core/java/com/android/internal/policy/IKeyguardService.aidl
core/java/com/android/internal/policy/PhoneWindow.java
core/java/com/android/internal/util/DumpUtils.java
core/java/com/android/internal/view/TooltipPopup.java
core/jni/AndroidRuntime.cpp
core/jni/android_hardware_Radio.cpp
core/jni/android_view_ThreadedRenderer.cpp
core/proto/android/providers/settings.proto
core/res/AndroidManifest.xml
core/res/res/drawable/stat_sys_vitals.xml [new file with mode: 0644]
core/res/res/drawable/sym_def_app_icon.xml
core/res/res/drawable/sym_def_app_icon_background.xml [new file with mode: 0644]
core/res/res/layout/activity_chooser_view_list_item.xml
core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png [new file with mode: 0644]
core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png [deleted file]
core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png [new file with mode: 0644]
core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png [deleted file]
core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png [new file with mode: 0644]
core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png [deleted file]
core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png [new file with mode: 0644]
core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png [deleted file]
core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png [new file with mode: 0644]
core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png [deleted file]
core/res/res/values-af/strings.xml
core/res/res/values-am/strings.xml
core/res/res/values-ar/strings.xml
core/res/res/values-az/strings.xml
core/res/res/values-b+sr+Latn/strings.xml
core/res/res/values-be/strings.xml
core/res/res/values-bg/strings.xml
core/res/res/values-bn/strings.xml
core/res/res/values-bs/strings.xml
core/res/res/values-ca/strings.xml
core/res/res/values-cs/strings.xml
core/res/res/values-da/strings.xml
core/res/res/values-de/strings.xml
core/res/res/values-el/strings.xml
core/res/res/values-en-rAU/strings.xml
core/res/res/values-en-rGB/strings.xml
core/res/res/values-en-rIN/strings.xml
core/res/res/values-es-rUS/strings.xml
core/res/res/values-es/strings.xml
core/res/res/values-et/strings.xml
core/res/res/values-eu/strings.xml
core/res/res/values-fa/strings.xml
core/res/res/values-fi/strings.xml
core/res/res/values-fr-rCA/strings.xml
core/res/res/values-fr/strings.xml
core/res/res/values-gl/strings.xml
core/res/res/values-gu/strings.xml
core/res/res/values-hi/strings.xml
core/res/res/values-hr/strings.xml
core/res/res/values-hu/strings.xml
core/res/res/values-hy/strings.xml
core/res/res/values-in/strings.xml
core/res/res/values-is/strings.xml
core/res/res/values-it/strings.xml
core/res/res/values-iw/strings.xml
core/res/res/values-ja/strings.xml
core/res/res/values-ka/strings.xml
core/res/res/values-kk/strings.xml
core/res/res/values-km/strings.xml
core/res/res/values-kn/strings.xml
core/res/res/values-ko/strings.xml
core/res/res/values-ky/strings.xml
core/res/res/values-lo/strings.xml
core/res/res/values-lt/strings.xml
core/res/res/values-lv/strings.xml
core/res/res/values-mcc310-mnc004/config.xml
core/res/res/values-mcc311-mnc480/config.xml
core/res/res/values-mk/strings.xml
core/res/res/values-ml/strings.xml
core/res/res/values-mn/strings.xml
core/res/res/values-mr/strings.xml
core/res/res/values-ms/strings.xml
core/res/res/values-my/strings.xml
core/res/res/values-nb/strings.xml
core/res/res/values-ne/strings.xml
core/res/res/values-nl/strings.xml
core/res/res/values-pa/strings.xml
core/res/res/values-pl/strings.xml
core/res/res/values-pt-rBR/strings.xml
core/res/res/values-pt-rPT/strings.xml
core/res/res/values-pt/strings.xml
core/res/res/values-ro/strings.xml
core/res/res/values-ru/strings.xml
core/res/res/values-si/strings.xml
core/res/res/values-sk/strings.xml
core/res/res/values-sl/strings.xml
core/res/res/values-sq/strings.xml
core/res/res/values-sr/strings.xml
core/res/res/values-sv/strings.xml
core/res/res/values-sw/strings.xml
core/res/res/values-ta/strings.xml
core/res/res/values-te/strings.xml
core/res/res/values-th/strings.xml
core/res/res/values-tl/strings.xml
core/res/res/values-tr/strings.xml
core/res/res/values-uk/strings.xml
core/res/res/values-ur/strings.xml
core/res/res/values-uz/strings.xml
core/res/res/values-vi/strings.xml
core/res/res/values-zh-rCN/strings.xml
core/res/res/values-zh-rHK/strings.xml
core/res/res/values-zh-rTW/strings.xml
core/res/res/values-zu/strings.xml
core/res/res/values/config.xml
core/res/res/values/strings.xml
core/res/res/values/symbols.xml
core/res/res/values/themes_device_defaults.xml
core/tests/coretests/src/android/content/pm/AppCacheTest.java
core/tests/coretests/src/android/provider/SettingsBackupTest.java
core/tests/coretests/src/android/widget/touchmode/TouchModeFocusableTest.java
core/tests/coretests/src/com/android/internal/app/procstats/SparseMappingTableTest.java
core/tests/coretests/src/com/android/internal/os/BatteryStatsBackgroundStatsTest.java
core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java [new file with mode: 0644]
core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
core/tests/coretests/src/com/android/internal/os/BatteryStatsTests.java
graphics/java/android/graphics/Paint.java
graphics/java/android/graphics/Typeface.java
graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
libs/hwui/renderthread/CanvasContext.cpp
location/java/android/location/CountryDetector.java
location/java/android/location/LocationManager.java
media/java/android/media/AudioManager.java
media/java/android/media/MediaCodec.java
media/java/android/media/MediaHTTPConnection.java
media/java/android/media/MediaRouter.java
media/java/android/media/MediaSync.java
media/java/android/media/midi/MidiManager.java
media/java/android/media/projection/MediaProjectionManager.java
media/java/android/media/session/MediaSessionManager.java
media/java/android/media/soundtrigger/SoundTriggerDetector.java
media/java/android/media/soundtrigger/SoundTriggerManager.java
media/java/android/media/tv/TvInputManager.java
media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/helpers/StaticMetadata.java
packages/CaptivePortalLogin/res/layout/activity_captive_portal_login.xml
packages/CaptivePortalLogin/res/values/styles.xml
packages/CaptivePortalLogin/src/com/android/captiveportallogin/CaptivePortalLoginActivity.java
packages/SettingsLib/res/layout/usage_view.xml
packages/SettingsLib/res/values-af/strings.xml
packages/SettingsLib/res/values-am/strings.xml
packages/SettingsLib/res/values-ar/strings.xml
packages/SettingsLib/res/values-az/strings.xml
packages/SettingsLib/res/values-b+sr+Latn/strings.xml
packages/SettingsLib/res/values-be/strings.xml
packages/SettingsLib/res/values-bg/strings.xml
packages/SettingsLib/res/values-bn/strings.xml
packages/SettingsLib/res/values-bs/strings.xml
packages/SettingsLib/res/values-ca/strings.xml
packages/SettingsLib/res/values-cs/strings.xml
packages/SettingsLib/res/values-da/strings.xml
packages/SettingsLib/res/values-de/strings.xml
packages/SettingsLib/res/values-el/strings.xml
packages/SettingsLib/res/values-en-rAU/strings.xml
packages/SettingsLib/res/values-en-rGB/strings.xml
packages/SettingsLib/res/values-en-rIN/strings.xml
packages/SettingsLib/res/values-es-rUS/strings.xml
packages/SettingsLib/res/values-es/strings.xml
packages/SettingsLib/res/values-et/strings.xml
packages/SettingsLib/res/values-eu/strings.xml
packages/SettingsLib/res/values-fa/strings.xml
packages/SettingsLib/res/values-fi/strings.xml
packages/SettingsLib/res/values-fr-rCA/strings.xml
packages/SettingsLib/res/values-fr/strings.xml
packages/SettingsLib/res/values-gl/strings.xml
packages/SettingsLib/res/values-gu/strings.xml
packages/SettingsLib/res/values-hi/strings.xml
packages/SettingsLib/res/values-hr/strings.xml
packages/SettingsLib/res/values-hu/strings.xml
packages/SettingsLib/res/values-hy/strings.xml
packages/SettingsLib/res/values-in/strings.xml
packages/SettingsLib/res/values-is/strings.xml
packages/SettingsLib/res/values-it/strings.xml
packages/SettingsLib/res/values-iw/strings.xml
packages/SettingsLib/res/values-ja/strings.xml
packages/SettingsLib/res/values-ka/strings.xml
packages/SettingsLib/res/values-kk/strings.xml
packages/SettingsLib/res/values-km/strings.xml
packages/SettingsLib/res/values-kn/strings.xml
packages/SettingsLib/res/values-ko/strings.xml
packages/SettingsLib/res/values-ky/strings.xml
packages/SettingsLib/res/values-lo/strings.xml
packages/SettingsLib/res/values-lt/strings.xml
packages/SettingsLib/res/values-lv/strings.xml
packages/SettingsLib/res/values-mk/strings.xml
packages/SettingsLib/res/values-ml/strings.xml
packages/SettingsLib/res/values-mn/strings.xml
packages/SettingsLib/res/values-mr/strings.xml
packages/SettingsLib/res/values-ms/strings.xml
packages/SettingsLib/res/values-my/strings.xml
packages/SettingsLib/res/values-nb/strings.xml
packages/SettingsLib/res/values-ne/strings.xml
packages/SettingsLib/res/values-nl/strings.xml
packages/SettingsLib/res/values-pa/strings.xml
packages/SettingsLib/res/values-pl/strings.xml
packages/SettingsLib/res/values-pt-rBR/strings.xml
packages/SettingsLib/res/values-pt-rPT/strings.xml
packages/SettingsLib/res/values-pt/strings.xml
packages/SettingsLib/res/values-ro/strings.xml
packages/SettingsLib/res/values-ru/strings.xml
packages/SettingsLib/res/values-si/strings.xml
packages/SettingsLib/res/values-sk/strings.xml
packages/SettingsLib/res/values-sl/strings.xml
packages/SettingsLib/res/values-sq/strings.xml
packages/SettingsLib/res/values-sr/strings.xml
packages/SettingsLib/res/values-sv/strings.xml
packages/SettingsLib/res/values-sw/strings.xml
packages/SettingsLib/res/values-ta/strings.xml
packages/SettingsLib/res/values-te/strings.xml
packages/SettingsLib/res/values-th/strings.xml
packages/SettingsLib/res/values-tl/strings.xml
packages/SettingsLib/res/values-tr/strings.xml
packages/SettingsLib/res/values-uk/strings.xml
packages/SettingsLib/res/values-ur/strings.xml
packages/SettingsLib/res/values-uz/strings.xml
packages/SettingsLib/res/values-vi/strings.xml
packages/SettingsLib/res/values-zh-rCN/strings.xml
packages/SettingsLib/res/values-zh-rHK/strings.xml
packages/SettingsLib/res/values-zh-rTW/strings.xml
packages/SettingsLib/res/values-zu/strings.xml
packages/SettingsLib/res/values/strings.xml
packages/SettingsLib/src/com/android/settingslib/applications/InterestingConfigChanges.java
packages/SettingsLib/src/com/android/settingslib/applications/StorageStatsSource.java
packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java [new file with mode: 0644]
packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java [new file with mode: 0644]
packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java [new file with mode: 0644]
packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
packages/Shell/src/com/android/shell/BugreportProgressService.java
packages/SystemUI/AndroidManifest.xml
packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
packages/SystemUI/res-keyguard/values-h560dp/dimens.xml
packages/SystemUI/res-keyguard/values-h650dp/dimens.xml
packages/SystemUI/res-keyguard/values/dimens.xml
packages/SystemUI/res/drawable/ic_qs_signal_1x.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_3g.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_4g.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_e.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_g.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_h.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_lte.xml [deleted file]
packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml [deleted file]
packages/SystemUI/res/layout/qs_detail.xml
packages/SystemUI/res/layout/qs_detail_header.xml
packages/SystemUI/res/layout/qs_detail_items.xml
packages/SystemUI/res/layout/qs_footer.xml
packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
packages/SystemUI/res/layout/status_bar_alarm_group.xml
packages/SystemUI/res/layout/zen_mode_panel.xml
packages/SystemUI/res/values-af/strings.xml
packages/SystemUI/res/values-am/strings.xml
packages/SystemUI/res/values-ar/strings.xml
packages/SystemUI/res/values-az/strings.xml
packages/SystemUI/res/values-b+sr+Latn/strings.xml
packages/SystemUI/res/values-be/strings.xml
packages/SystemUI/res/values-bg/strings.xml
packages/SystemUI/res/values-bn/strings.xml
packages/SystemUI/res/values-bs/strings.xml
packages/SystemUI/res/values-ca/strings.xml
packages/SystemUI/res/values-cs/strings.xml
packages/SystemUI/res/values-da/strings.xml
packages/SystemUI/res/values-de/strings.xml
packages/SystemUI/res/values-el/strings.xml
packages/SystemUI/res/values-en-rAU/strings.xml
packages/SystemUI/res/values-en-rGB/strings.xml
packages/SystemUI/res/values-en-rIN/strings.xml
packages/SystemUI/res/values-es-rUS/strings.xml
packages/SystemUI/res/values-es/strings.xml
packages/SystemUI/res/values-et/strings.xml
packages/SystemUI/res/values-eu/strings.xml
packages/SystemUI/res/values-fa/strings.xml
packages/SystemUI/res/values-fi/strings.xml
packages/SystemUI/res/values-fr-rCA/strings.xml
packages/SystemUI/res/values-fr/strings.xml
packages/SystemUI/res/values-gl/strings.xml
packages/SystemUI/res/values-gu/strings.xml
packages/SystemUI/res/values-hi/strings.xml
packages/SystemUI/res/values-hr/strings.xml
packages/SystemUI/res/values-hu/strings.xml
packages/SystemUI/res/values-hy/strings.xml
packages/SystemUI/res/values-hy/strings_tv.xml
packages/SystemUI/res/values-in/strings.xml
packages/SystemUI/res/values-is/strings.xml
packages/SystemUI/res/values-it/strings.xml
packages/SystemUI/res/values-iw/strings.xml
packages/SystemUI/res/values-ja/strings.xml
packages/SystemUI/res/values-ka/strings.xml
packages/SystemUI/res/values-kk/strings.xml
packages/SystemUI/res/values-km/strings.xml
packages/SystemUI/res/values-kn/strings.xml
packages/SystemUI/res/values-ko/strings.xml
packages/SystemUI/res/values-ky/strings.xml
packages/SystemUI/res/values-lo/strings.xml
packages/SystemUI/res/values-lt/strings.xml
packages/SystemUI/res/values-lv/strings.xml
packages/SystemUI/res/values-mk/strings.xml
packages/SystemUI/res/values-ml/strings.xml
packages/SystemUI/res/values-mn/strings.xml
packages/SystemUI/res/values-mr/strings.xml
packages/SystemUI/res/values-ms/strings.xml
packages/SystemUI/res/values-my/strings.xml
packages/SystemUI/res/values-nb/strings.xml
packages/SystemUI/res/values-ne/strings.xml
packages/SystemUI/res/values-nl/strings.xml
packages/SystemUI/res/values-pa/strings.xml
packages/SystemUI/res/values-pl/strings.xml
packages/SystemUI/res/values-pt-rBR/strings.xml
packages/SystemUI/res/values-pt-rPT/strings.xml
packages/SystemUI/res/values-pt/strings.xml
packages/SystemUI/res/values-ro/strings.xml
packages/SystemUI/res/values-ru/strings.xml
packages/SystemUI/res/values-si/strings.xml
packages/SystemUI/res/values-sk/strings.xml
packages/SystemUI/res/values-sl/strings.xml
packages/SystemUI/res/values-sq/strings.xml
packages/SystemUI/res/values-sr/strings.xml
packages/SystemUI/res/values-sv/strings.xml
packages/SystemUI/res/values-sw/strings.xml
packages/SystemUI/res/values-ta/strings.xml
packages/SystemUI/res/values-te/strings.xml
packages/SystemUI/res/values-th/strings.xml
packages/SystemUI/res/values-tl/strings.xml
packages/SystemUI/res/values-tr/strings.xml
packages/SystemUI/res/values-uk/strings.xml
packages/SystemUI/res/values-ur/strings.xml
packages/SystemUI/res/values-uz/strings.xml
packages/SystemUI/res/values-vi/strings.xml
packages/SystemUI/res/values-zh-rCN/strings.xml
packages/SystemUI/res/values-zh-rHK/strings.xml
packages/SystemUI/res/values-zh-rTW/strings.xml
packages/SystemUI/res/values-zu/strings.xml
packages/SystemUI/res/values/dimens.xml
packages/SystemUI/res/values/styles.xml
packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
packages/SystemUI/src/com/android/systemui/Dependency.java
packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java [new file with mode: 0644]
packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java [new file with mode: 0644]
packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
packages/SystemUI/src/com/android/systemui/pip/tv/PipManager.java
packages/SystemUI/src/com/android/systemui/plugins/PluginManagerImpl.java
packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
packages/SystemUI/src/com/android/systemui/qs/QuickQSPanel.java
packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
packages/SystemUI/src/com/android/systemui/recents/views/AnimationProps.java
packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java [new file with mode: 0644]
packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
packages/SystemUI/src/com/android/systemui/recents/views/RecentsViewTouchHandler.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
packages/SystemUI/src/com/android/systemui/recents/views/TaskViewAccessibilityDelegate.java
packages/SystemUI/src/com/android/systemui/stackdivider/Divider.java
packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
packages/SystemUI/src/com/android/systemui/stackdivider/ForcedResizableInfoActivityController.java
packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigPictureTemplateViewWrapper.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationBigTextTemplateViewWrapper.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationHeaderViewWrapper.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationInflater.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMediaTemplateViewWrapper.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationTemplateViewWrapper.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
packages/SystemUI/src/com/android/systemui/statusbar/notification/VisualStabilityManager.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconContainer.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonRipple.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/TelephonyIcons.java
packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/AmbientState.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
packages/SystemUI/src/com/android/systemui/util/Utils.java [new file with mode: 0644]
packages/SystemUI/src/com/android/systemui/volume/VolumeDialogComponent.java
packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java [new file with mode: 0644]
packages/SystemUI/tests/src/com/android/systemui/SysuiBaseFragmentTest.java
packages/SystemUI/tests/src/com/android/systemui/SysuiTestCase.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/ExpandableNotificationRowTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationCustomViewWrapperTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/SignalClusterViewTest.java [new file with mode: 0644]
packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/NotificationViewWrapperTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CallbackHandlerTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerDataTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerSignalTest.java
packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java [new file with mode: 0644]
packages/SystemUI/tests/src/com/android/systemui/statusbar/stack/NotificationChildrenContainerTest.java
packages/SystemUI/tests/src/com/android/systemui/util/wakelock/WakeLockTest.java
proto/src/metrics_constants.proto
services/autofill/java/com/android/server/autofill/AutofillManagerService.java
services/autofill/java/com/android/server/autofill/AutofillManagerServiceImpl.java
services/autofill/java/com/android/server/autofill/Session.java
services/autofill/java/com/android/server/autofill/ViewState.java
services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
services/autofill/java/com/android/server/autofill/ui/FillUi.java
services/autofill/java/com/android/server/autofill/ui/SaveUi.java
services/core/java/com/android/server/EventLogTags.logtags
services/core/java/com/android/server/StorageManagerService.java
services/core/java/com/android/server/VibratorService.java
services/core/java/com/android/server/Watchdog.java
services/core/java/com/android/server/accounts/AccountManagerService.java
services/core/java/com/android/server/am/ActiveServices.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/ActivityManagerShellCommand.java
services/core/java/com/android/server/am/ActivityRecord.java
services/core/java/com/android/server/am/ActivityStack.java
services/core/java/com/android/server/am/ActivityStackSupervisor.java
services/core/java/com/android/server/am/ActivityStarter.java
services/core/java/com/android/server/am/BatteryStatsService.java
services/core/java/com/android/server/am/KeyguardController.java
services/core/java/com/android/server/am/PinnedActivityStack.java
services/core/java/com/android/server/am/ProcessStatsService.java
services/core/java/com/android/server/am/ProviderMap.java
services/core/java/com/android/server/am/TaskChangeNotificationController.java
services/core/java/com/android/server/am/TaskRecord.java
services/core/java/com/android/server/connectivity/Tethering.java
services/core/java/com/android/server/connectivity/tethering/TetheringConfiguration.java
services/core/java/com/android/server/content/SyncManager.java
services/core/java/com/android/server/display/DisplayPowerController.java
services/core/java/com/android/server/display/DisplayPowerState.java
services/core/java/com/android/server/display/NightDisplayService.java
services/core/java/com/android/server/dreams/DreamManagerService.java
services/core/java/com/android/server/notification/ManagedServices.java
services/core/java/com/android/server/notification/NotificationManagerService.java
services/core/java/com/android/server/notification/NotificationRecord.java
services/core/java/com/android/server/notification/RankingHelper.java
services/core/java/com/android/server/pm/DefaultPermissionGrantPolicy.java
services/core/java/com/android/server/pm/Installer.java
services/core/java/com/android/server/pm/InstantAppRegistry.java
services/core/java/com/android/server/pm/LauncherAppsService.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/policy/AccessibilityShortcutController.java
services/core/java/com/android/server/policy/PhoneWindowManager.java
services/core/java/com/android/server/policy/WindowOrientationListener.java
services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
services/core/java/com/android/server/power/PowerManagerService.java
services/core/java/com/android/server/storage/DeviceStorageMonitorService.java
services/core/java/com/android/server/storage/FileCollector.java
services/core/java/com/android/server/vr/VrManagerService.java
services/core/java/com/android/server/wm/AlertWindowNotification.java
services/core/java/com/android/server/wm/AppTransition.java
services/core/java/com/android/server/wm/AppWindowContainerController.java
services/core/java/com/android/server/wm/AppWindowToken.java
services/core/java/com/android/server/wm/DisplayContent.java
services/core/java/com/android/server/wm/PinnedStackController.java
services/core/java/com/android/server/wm/PinnedStackWindowController.java
services/core/java/com/android/server/wm/Task.java
services/core/java/com/android/server/wm/TaskSnapshotController.java
services/core/java/com/android/server/wm/TaskSnapshotSurface.java
services/core/java/com/android/server/wm/TaskStack.java
services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
services/core/java/com/android/server/wm/WindowManagerDebugConfig.java
services/core/java/com/android/server/wm/WindowManagerService.java
services/core/java/com/android/server/wm/WindowState.java
services/core/java/com/android/server/wm/WindowStateAnimator.java
services/core/java/com/android/server/wm/WindowSurfacePlacer.java
services/java/com/android/server/SystemServer.java
services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
services/tests/notification/src/com/android/server/notification/NotificationRecordTest.java
services/tests/notification/src/com/android/server/notification/RankingHelperTest.java
services/tests/servicestests/AndroidManifest.xml
services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java
services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTestFixtures.java
services/tests/servicestests/src/com/android/server/accounts/TestAccountType1Authenticator.java
services/tests/servicestests/src/com/android/server/am/ActivityTestsBase.java
services/tests/servicestests/src/com/android/server/wm/UnknownAppVisibilityControllerTest.java
services/tests/servicestests/src/com/android/server/wm/WindowStateTests.java
services/usage/java/com/android/server/usage/StorageStatsService.java
services/usb/java/com/android/server/usb/UsbDeviceManager.java
services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionSessionConnection.java
telecomm/java/android/telecom/TelecomManager.java
telephony/java/android/telephony/CarrierConfigManager.java
telephony/java/android/telephony/PhoneNumberUtils.java
telephony/java/android/telephony/SmsManager.java
telephony/java/android/telephony/SubscriptionManager.java
telephony/java/android/telephony/TelephonyManager.java
tests/MusicServiceDemo/src/com/example/android/musicservicedemo/MainActivity.java
tests/TouchLatency/app/src/main/java/com/prefabulated/touchlatency/TouchLatencyActivity.java
tests/net/java/com/android/server/connectivity/TetheringTest.java
tests/testables/src/android/testing/ViewUtils.java
tools/aapt2/Android.bp
tools/aapt2/Format.proto
tools/aapt2/ResourceParser.cpp
tools/aapt2/ResourceParser.h
tools/aapt2/ResourceParser_test.cpp
tools/aapt2/ResourceTable.cpp
tools/aapt2/ResourceTable.h
tools/aapt2/ResourceUtils.cpp
tools/aapt2/ResourceUtils.h
tools/aapt2/ResourceUtils_test.cpp
tools/aapt2/ResourceValues.cpp
tools/aapt2/ResourceValues.h
tools/aapt2/ResourceValues_test.cpp
tools/aapt2/cmd/Compile.cpp
tools/aapt2/cmd/Link.cpp
tools/aapt2/integration-tests/AppOne/res/values/test.xml
tools/aapt2/integration-tests/SymlinkTest/Android.mk [new file with mode: 0644]
tools/aapt2/integration-tests/SymlinkTest/AndroidManifest.xml [new file with mode: 0644]
tools/aapt2/integration-tests/SymlinkTest/res/drawable/white_3x3.9.png [new symlink]
tools/aapt2/integration-tests/SymlinkTest/res/layout/layout.xml [new symlink]
tools/aapt2/integration-tests/SymlinkTest/res/values/values.xml [new symlink]
tools/aapt2/integration-tests/SymlinkTest/targets/layout.xml [new file with mode: 0644]
tools/aapt2/integration-tests/SymlinkTest/targets/values.xml [new file with mode: 0644]
tools/aapt2/integration-tests/SymlinkTest/targets/white_3x3.9.png [new file with mode: 0644]
tools/aapt2/link/ReferenceLinker.cpp
tools/aapt2/link/TableMerger.cpp
tools/aapt2/link/TableMerger_test.cpp
tools/aapt2/proto/TableProtoDeserializer.cpp
tools/aapt2/proto/TableProtoSerializer.cpp
tools/aapt2/proto/TableProtoSerializer_test.cpp
tools/aapt2/readme.md
tools/aapt2/test/Builders.h
tools/aapt2/test/Common.cpp [new file with mode: 0644]
tools/aapt2/test/Common.h
tools/aapt2/test/Test.h
tools/aapt2/util/Files.cpp
tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
wifi/java/android/net/wifi/RttManager.java
wifi/java/android/net/wifi/WifiConfiguration.java
wifi/java/android/net/wifi/WifiManager.java
wifi/java/android/net/wifi/WifiScanner.java
wifi/java/android/net/wifi/aware/WifiAwareManager.java
wifi/java/android/net/wifi/hotspot2/PasspointConfiguration.java
wifi/java/android/net/wifi/hotspot2/pps/Credential.java
wifi/java/android/net/wifi/hotspot2/pps/HomeSp.java
wifi/java/android/net/wifi/p2p/WifiP2pManager.java
wifi/tests/src/android/net/wifi/WifiManagerTest.java

index b5f8cb0..3f2ae83 100644 (file)
@@ -923,6 +923,7 @@ framework_docs_LOCAL_DROIDDOC_OPTIONS := \
     -android \
     -knowntags ./frameworks/base/docs/knowntags.txt \
     -knowntags ./libcore/known_oj_tags.txt \
+    -manifest ./frameworks/base/core/res/AndroidManifest.xml \
     -hidePackage com.android.org.conscrypt \
     -since $(SRC_API_DIR)/1.xml 1 \
     -since $(SRC_API_DIR)/2.xml 2 \
index 6023aab..ac97b54 100644 (file)
@@ -26513,7 +26513,6 @@ package android.net.wifi {
     method public boolean isTdlsSupported();
     method public boolean isWifiEnabled();
     method public deprecated boolean pingSupplicant();
-    method public void queryPasspointIcon(long, java.lang.String);
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
@@ -26526,29 +26525,17 @@ package android.net.wifi {
     method public boolean startScan();
     method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
-    field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
-    field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
-    field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
-    field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
-    field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
     field public static final java.lang.String EXTRA_BSSID = "bssid";
-    field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
-    field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
-    field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
-    field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
-    field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
-    field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
-    field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
     field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
@@ -33907,7 +33894,6 @@ package android.provider {
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_NAME = "android.provider.extra.RECIPIENT_CONTACT_NAME";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_URI = "android.provider.extra.RECIPIENT_CONTACT_URI";
-    field public static final java.lang.String EXTRA_SENDER_ACCOUNT_HASH = "android.provider.extra.SENDER_ACCOUNT_HASH";
     field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT";
     field public static final java.lang.String METADATA_ACCOUNT_TYPE = "android.provider.account_type";
     field public static final java.lang.String METADATA_MIMETYPE = "android.provider.mimetype";
index 67b6e82..a2c2771 100644 (file)
@@ -29038,7 +29038,6 @@ package android.net.wifi {
     method public boolean isWifiEnabled();
     method public boolean isWifiScannerSupported();
     method public deprecated boolean pingSupplicant();
-    method public void queryPasspointIcon(long, java.lang.String);
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
@@ -29055,10 +29054,6 @@ package android.net.wifi {
     method public boolean startScan(android.os.WorkSource);
     method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
-    field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
-    field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
-    field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
-    field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int CHANGE_REASON_ADDED = 0; // 0x0
@@ -29066,14 +29061,8 @@ package android.net.wifi {
     field public static final int CHANGE_REASON_REMOVED = 1; // 0x1
     field public static final java.lang.String CONFIGURED_NETWORKS_CHANGED_ACTION = "android.net.wifi.CONFIGURED_NETWORKS_CHANGE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
-    field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
     field public static final java.lang.String EXTRA_BSSID = "bssid";
-    field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
     field public static final java.lang.String EXTRA_CHANGE_REASON = "changeReason";
-    field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
-    field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
-    field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
-    field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
     field public static final java.lang.String EXTRA_MULTIPLE_NETWORKS_CHANGED = "multipleChanges";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
@@ -29081,10 +29070,8 @@ package android.net.wifi {
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_AP_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
-    field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
-    field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
     field public static final java.lang.String EXTRA_WIFI_AP_STATE = "wifi_state";
     field public static final java.lang.String EXTRA_WIFI_CONFIGURATION = "wifiConfiguration";
     field public static final java.lang.String EXTRA_WIFI_CREDENTIAL_EVENT_TYPE = "et";
@@ -36821,7 +36808,6 @@ package android.provider {
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_NAME = "android.provider.extra.RECIPIENT_CONTACT_NAME";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_URI = "android.provider.extra.RECIPIENT_CONTACT_URI";
-    field public static final java.lang.String EXTRA_SENDER_ACCOUNT_HASH = "android.provider.extra.SENDER_ACCOUNT_HASH";
     field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT";
     field public static final java.lang.String METADATA_ACCOUNT_TYPE = "android.provider.account_type";
     field public static final java.lang.String METADATA_MIMETYPE = "android.provider.mimetype";
index d3cb4c9..9b5b1a2 100644 (file)
@@ -26622,7 +26622,6 @@ package android.net.wifi {
     method public boolean isTdlsSupported();
     method public boolean isWifiEnabled();
     method public deprecated boolean pingSupplicant();
-    method public void queryPasspointIcon(long, java.lang.String);
     method public boolean reassociate();
     method public boolean reconnect();
     method public boolean removeNetwork(int);
@@ -26635,29 +26634,17 @@ package android.net.wifi {
     method public boolean startScan();
     method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsCallback);
     method public int updateNetwork(android.net.wifi.WifiConfiguration);
-    field public static final java.lang.String ACTION_PASSPOINT_DEAUTH_IMMINENT = "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
-    field public static final java.lang.String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
-    field public static final java.lang.String ACTION_PASSPOINT_OSU_PROVIDERS_LIST = "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
-    field public static final java.lang.String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION = "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
     field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
     field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
     field public static final int ERROR_AUTHENTICATING = 1; // 0x1
-    field public static final java.lang.String EXTRA_ANQP_ELEMENT_DATA = "android.net.wifi.extra.ANQP_ELEMENT_DATA";
     field public static final java.lang.String EXTRA_BSSID = "bssid";
-    field public static final java.lang.String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
-    field public static final java.lang.String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
-    field public static final java.lang.String EXTRA_ESS = "android.net.wifi.extra.ESS";
-    field public static final java.lang.String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
-    field public static final java.lang.String EXTRA_ICON = "android.net.wifi.extra.ICON";
     field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
     field public static final java.lang.String EXTRA_NEW_RSSI = "newRssi";
     field public static final java.lang.String EXTRA_NEW_STATE = "newState";
     field public static final java.lang.String EXTRA_PREVIOUS_WIFI_STATE = "previous_wifi_state";
     field public static final java.lang.String EXTRA_RESULTS_UPDATED = "resultsUpdated";
-    field public static final java.lang.String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD = "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
     field public static final java.lang.String EXTRA_SUPPLICANT_CONNECTED = "connected";
     field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
-    field public static final java.lang.String EXTRA_URL = "android.net.wifi.extra.URL";
     field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
     field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
     field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
@@ -34044,7 +34031,6 @@ package android.provider {
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_CHAT_ID = "android.provider.extra.RECIPIENT_CONTACT_CHAT_ID";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_NAME = "android.provider.extra.RECIPIENT_CONTACT_NAME";
     field public static final java.lang.String EXTRA_RECIPIENT_CONTACT_URI = "android.provider.extra.RECIPIENT_CONTACT_URI";
-    field public static final java.lang.String EXTRA_SENDER_ACCOUNT_HASH = "android.provider.extra.SENDER_ACCOUNT_HASH";
     field public static final java.lang.String INVITE_CONTACT = "com.android.contacts.action.INVITE_CONTACT";
     field public static final java.lang.String METADATA_ACCOUNT_TYPE = "android.provider.account_type";
     field public static final java.lang.String METADATA_MIMETYPE = "android.provider.mimetype";
@@ -45743,6 +45729,7 @@ package android.view {
     method public boolean isAttachedToWindow();
     method public boolean isClickable();
     method public boolean isContextClickable();
+    method public boolean isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable);
     method public boolean isDirty();
     method public boolean isDrawingCacheEnabled();
     method public boolean isDuplicateParentStateEnabled();
@@ -47125,6 +47112,7 @@ package android.view {
     method public void setColorMode(int);
     method public final void setTitle(java.lang.CharSequence);
     method public void writeToParcel(android.os.Parcel, int);
+    field public static final int ACCESSIBILITY_TITLE_CHANGED = 33554432; // 0x2000000
     field public static final int ALPHA_CHANGED = 128; // 0x80
     field public static final int ANIMATION_CHANGED = 16; // 0x10
     field public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
@@ -47226,6 +47214,7 @@ package android.view {
     field public static final deprecated int TYPE_SYSTEM_OVERLAY = 2006; // 0x7d6
     field public static final deprecated int TYPE_TOAST = 2005; // 0x7d5
     field public static final int TYPE_WALLPAPER = 2013; // 0x7dd
+    field public java.lang.CharSequence accessibilityTitle;
     field public float alpha;
     field public float buttonBrightness;
     field public float dimAmount;
index b60aed6..d71573f 100644 (file)
@@ -63,6 +63,7 @@ import android.os.ShellCallback;
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.os.storage.StorageManager;
 import android.text.TextUtils;
 import android.text.format.DateUtils;
 import android.util.Log;
@@ -1471,7 +1472,8 @@ public final class Pm {
         }
         ClearDataObserver obs = new ClearDataObserver();
         try {
-            mPm.freeStorageAndNotify(volumeUuid, sizeVal, obs);
+            mPm.freeStorageAndNotify(volumeUuid, sizeVal,
+                    StorageManager.FLAG_ALLOCATE_DEFY_RESERVED, obs);
             synchronized (obs) {
                 while (!obs.finished) {
                     try {
index 8fd8043..a446296 100644 (file)
@@ -24,6 +24,7 @@ import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.Size;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.BroadcastBehavior;
 import android.app.Activity;
@@ -161,6 +162,7 @@ import java.util.concurrent.TimeoutException;
  * the application's main event thread.  These operations throw
  * {@link IllegalStateException} if they are used on the main thread.
  */
+@SystemService(Context.ACCOUNT_SERVICE)
 public class AccountManager {
 
     private static final String TAG = "AccountManager";
@@ -2509,6 +2511,18 @@ public class AccountManager {
         return new AuthenticatorException(message);
     }
 
+    private void getAccountByTypeAndFeatures(String accountType, String[] features,
+        AccountManagerCallback<Bundle> callback, Handler handler) {
+        (new AmsTask(null, handler, callback) {
+            @Override
+            public void doWork() throws RemoteException {
+                mService.getAccountByTypeAndFeatures(mResponse, accountType, features,
+                    mContext.getOpPackageName());
+            }
+
+        }).start();
+    }
+
     private class GetAuthTokenByTypeAndFeaturesTask
             extends AmsTask implements AccountManagerCallback<Bundle> {
         GetAuthTokenByTypeAndFeaturesTask(final String accountType, final String authTokenType,
@@ -2535,13 +2549,16 @@ public class AccountManager {
 
         @Override
         public void doWork() throws RemoteException {
-            getAccountsByTypeAndFeatures(mAccountType, mFeatures,
-                    new AccountManagerCallback<Account[]>() {
+            getAccountByTypeAndFeatures(mAccountType, mFeatures,
+                    new AccountManagerCallback<Bundle>() {
                         @Override
-                        public void run(AccountManagerFuture<Account[]> future) {
-                            Account[] accounts;
+                        public void run(AccountManagerFuture<Bundle> future) {
+                            String accountName = null;
+                            String accountType = null;
                             try {
-                                accounts = future.getResult();
+                                Bundle result = future.getResult();
+                                accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+                                accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
                             } catch (OperationCanceledException e) {
                                 setException(e);
                                 return;
@@ -2553,9 +2570,7 @@ public class AccountManager {
                                 return;
                             }
 
-                            mNumAccounts = accounts.length;
-
-                            if (accounts.length == 0) {
+                            if (accountName == null) {
                                 if (mActivity != null) {
                                     // no accounts, add one now. pretend that the user directly
                                     // made this request
@@ -2575,63 +2590,17 @@ public class AccountManager {
                                     }
                                     // we are done
                                 }
-                            } else if (accounts.length == 1) {
+                            } else {
+                                mNumAccounts = 1;
+                                Account account = new Account(accountName, accountType);
                                 // have a single account, return an authtoken for it
                                 if (mActivity == null) {
-                                    mFuture = getAuthToken(accounts[0], mAuthTokenType,
+                                    mFuture = getAuthToken(account, mAuthTokenType,
                                             false /* notifyAuthFailure */, mMyCallback, mHandler);
                                 } else {
-                                    mFuture = getAuthToken(accounts[0],
-                                            mAuthTokenType, mLoginOptions,
+                                    mFuture = getAuthToken(account, mAuthTokenType, mLoginOptions,
                                             mActivity, mMyCallback, mHandler);
                                 }
-                            } else {
-                                if (mActivity != null) {
-                                    IAccountManagerResponse chooseResponse =
-                                            new IAccountManagerResponse.Stub() {
-                                        @Override
-                                        public void onResult(Bundle value) throws RemoteException {
-                                            Account account = new Account(
-                                                    value.getString(KEY_ACCOUNT_NAME),
-                                                    value.getString(KEY_ACCOUNT_TYPE),
-                                                    value.getString(KEY_ACCOUNT_ACCESS_ID));
-                                            mFuture = getAuthToken(account, mAuthTokenType,
-                                                    mLoginOptions,  mActivity, mMyCallback,
-                                                    mHandler);
-                                        }
-
-                                        @Override
-                                        public void onError(int errorCode, String errorMessage)
-                                                throws RemoteException {
-                                            mResponse.onError(errorCode, errorMessage);
-                                        }
-                                    };
-                                    // have many accounts, launch the chooser
-                                    Intent intent = new Intent();
-                                    // TODO - this activity will not include
-                                    // USER_MANAGED_NOT_VISIBLE
-                                    // accounts. We need to move method to service
-                                    ComponentName componentName = ComponentName.unflattenFromString(
-                                            Resources.getSystem().getString(
-                                                    R.string.config_chooseAccountActivity));
-                                    intent.setClassName(componentName.getPackageName(),
-                                            componentName.getClassName());
-                                    intent.putExtra(KEY_ACCOUNTS, accounts);
-                                    intent.putExtra(KEY_ACCOUNT_MANAGER_RESPONSE,
-                                            new AccountManagerResponse(chooseResponse));
-                                    mActivity.startActivity(intent);
-                                    // the result will arrive via the IAccountManagerResponse
-                                } else {
-                                    // send result since we can't prompt to select an account
-                                    Bundle result = new Bundle();
-                                    result.putString(KEY_ACCOUNTS, null);
-                                    try {
-                                        mResponse.onResult(result);
-                                    } catch (RemoteException e) {
-                                        // this will never happen
-                                    }
-                                    // we are done
-                                }
                             }
                         }}, mHandler);
         }
@@ -2721,8 +2690,8 @@ public class AccountManager {
     public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
             final String accountType, final String authTokenType, final String[] features,
             final Activity activity, final Bundle addAccountOptions,
-            final Bundle getAuthTokenOptions,
-            final AccountManagerCallback<Bundle> callback, final Handler handler) {
+            final Bundle getAuthTokenOptions, final AccountManagerCallback<Bundle> callback,
+            final Handler handler) {
         if (accountType == null) throw new IllegalArgumentException("account type is null");
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
         final GetAuthTokenByTypeAndFeaturesTask task =
@@ -3237,6 +3206,7 @@ public class AccountManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public AccountManagerFuture<Bundle> finishSessionAsUser(
             final Bundle sessionBundle,
             final Activity activity,
index 7494cfc..4cf0a20 100644 (file)
@@ -40,6 +40,8 @@ interface IAccountManager {
     Account[] getAccountsAsUser(String accountType, int userId, String opPackageName);
     void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features,
         String opPackageName);
+    void getAccountByTypeAndFeatures(in IAccountManagerResponse response, String accountType,
+        in String[] features, String opPackageName);
     void getAccountsByFeatures(in IAccountManagerResponse response, String accountType,
         in String[] features, String opPackageName);
     boolean addAccountExplicitly(in Account account, String password, in Bundle extras);
index e2e5a8f..260323f 100644 (file)
@@ -136,7 +136,8 @@ public class AnimationHandler {
 
     private void doAnimationFrame(long frameTime) {
         long currentTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < mAnimationCallbacks.size(); i++) {
+        final int size = mAnimationCallbacks.size();
+        for (int i = 0; i < size; i++) {
             final AnimationFrameCallback callback = mAnimationCallbacks.get(i);
             if (callback == null) {
                 continue;
index 38ce427..854e531 100644 (file)
@@ -473,9 +473,13 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
             if (mReversing) {
                 // Between start() and first frame, mLastEventId would be unset (i.e. -1)
                 mLastEventId = mLastEventId == -1 ? mEvents.size() : mLastEventId;
-                for (int j = mLastEventId - 1; j >= 0; j--) {
-                    AnimationEvent event = mEvents.get(j);
+                while (mLastEventId > 0) {
+                    mLastEventId = mLastEventId - 1;
+                    AnimationEvent event = mEvents.get(mLastEventId);
                     Animator anim = event.mNode.mAnimation;
+                    if (mNodeMap.get(anim).mEnded) {
+                        continue;
+                    }
                     if (event.mEvent == AnimationEvent.ANIMATION_END) {
                         anim.reverse();
                     } else if (event.mEvent == AnimationEvent.ANIMATION_DELAY_ENDED
@@ -487,9 +491,15 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
                     }
                 }
             } else {
-                for (int j = mLastEventId + 1; j < mEvents.size(); j++) {
-                    AnimationEvent event = mEvents.get(j);
+                while (mLastEventId < mEvents.size() - 1) {
+                    // Avoid potential reentrant loop caused by child animators manipulating
+                    // AnimatorSet's lifecycle (i.e. not a recommended approach).
+                    mLastEventId = mLastEventId + 1;
+                    AnimationEvent event = mEvents.get(mLastEventId);
                     Animator anim = event.mNode.mAnimation;
+                    if (mNodeMap.get(anim).mEnded) {
+                        continue;
+                    }
                     if (event.mEvent == AnimationEvent.ANIMATION_START) {
                         anim.start();
                     } else if (event.mEvent == AnimationEvent.ANIMATION_END && anim.isStarted()) {
@@ -663,6 +673,10 @@ public final class AnimatorSet extends Animator implements AnimationHandler.Anim
      * <p>Starting this <code>AnimatorSet</code> will, in turn, start the animations for which
      * it is responsible. The details of when exactly those animations are started depends on
      * the dependency relationships that have been set up between the animations.
+     *
+     * <b>Note:</b> Manipulating AnimatorSet's lifecycle in the child animators' listener callbacks
+     * will lead to undefined behaviors. Also, AnimatorSet will ignore any seeking in the child
+     * animators once {@link #start()} is called.
      */
     @SuppressWarnings("unchecked")
     @Override
index 4e31e44..e686a89 100644 (file)
@@ -1397,7 +1397,7 @@ public class ValueAnimator extends Animator implements AnimationHandler.Animatio
         if (mStartTime < 0) {
             // First frame. If there is start delay, start delay count down will happen *after* this
             // frame.
-            mStartTime = mReversing ? frameTime : frameTime + mStartDelay;
+            mStartTime = mReversing ? frameTime : frameTime + (long) (mStartDelay * sDurationScale);
         }
 
         // Handle pause/resume
diff --git a/core/java/android/annotation/SystemService.java b/core/java/android/annotation/SystemService.java
new file mode 100644 (file)
index 0000000..ba5002a
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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.annotation;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+import android.content.Context;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Description of a system service available through
+ * {@link Context#getSystemService(Class)}.
+ *
+ * @hide
+ */
+@Retention(SOURCE)
+@Target(TYPE)
+public @interface SystemService {
+    String value();
+}
index b439c1d..3574f8d 100644 (file)
@@ -5790,6 +5790,7 @@ public class Activity extends ContextThemeWrapper
      *
      * @return True if this is the root activity, else false.
      */
+    @Override
     public boolean isTaskRoot() {
         try {
             return ActivityManager.getService().getTaskForActivity(mToken, true) >= 0;
@@ -6142,6 +6143,7 @@ public class Activity extends ContextThemeWrapper
      *
      * @param action the action to run on the UI thread
      */
+    @Override
     public final void runOnUiThread(Runnable action) {
         if (Thread.currentThread() != mUiThread) {
             mHandler.post(action);
@@ -7206,6 +7208,9 @@ public class Activity extends ContextThemeWrapper
                 "dispatchPictureInPictureModeChanged " + this + ": " + isInPictureInPictureMode
                         + " " + newConfig);
         mFragments.dispatchPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
+        if (mWindow != null) {
+            mWindow.onPictureInPictureModeChanged(isInPictureInPictureMode);
+        }
         onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig);
     }
 
index 0925217..f398c8d 100644 (file)
@@ -22,6 +22,7 @@ import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -117,6 +118,7 @@ import java.util.List;
  * be used for testing and debugging purposes only.
  * </p>
  */
+@SystemService(Context.ACTIVITY_SERVICE)
 public class ActivityManager {
     private static String TAG = "ActivityManager";
 
@@ -301,6 +303,19 @@ public class ActivityManager {
     public static final int START_INTENT_NOT_RESOLVED = FIRST_START_FATAL_ERROR_CODE + 9;
 
     /**
+     * Result for IActivityManager.startAssistantActivity: active session is currently hidden.
+     * @hide
+     */
+    public static final int START_ASSISTANT_HIDDEN_SESSION = FIRST_START_FATAL_ERROR_CODE + 10;
+
+    /**
+     * Result for IActivityManager.startAssistantActivity: active session does not match
+     * the requesting token.
+     * @hide
+     */
+    public static final int START_ASSISTANT_NOT_ACTIVE_SESSION = FIRST_START_FATAL_ERROR_CODE + 11;
+
+    /**
      * Result for IActivityManaqer.startActivity: the activity was started
      * successfully as normal.
      * @hide
@@ -1139,8 +1154,12 @@ public class ActivityManager {
      * E.g. freeform, split-screen, picture-in-picture.
      * @hide
      */
-    static public boolean supportsMultiWindow() {
-        return !isLowRamDeviceStatic()
+    static public boolean supportsMultiWindow(Context context) {
+        // On watches, multi-window is used to present essential system UI, and thus it must be
+        // supported regardless of device memory characteristics.
+        boolean isWatch = context.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_WATCH);
+        return (!isLowRamDeviceStatic() || isWatch)
                 && Resources.getSystem().getBoolean(
                     com.android.internal.R.bool.config_supportsMultiWindow);
     }
@@ -1149,8 +1168,8 @@ public class ActivityManager {
      * Returns true if the system supports split screen multi-window.
      * @hide
      */
-    static public boolean supportsSplitScreenMultiWindow() {
-        return supportsMultiWindow()
+    static public boolean supportsSplitScreenMultiWindow(Context context) {
+        return supportsMultiWindow(context)
                 && Resources.getSystem().getBoolean(
                     com.android.internal.R.bool.config_supportsSplitScreenMultiWindow);
     }
@@ -3593,6 +3612,7 @@ public class ActivityManager {
      * @hide
      */
     @SystemApi @TestApi
+    @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public void addOnUidImportanceListener(OnUidImportanceListener listener,
             @RunningAppProcessInfo.Importance int importanceCutpoint) {
         synchronized (this) {
@@ -3621,6 +3641,7 @@ public class ActivityManager {
      * @hide
      */
     @SystemApi @TestApi
+    @RequiresPermission(Manifest.permission.PACKAGE_USAGE_STATS)
     public void removeOnUidImportanceListener(OnUidImportanceListener listener) {
         synchronized (this) {
             UidObserver observer = mImportanceListeners.remove(listener);
@@ -3988,6 +4009,10 @@ public class ActivityManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            "android.permission.INTERACT_ACROSS_USERS",
+            "android.permission.INTERACT_ACROSS_USERS_FULL"
+    })
     public static int getCurrentUser() {
         UserInfo ui;
         try {
index 53608fb..cbb93a0 100644 (file)
@@ -25,6 +25,8 @@ import android.annotation.TestApi;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -826,7 +828,11 @@ public class ActivityOptions {
             case ANIM_THUMBNAIL_SCALE_DOWN:
             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
-                mThumbnail = (Bitmap) opts.getParcelable(KEY_ANIM_THUMBNAIL);
+                // Unpackage the GraphicBuffer from the parceled thumbnail
+                final GraphicBuffer buffer = opts.getParcelable(KEY_ANIM_THUMBNAIL);
+                if (buffer != null) {
+                    mThumbnail = Bitmap.createHardwareBitmap(buffer);
+                }
                 mStartX = opts.getInt(KEY_ANIM_START_X, 0);
                 mStartY = opts.getInt(KEY_ANIM_START_Y, 0);
                 mWidth = opts.getInt(KEY_ANIM_WIDTH, 0);
@@ -919,9 +925,14 @@ public class ActivityOptions {
         return mCustomInPlaceResId;
     }
 
-    /** @hide */
-    public Bitmap getThumbnail() {
-        return mThumbnail;
+    /**
+     * The thumbnail is copied into a hardware bitmap when it is bundled and sent to the system, so
+     * it should always be backed by a GraphicBuffer on the other end.
+     *
+     * @hide
+     */
+    public GraphicBuffer getThumbnail() {
+        return mThumbnail != null ? mThumbnail.createGraphicBufferHandle() : null;
     }
 
     /** @hide */
@@ -1230,7 +1241,16 @@ public class ActivityOptions {
             case ANIM_THUMBNAIL_SCALE_DOWN:
             case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
             case ANIM_THUMBNAIL_ASPECT_SCALE_DOWN:
-                b.putParcelable(KEY_ANIM_THUMBNAIL, mThumbnail);
+                // Once we parcel the thumbnail for transfering over to the system, create a copy of
+                // the bitmap to a hardware bitmap and pass through the GraphicBuffer
+                if (mThumbnail != null) {
+                    final Bitmap hwBitmap = mThumbnail.copy(Config.HARDWARE, true /* immutable */);
+                    if (hwBitmap != null) {
+                        b.putParcelable(KEY_ANIM_THUMBNAIL, hwBitmap.createGraphicBufferHandle());
+                    } else {
+                        Slog.w(TAG, "Failed to copy thumbnail");
+                    }
+                }
                 b.putInt(KEY_ANIM_START_X, mStartX);
                 b.putInt(KEY_ANIM_START_Y, mStartY);
                 b.putInt(KEY_ANIM_WIDTH, mWidth);
index 620e5cf..2813e8b 100644 (file)
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.Intent;
 import android.os.Build;
@@ -72,12 +74,8 @@ import java.lang.annotation.RetentionPolicy;
  * {@link #setExact(int, long, PendingIntent)}.  Applications whose {@code targetSdkVersion}
  * is earlier than API 19 will continue to see the previous behavior in which all
  * alarms are delivered exactly when requested.
- *
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.ALARM_SERVICE)}.
  */
+@SystemService(Context.ALARM_SERVICE)
 public class AlarmManager {
     private static final String TAG = "AlarmManager";
 
@@ -599,6 +597,7 @@ public class AlarmManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
             long intervalMillis, PendingIntent operation, WorkSource workSource) {
         setImpl(type, triggerAtMillis, windowMillis, intervalMillis, 0, operation, null, null,
@@ -633,6 +632,7 @@ public class AlarmManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public void set(@AlarmType int type, long triggerAtMillis, long windowMillis,
             long intervalMillis, OnAlarmListener listener, Handler targetHandler,
             WorkSource workSource) {
index 8292152..e672ada 100644 (file)
@@ -17,7 +17,9 @@
 package android.app;
 
 import android.Manifest;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.media.AudioAttributes.AttributeUsage;
@@ -42,10 +44,9 @@ import java.util.List;
  * API for interacting with "application operation" tracking.
  *
  * <p>This API is not generally intended for third party application developers; most
- * features are only available to system applications.  Obtain an instance of it through
- * {@link Context#getSystemService(String) Context.getSystemService} with
- * {@link Context#APP_OPS_SERVICE Context.APP_OPS_SERVICE}.</p>
+ * features are only available to system applications.
  */
+@SystemService(Context.APP_OPS_SERVICE)
 public class AppOpsManager {
     /**
      * <p>App ops allows callers to:</p>
@@ -1409,6 +1410,7 @@ public class AppOpsManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS)
     public void setUidMode(String appOp, int uid, int mode) {
         try {
             mService.setUidMode(AppOpsManager.strOpToOp(appOp), uid, mode);
index 525b151..e5c4208 100644 (file)
@@ -2108,7 +2108,7 @@ public class ApplicationPackageManager extends PackageManager {
     public void freeStorageAndNotify(String volumeUuid, long idealStorageSize,
             IPackageDataObserver observer) {
         try {
-            mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, observer);
+            mPM.freeStorageAndNotify(volumeUuid, idealStorageSize, 0, observer);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -2117,7 +2117,7 @@ public class ApplicationPackageManager extends PackageManager {
     @Override
     public void freeStorage(String volumeUuid, long freeStorageSize, IntentSender pi) {
         try {
-            mPM.freeStorage(volumeUuid, freeStorageSize, pi);
+            mPM.freeStorage(volumeUuid, freeStorageSize, 0, pi);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
index 175b979..b6cff38 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.os.Build;
 import android.os.Bundle;
@@ -72,6 +73,7 @@ public class BroadcastOptions {
      * power whitelist when this broadcast is being delivered to it.
      * @param duration The duration in milliseconds; 0 means to not place on whitelist.
      */
+    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
     public void setTemporaryAppWhitelistDuration(long duration) {
         mTemporaryAppWhitelistDuration = duration;
     }
index b89c165..5baaeb3 100644 (file)
@@ -19,6 +19,7 @@ package android.app;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ContentResolver;
 import android.content.ContentUris;
@@ -51,18 +52,15 @@ import java.util.List;
  * request that a URI be downloaded to a particular destination file. The download manager will
  * conduct the download in the background, taking care of HTTP interactions and retrying downloads
  * after failures or across connectivity changes and system reboots.
- *
- * Instances of this class should be obtained through
- * {@link android.content.Context#getSystemService(String)} by passing
- * {@link android.content.Context#DOWNLOAD_SERVICE}.
- *
+ * <p>
  * Apps that request downloads through this API should register a broadcast receiver for
  * {@link #ACTION_NOTIFICATION_CLICKED} to appropriately handle when the user clicks on a running
  * download in a notification or from the downloads UI.
- *
+ * <p>
  * Note that the application must have the {@link android.Manifest.permission#INTERNET}
  * permission to use this class.
  */
+@SystemService(Context.DOWNLOAD_SERVICE)
 public class DownloadManager {
 
     /**
index 16cbb7c..dbea349 100644 (file)
@@ -1953,6 +1953,12 @@ public class Instrumentation {
             case ActivityManager.START_VOICE_HIDDEN_SESSION:
                 throw new IllegalStateException(
                         "Cannot start voice activity on a hidden session");
+            case ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION:
+                throw new IllegalStateException(
+                        "Session calling startAssistantActivity does not match active session");
+            case ActivityManager.START_ASSISTANT_HIDDEN_SESSION:
+                throw new IllegalStateException(
+                        "Cannot start assistant activity on a hidden session");
             case ActivityManager.START_CANCELED:
                 throw new AndroidRuntimeException("Activity could not be started for "
                         + intent);
index fcf0aab..2a29616 100644 (file)
@@ -20,6 +20,7 @@ import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.app.trust.ITrustManager;
 import android.content.Context;
 import android.content.Intent;
@@ -44,12 +45,11 @@ import com.android.internal.policy.IKeyguardDismissCallback;
 import java.util.List;
 
 /**
- * Class that can be used to lock and unlock the keyboard. Get an instance of this
- * class by calling {@link android.content.Context#getSystemService(java.lang.String)}
- * with argument {@link android.content.Context#KEYGUARD_SERVICE}. The
+ * Class that can be used to lock and unlock the keyboard. The
  * actual class to control the keyboard locking is
  * {@link android.app.KeyguardManager.KeyguardLock}.
  */
+@SystemService(Context.KEYGUARD_SERVICE)
 public class KeyguardManager {
 
     private static final String TAG = "KeyguardManager";
index 3ed174b..4dd71b4 100644 (file)
@@ -22,6 +22,7 @@ import android.annotation.ColorInt;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -1009,6 +1010,7 @@ public class Notification implements Parcelable
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NOTIFICATION_DURING_SETUP)
     public static final String EXTRA_ALLOW_DURING_SETUP = "android.allowDuringSetup";
 
     /**
@@ -1110,6 +1112,7 @@ public class Notification implements Parcelable
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SUBSTITUTE_NOTIFICATION_APP_NAME)
     public static final String EXTRA_SUBSTITUTE_APP_NAME = "android.substName";
 
     /**
@@ -2640,6 +2643,20 @@ public class Notification implements Parcelable
     }
 
     /**
+     * @hide
+     */
+    public boolean suppressAlertingDueToGrouping() {
+        if (isGroupSummary()
+                && getGroupAlertBehavior() == Notification.GROUP_ALERT_CHILDREN) {
+            return true;
+        } else if (isGroupChild()
+                && getGroupAlertBehavior() == Notification.GROUP_ALERT_SUMMARY) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
      * Builder class for {@link Notification} objects.
      *
      * Provides a convenient way to set the various fields of a {@link Notification} and generate
index c076e5e..143d147 100644 (file)
@@ -575,8 +575,8 @@ public final class NotificationChannel implements Parcelable {
         setSound(safeUri(parser, ATT_SOUND), safeAudioAttributes(parser));
         enableLights(safeBool(parser, ATT_LIGHTS, false));
         setLightColor(safeInt(parser, ATT_LIGHT_COLOR, DEFAULT_LIGHT_COLOR));
-        enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false));
         setVibrationPattern(safeLongArray(parser, ATT_VIBRATION, null));
+        enableVibration(safeBool(parser, ATT_VIBRATION_ENABLED, false));
         setShowBadge(safeBool(parser, ATT_SHOW_BADGE, false));
         setDeleted(safeBool(parser, ATT_DELETED, false));
         setGroup(parser.getAttributeValue(null, ATT_GROUP));
index 6c55548..235b8d4 100644 (file)
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.Notification.Builder;
 import android.content.ComponentName;
@@ -81,10 +82,6 @@ import java.util.Objects;
  * to the {@link #cancel(int)} or {@link #cancel(String, int)} method to clear
  * this notification.
  *
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For a guide to creating notifications, read the
@@ -93,10 +90,9 @@ import java.util.Objects;
  * </div>
  *
  * @see android.app.Notification
- * @see android.content.Context#getSystemService
  */
-public class NotificationManager
-{
+@SystemService(Context.NOTIFICATION_SERVICE)
+public class NotificationManager {
     private static String TAG = "NotificationManager";
     private static boolean localLOGV = false;
 
index c529e4b..ea990ad 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.annotation.SystemService;
 import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -46,10 +47,6 @@ import java.util.List;
  * services are provided through methods in {@link android.app.Activity Activity}
  * and the {@link android.content.Intent#ACTION_SEARCH ACTION_SEARCH}
  * {@link android.content.Intent Intent}.
- * If you do require direct access to the SearchManager, do not instantiate
- * this class directly. Instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * context.getSystemService(Context.SEARCH_SERVICE)}.
  *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
@@ -58,9 +55,9 @@ import java.util.List;
  * <a href="{@docRoot}guide/topics/search/index.html">Search</a> developer guide.</p>
  * </div>
  */
+@SystemService(Context.SEARCH_SERVICE)
 public class SearchManager
-        implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener
-{
+        implements DialogInterface.OnDismissListener, DialogInterface.OnCancelListener {
 
     private static final boolean DBG = false;
     private static final String TAG = "SearchManager";
index e57a9b5..fb8bd39 100644 (file)
@@ -18,6 +18,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Binder;
 import android.os.RemoteException;
@@ -36,6 +37,7 @@ import java.lang.annotation.RetentionPolicy;
  *
  * @hide
  */
+@SystemService(Context.STATUS_BAR_SERVICE)
 public class StatusBarManager {
 
     public static final int DISABLE_EXPAND = View.STATUS_BAR_DISABLE_EXPAND;
index 8a4f8a6..0f006b6 100644 (file)
@@ -151,10 +151,7 @@ public class TimePickerDialog extends AlertDialog implements OnClickListener,
             @Override
             public void onClick(View view) {
                 if (mTimePicker.validateInput()) {
-                    if (mTimeSetListener != null) {
-                        mTimeSetListener.onTimeSet(mTimePicker, mTimePicker.getCurrentHour(),
-                                mTimePicker.getCurrentMinute());
-                    }
+                    TimePickerDialog.this.onClick(TimePickerDialog.this, BUTTON_POSITIVE);
                     dismiss();
                 }
             }
index 07e2570..bc61668 100644 (file)
@@ -17,6 +17,7 @@
 package android.app;
 
 import android.annotation.IntDef;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
 import android.content.res.Configuration;
@@ -49,11 +50,8 @@ import java.lang.annotation.RetentionPolicy;
  * displayed allowing the user to exit dock mode.  Thus the dock mode
  * represented here may be different than the current state of the underlying
  * dock event broadcast.
- *
- * <p>You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.UI_MODE_SERVICE)}.
  */
+@SystemService(Context.UI_MODE_SERVICE)
 public class UiModeManager {
     private static final String TAG = "UiModeManager";
 
index 8014eca..b40c96c 100644 (file)
@@ -1,19 +1,20 @@
 package android.app;
 
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
+import android.content.Context;
 import android.os.RemoteException;
 import android.service.vr.IVrManager;
 
 /**
  * Used to control aspects of a devices Virtual Reality (VR) capabilities.
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
  * @hide
  */
 @SystemApi
+@SystemService(Context.VR_SERVICE)
 public class VrManager {
     private final IVrManager mService;
 
@@ -29,11 +30,10 @@ public class VrManager {
      * remain in VR mode even if the foreground does not specify Vr mode being enabled. Mainly used
      * by VR viewers to indicate that a device is placed in a VR viewer.
      *
-     * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
-     *
      * @see Activity#setVrModeEnabled(boolean, ComponentName)
      * @param enabled true if the device should be placed in persistent VR mode.
      */
+    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     public void setPersistentVrModeEnabled(boolean enabled) {
         try {
             mService.setPersistentVrModeEnabled(enabled);
@@ -46,13 +46,12 @@ public class VrManager {
      * Sets the resolution and DPI of the vr2d virtual display used to display 2D
      * applications in VR mode.
      *
-     * <p>Requires {@link android.Manifest.permission#ACCESS_VR_MANAGER} permission.</p>
-     *
      * @param vr2dDisplayProp properties to be set to the virtual display for
      * 2D applications in VR mode.
      *
      * {@hide}
      */
+    @RequiresPermission(android.Manifest.permission.RESTRICTED_VR_ACCESS)
     public void setVr2dDisplayProperties(
             Vr2dDisplayProperties vr2dDisplayProp) {
         try {
index db2f937..a850423 100644 (file)
@@ -18,8 +18,10 @@ package android.app;
 
 import android.annotation.IntDef;
 import android.annotation.RawRes;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -76,13 +78,13 @@ import java.util.concurrent.TimeUnit;
 /**
  * Provides access to the system wallpaper. With WallpaperManager, you can
  * get the current wallpaper, get the desired dimensions for the wallpaper, set
- * the wallpaper, and more. Get an instance of WallpaperManager with
- * {@link #getInstance(android.content.Context) getInstance()}.
+ * the wallpaper, and more.
  *
  * <p> An app can check whether wallpapers are supported for the current user, by calling
  * {@link #isWallpaperSupported()}, and whether setting of wallpapers is allowed, by calling
  * {@link #isSetWallpaperAllowed()}.
  */
+@SystemService(Context.WALLPAPER_SERVICE)
 public class WallpaperManager {
     private static String TAG = "WallpaperManager";
     private static boolean DEBUG = false;
@@ -1355,6 +1357,7 @@ public class WallpaperManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_HINTS)
     public void setDisplayPadding(Rect padding) {
         try {
             if (sGlobals.mService == null) {
@@ -1395,6 +1398,7 @@ public class WallpaperManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
     public void clearWallpaper() {
         clearWallpaper(FLAG_LOCK, mContext.getUserId());
         clearWallpaper(FLAG_SYSTEM, mContext.getUserId());
@@ -1407,6 +1411,7 @@ public class WallpaperManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER)
     public void clearWallpaper(@SetWallpaperFlags int which, int userId) {
         if (sGlobals.mService == null) {
             Log.w(TAG, "WallpaperService not running");
@@ -1422,12 +1427,10 @@ public class WallpaperManager {
     /**
      * Set the live wallpaper.
      *
-     * This can only be called by packages with android.permission.SET_WALLPAPER_COMPONENT
-     * permission.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_WALLPAPER_COMPONENT)
     public boolean setWallpaperComponent(ComponentName name) {
         return setWallpaperComponent(name, UserHandle.myUserId());
     }
index 9ae5d1c..01c4656 100644 (file)
@@ -20,9 +20,12 @@ import android.annotation.ColorInt;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
@@ -98,6 +101,7 @@ import java.util.Set;
  * "{@docRoot}guide/topics/admin/device-admin.html">Device Administration</a> developer
  * guide. </div>
  */
+@SystemService(Context.DEVICE_POLICY_SERVICE)
 public class DevicePolicyManager {
     private static String TAG = "DevicePolicyManager";
 
@@ -1601,6 +1605,7 @@ public class DevicePolicyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public boolean packageHasActiveAdmins(String packageName) {
         return packageHasActiveAdmins(packageName, myUserId());
     }
@@ -4512,11 +4517,10 @@ public class DevicePolicyManager {
     /**
      * @return device owner component name, even if it's running on a different user.
      *
-     * <p>Requires the MANAGE_USERS permission.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public ComponentName getDeviceOwnerComponentOnAnyUser() {
         return getDeviceOwnerComponentInner(/* callingUserOnly =*/ false);
     }
@@ -4600,6 +4604,7 @@ public class DevicePolicyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public @Nullable String getDeviceOwner() {
         throwIfParentInstance("getDeviceOwner");
         final ComponentName name = getDeviceOwnerComponentOnCallingUser();
@@ -4617,6 +4622,7 @@ public class DevicePolicyManager {
      */
     @SystemApi
     @TestApi
+    @SuppressLint("Doclava125")
     public boolean isDeviceManaged() {
         try {
             return mService.hasDeviceOwner();
@@ -4629,11 +4635,10 @@ public class DevicePolicyManager {
      * Returns the device owner name.  Note this method *will* return the device owner
      * name when it's running on a different user.
      *
-     * <p>Requires the MANAGE_USERS permission.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public String getDeviceOwnerNameOnAnyUser() {
         throwIfParentInstance("getDeviceOwnerNameOnAnyUser");
         if (mService != null) {
@@ -4653,6 +4658,7 @@ public class DevicePolicyManager {
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public @Nullable String getDeviceInitializerApp() {
         return null;
     }
@@ -4664,6 +4670,7 @@ public class DevicePolicyManager {
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public @Nullable ComponentName getDeviceInitializerComponent() {
         return null;
     }
@@ -4686,6 +4693,7 @@ public class DevicePolicyManager {
      */
     @Deprecated
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_DEVICE_ADMINS)
     public boolean setActiveProfileOwner(@NonNull ComponentName admin, @Deprecated String ownerName)
             throws IllegalArgumentException {
         throwIfParentInstance("setActiveProfileOwner");
@@ -5003,6 +5011,7 @@ public class DevicePolicyManager {
      * @throws IllegalArgumentException if the userId is invalid.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public @Nullable String getProfileOwnerNameAsUser(int userId) throws IllegalArgumentException {
         throwIfParentInstance("getProfileOwnerNameAsUser");
         if (mService != null) {
@@ -6773,8 +6782,7 @@ public class DevicePolicyManager {
      * Called by the system update service to notify device and profile owners of pending system
      * updates.
      *
-     * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
-     * permission. This method should only be used when it is unknown whether the pending system
+     * This method should only be used when it is unknown whether the pending system
      * update is a security patch. Otherwise, use
      * {@link #notifyPendingSystemUpdate(long, boolean)}.
      *
@@ -6785,6 +6793,7 @@ public class DevicePolicyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NOTIFY_PENDING_SYSTEM_UPDATE)
     public void notifyPendingSystemUpdate(long updateReceivedTime) {
         throwIfParentInstance("notifyPendingSystemUpdate");
         if (mService != null) {
@@ -6800,8 +6809,7 @@ public class DevicePolicyManager {
      * Called by the system update service to notify device and profile owners of pending system
      * updates.
      *
-     * The caller must hold {@link android.Manifest.permission#NOTIFY_PENDING_SYSTEM_UPDATE}
-     * permission. This method should be used instead of {@link #notifyPendingSystemUpdate(long)}
+     * This method should be used instead of {@link #notifyPendingSystemUpdate(long)}
      * when it is known whether the pending system update is a security patch.
      *
      * @param updateReceivedTime The time as given by {@link System#currentTimeMillis()}
@@ -6813,6 +6821,7 @@ public class DevicePolicyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.NOTIFY_PENDING_SYSTEM_UPDATE)
     public void notifyPendingSystemUpdate(long updateReceivedTime, boolean isSecurityPatch) {
         throwIfParentInstance("notifyPendingSystemUpdate");
         if (mService != null) {
@@ -7521,6 +7530,7 @@ public class DevicePolicyManager {
      */
     @SystemApi
     @TestApi
+    @SuppressLint("Doclava125")
     public @Nullable CharSequence getDeviceOwnerOrganizationName() {
         try {
             return mService.getDeviceOwnerOrganizationName();
@@ -7711,6 +7721,7 @@ public class DevicePolicyManager {
       * @hide
       */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public void setDeviceProvisioningConfigApplied() {
         try {
             mService.setDeviceProvisioningConfigApplied();
@@ -7731,6 +7742,7 @@ public class DevicePolicyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isDeviceProvisioningConfigApplied() {
         try {
             return mService.isDeviceProvisioningConfigApplied();
index c99a1e4..266fa7e 100644 (file)
@@ -18,7 +18,6 @@ import android.os.PooledStringReader;
 import android.os.PooledStringWriter;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.service.autofill.FillContext;
 import android.service.autofill.FillRequest;
 import android.text.TextUtils;
 import android.util.Log;
@@ -31,7 +30,6 @@ import android.view.ViewStructure.HtmlInfo.Builder;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
 import android.view.autofill.AutofillId;
-import android.view.autofill.AutofillManager;
 import android.view.autofill.AutofillValue;
 
 import java.util.ArrayList;
@@ -39,18 +37,18 @@ import java.util.Arrays;
 import java.util.List;
 
 /**
- * Assist data automatically created by the platform's implementation of Assist and Autofill.
+ * Assist data automatically created by the platform's implementation of assist and autofill.
  *
- * <p>The structure is used for Assist purposes when created by
+ * <p>The structure is used for assist purposes when created by
  * {@link android.app.Activity#onProvideAssistData}, {@link View#onProvideStructure(ViewStructure)},
  * or {@link View#onProvideVirtualStructure(ViewStructure)}.
  *
- * <p>The structure is used for Autofill purposes when created by
+ * <p>The structure is used for autofill purposes when created by
  * {@link View#onProvideAutofillStructure(ViewStructure, int)},
  * or {@link View#onProvideAutofillVirtualStructure(ViewStructure, int)}.
  *
- * <p>For performance reasons, some properties of the Assist data might be available just for Assist
- * or Autofill purposes; in those case, the property availability will be document in its javadoc.
+ * <p>For performance reasons, some properties of the assist data might be available just for assist
+ * or autofill purposes; in those case, the property availability will be document in its javadoc.
  */
 public class AssistStructure implements Parcelable {
     static final String TAG = "AssistStructure";
@@ -958,10 +956,10 @@ public class AssistStructure implements Parcelable {
         /**
          * Gets the id that can be used to autofill the view contents.
          *
-         * <p>It's relevant set when the {@link AssistStructure} is used for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
          *
          * @return id that can be used to autofill the view contents, or {@code null} if the
-         * structure was created for Assist purposes.
+         * structure was created for assist purposes.
          */
         @Nullable public AutofillId getAutofillId() {
             return mAutofillId;
@@ -970,10 +968,10 @@ public class AssistStructure implements Parcelable {
         /**
          * Gets the the type of value that can be used to autofill the view contents.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes.
          *
          * @return autofill type as defined by {@link View#getAutofillType()},
-         * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for Assist purposes.
+         * or {@link View#AUTOFILL_TYPE_NONE} if the structure was created for assist purposes.
          */
         public @View.AutofillType int getAutofillType() {
             return mAutofillType;
@@ -983,11 +981,11 @@ public class AssistStructure implements Parcelable {
          * Describes the content of a view so that a autofill service can fill in the appropriate
          * data.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes,
+         * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
          * not for Assist - see {@link View#getAutofillHints()} for more info.
          *
          * @return The autofill hints for this view, or {@code null} if the structure was created
-         * for Assist purposes.
+         * for assist purposes.
          */
         @Nullable public String[] getAutofillHints() {
             return mAutofillHints;
@@ -996,11 +994,11 @@ public class AssistStructure implements Parcelable {
         /**
          * Gets the the value of this view.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes,
-         * not for Assist purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
+         * not for assist purposes.
          *
          * @return the autofill value of this view, or {@code null} if the structure was created
-         * for Assist purposes.
+         * for assist purposes.
          */
         @Nullable public AutofillValue getAutofillValue() {
             return mAutofillValue;
@@ -1017,11 +1015,11 @@ public class AssistStructure implements Parcelable {
          * <p>Typically used by nodes whose {@link View#getAutofillType()} is a list to indicate
          * the meaning of each possible value in the list.
          *
-         * <p>It's relevant when the {@link AssistStructure} is used for Autofill purposes, not
-         * for Assist purposes.
+         * <p>It's relevant when the {@link AssistStructure} is used for autofill purposes, not
+         * for assist purposes.
          *
          * @return the options that can be used to autofill this view, or {@code null} if the
-         * structure was created for Assist purposes.
+         * structure was created for assist purposes.
          */
         @Nullable public CharSequence[] getAutofillOptions() {
             return mAutofillOptions;
@@ -1106,8 +1104,8 @@ public class AssistStructure implements Parcelable {
          * or scaling.  The returned Matrix object is owned by ViewNode; do not modify it.
          * Returns null if there is no transformation applied to the view.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public Matrix getTransformation() {
             return mMatrix;
@@ -1118,8 +1116,8 @@ public class AssistStructure implements Parcelable {
          * characterstics, as set by {@link ViewStructure#setElevation
          * ViewStructure.setElevation(float)}.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public float getElevation() {
             return mElevation;
@@ -1130,8 +1128,8 @@ public class AssistStructure implements Parcelable {
          * of the view's contents, as set by {@link ViewStructure#setAlpha
          * ViewStructure.setAlpha(float)}.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public float getAlpha() {
             return mAlpha;
@@ -1260,7 +1258,7 @@ public class AssistStructure implements Parcelable {
          * document.
          *
          * <strong>WARNING:</strong> a {@link android.service.autofill.AutofillService} should only
-         * use this domain for Autofill purposes when it trusts the app generating it (i.e., the app
+         * use this domain for autofill purposes when it trusts the app generating it (i.e., the app
          * defined by {@link AssistStructure#getActivityComponent()}).
          *
          * @return domain-only part of the document. For example, if the full URL is
@@ -1273,11 +1271,11 @@ public class AssistStructure implements Parcelable {
         /**
          * Returns the HTML properties associated with this view.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Autofill purposes,
-         * not for Assist purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for autofill purposes,
+         * not for assist purposes.
          *
          * @return the HTML properties associated with this view, or {@code null} if the
-         * structure was created for Assist purposes.
+         * structure was created for assist purposes.
          */
         @Nullable public HtmlInfo getHtmlInfo() {
             return mHtmlInfo;
@@ -1301,8 +1299,8 @@ public class AssistStructure implements Parcelable {
         /**
          * If {@link #getText()} is non-null, this is where the current selection starts.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public int getTextSelectionStart() {
             return mText != null ? mText.mTextSelectionStart : -1;
@@ -1313,8 +1311,8 @@ public class AssistStructure implements Parcelable {
          * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
          * indicating the cursor position.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public int getTextSelectionEnd() {
             return mText != null ? mText.mTextSelectionEnd : -1;
@@ -1337,8 +1335,8 @@ public class AssistStructure implements Parcelable {
          * Note that the text may also contain style spans that modify the color of specific
          * parts of the text.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public int getTextBackgroundColor() {
             return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
@@ -1350,8 +1348,8 @@ public class AssistStructure implements Parcelable {
          * Note that the text may also contain style spans that modify the size of specific
          * parts of the text.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public float getTextSize() {
             return mText != null ? mText.mTextSize : 0;
@@ -1365,8 +1363,8 @@ public class AssistStructure implements Parcelable {
          * Note that the text may also contain style spans that modify the style of specific
          * parts of the text.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public int getTextStyle() {
             return mText != null ? mText.mTextStyle : 0;
@@ -1378,8 +1376,8 @@ public class AssistStructure implements Parcelable {
          * into the text string where that line starts.  May return null if there is no line
          * information.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public int[] getTextLineCharOffsets() {
             return mText != null ? mText.mLineCharOffsets : null;
@@ -1391,8 +1389,8 @@ public class AssistStructure implements Parcelable {
          * where that text appears in the view.  May return null if there is no line
          * information.
          *
-         * <p>It's only relevant when the {@link AssistStructure} is used for Assist purposes,
-         * not for Autofill purposes.
+         * <p>It's only relevant when the {@link AssistStructure} is used for assist purposes,
+         * not for autofill purposes.
          */
         public int[] getTextLineBaselines() {
             return mText != null ? mText.mLineBaselines : null;
index 9d02f53..9f9b217 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.app.backup;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.ComponentName;
 import android.content.Context;
@@ -324,6 +325,7 @@ public class BackupManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public RestoreSession beginRestoreSession() {
         RestoreSession session = null;
         checkServiceBinder();
@@ -348,11 +350,10 @@ public class BackupManager {
      * mechanism was disabled will still be backed up properly if it is enabled
      * at some point in the future.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void setBackupEnabled(boolean isEnabled) {
         checkServiceBinder();
         if (sService != null) {
@@ -367,11 +368,10 @@ public class BackupManager {
     /**
      * Report whether the backup mechanism is currently enabled.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public boolean isBackupEnabled() {
         checkServiceBinder();
         if (sService != null) {
@@ -390,11 +390,10 @@ public class BackupManager {
      * the archival restore dataset (if any).  When disabled, no such attempt will
      * be made.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void setAutoRestore(boolean isEnabled) {
         checkServiceBinder();
         if (sService != null) {
@@ -407,14 +406,14 @@ public class BackupManager {
     }
 
     /**
-     * Identify the currently selected transport.  Callers must hold the
-     * android.permission.BACKUP permission to use this method.
+     * Identify the currently selected transport.
      * @return The name of the currently active backup transport.  In case of
      *   failure or if no transport is currently active, this method returns {@code null}.
      *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public String getCurrentTransport() {
         checkServiceBinder();
         if (sService != null) {
@@ -428,12 +427,12 @@ public class BackupManager {
     }
 
     /**
-     * Request a list of all available backup transports' names.  Callers must
-     * hold the android.permission.BACKUP permission to use this method.
+     * Request a list of all available backup transports' names.
      *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public String[] listAllTransports() {
         checkServiceBinder();
         if (sService != null) {
@@ -449,8 +448,6 @@ public class BackupManager {
     /**
      * Specify the current backup transport.
      *
-     * <p> Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param transport The name of the transport to select.  This should be one
      *   of the names returned by {@link #listAllTransports()}. This is the String returned by
      *   {@link BackupTransport#name()} for the particular transport.
@@ -462,6 +459,7 @@ public class BackupManager {
      */
     @Deprecated
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public String selectBackupTransport(String transport) {
         checkServiceBinder();
         if (sService != null) {
@@ -479,8 +477,6 @@ public class BackupManager {
      * This method is async because BackupManager might need to bind to the specified transport
      * which is in a separate process.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param transport ComponentName of the service hosting the transport. This is different from
      *                  the transport's name that is returned by {@link BackupTransport#name()}.
      * @param listener A listener object to get a callback on the transport being selected.
@@ -488,6 +484,7 @@ public class BackupManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void selectBackupTransport(ComponentName transport,
             SelectBackupTransportCallback listener) {
         checkServiceBinder();
@@ -510,11 +507,10 @@ public class BackupManager {
      * transport will still be asked to confirm via the usual requestBackupTime()
      * method.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void backupNow() {
         checkServiceBinder();
         if (sService != null) {
@@ -530,8 +526,6 @@ public class BackupManager {
      * Ask the framework which dataset, if any, the given package's data would be
      * restored from if we were to install it right now.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param packageName The name of the package whose most-suitable dataset we
      *     wish to look up
      * @return The dataset token from which a restore should be attempted, or zero if
@@ -540,6 +534,7 @@ public class BackupManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public long getAvailableRestoreToken(String packageName) {
         checkServiceBinder();
         if (sService != null) {
@@ -555,14 +550,13 @@ public class BackupManager {
     /**
      * Ask the framework whether this app is eligible for backup.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @param packageName The name of the package.
      * @return Whether this app is eligible for backup.
      *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public boolean isAppEligibleForBackup(String packageName) {
         checkServiceBinder();
         if (sService != null) {
@@ -592,6 +586,7 @@ public class BackupManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public int requestBackup(String[] packages, BackupObserver observer) {
         return requestBackup(packages, observer, null, 0);
     }
@@ -615,6 +610,7 @@ public class BackupManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public int requestBackup(String[] packages, BackupObserver observer,
             BackupManagerMonitor monitor, int flags) {
         checkServiceBinder();
@@ -638,11 +634,10 @@ public class BackupManager {
      * Cancel all running backups. After this call returns, no currently running backups will
      * interact with the selected transport.
      *
-     * <p>Callers must hold the android.permission.BACKUP permission to use this method.
-     *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.BACKUP)
     public void cancelBackups() {
         checkServiceBinder();
         if (sService != null) {
index 3cb59f2..87e516c 100644 (file)
@@ -35,6 +35,7 @@ import android.util.Log;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -501,7 +502,7 @@ public class JobInfo implements Parcelable {
         if (constraintFlags != j.constraintFlags) {
             return false;
         }
-        if (!Objects.deepEquals(triggerContentUris, j.triggerContentUris)) {
+        if (!Arrays.equals(triggerContentUris, j.triggerContentUris)) {
             return false;
         }
         if (triggerContentUpdateDelay != j.triggerContentUpdateDelay) {
@@ -556,37 +557,37 @@ public class JobInfo implements Parcelable {
     public int hashCode() {
         int hashCode = jobId;
         if (extras != null) {
-            hashCode = 31*hashCode + extras.hashCode();
+            hashCode = 31 * hashCode + extras.hashCode();
         }
         if (transientExtras != null) {
-            hashCode = 31*hashCode + transientExtras.hashCode();
+            hashCode = 31 * hashCode + transientExtras.hashCode();
         }
         if (clipData != null) {
-            hashCode = 31*hashCode + clipData.hashCode();
+            hashCode = 31 * hashCode + clipData.hashCode();
         }
         hashCode = 31*hashCode + clipGrantFlags;
         if (service != null) {
-            hashCode = 31*hashCode + service.hashCode();
+            hashCode = 31 * hashCode + service.hashCode();
         }
-        hashCode = 31*hashCode + constraintFlags;
+        hashCode = 31 * hashCode + constraintFlags;
         if (triggerContentUris != null) {
-            hashCode = 31*hashCode + triggerContentUris.hashCode();
+            hashCode = 31 * hashCode + Arrays.hashCode(triggerContentUris);
         }
-        hashCode = 31*hashCode + Long.hashCode(triggerContentUpdateDelay);
-        hashCode = 31*hashCode + Long.hashCode(triggerContentMaxDelay);
-        hashCode = 31*hashCode + Boolean.hashCode(hasEarlyConstraint);
-        hashCode = 31*hashCode + Boolean.hashCode(hasLateConstraint);
-        hashCode = 31*hashCode + networkType;
-        hashCode = 31*hashCode + Long.hashCode(minLatencyMillis);
-        hashCode = 31*hashCode + Long.hashCode(maxExecutionDelayMillis);
-        hashCode = 31*hashCode + Boolean.hashCode(isPeriodic);
-        hashCode = 31*hashCode + Boolean.hashCode(isPersisted);
-        hashCode = 31*hashCode + Long.hashCode(intervalMillis);
-        hashCode = 31*hashCode + Long.hashCode(flexMillis);
-        hashCode = 31*hashCode + Long.hashCode(initialBackoffMillis);
-        hashCode = 31*hashCode + backoffPolicy;
-        hashCode = 31*hashCode + priority;
-        hashCode = 31*hashCode + flags;
+        hashCode = 31 * hashCode + Long.hashCode(triggerContentUpdateDelay);
+        hashCode = 31 * hashCode + Long.hashCode(triggerContentMaxDelay);
+        hashCode = 31 * hashCode + Boolean.hashCode(hasEarlyConstraint);
+        hashCode = 31 * hashCode + Boolean.hashCode(hasLateConstraint);
+        hashCode = 31 * hashCode + networkType;
+        hashCode = 31 * hashCode + Long.hashCode(minLatencyMillis);
+        hashCode = 31 * hashCode + Long.hashCode(maxExecutionDelayMillis);
+        hashCode = 31 * hashCode + Boolean.hashCode(isPeriodic);
+        hashCode = 31 * hashCode + Boolean.hashCode(isPersisted);
+        hashCode = 31 * hashCode + Long.hashCode(intervalMillis);
+        hashCode = 31 * hashCode + Long.hashCode(flexMillis);
+        hashCode = 31 * hashCode + Long.hashCode(initialBackoffMillis);
+        hashCode = 31 * hashCode + backoffPolicy;
+        hashCode = 31 * hashCode + priority;
+        hashCode = 31 * hashCode + flags;
         return hashCode;
     }
 
index 1768828..3868439 100644 (file)
@@ -19,8 +19,11 @@ package android.app.job;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ClipData;
+import android.content.Context;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.PersistableBundle;
@@ -53,6 +56,7 @@ import java.util.List;
  * {@link android.content.Context#getSystemService
  * Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}.
  */
+@SystemService(Context.JOB_SCHEDULER_SERVICE)
 public abstract class JobScheduler {
     /** @hide */
     @IntDef(prefix = { "RESULT_" }, value = {
@@ -132,6 +136,7 @@ public abstract class JobScheduler {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName,
             int userId, String tag);
 
index b0ec650..ab94da8 100644 (file)
@@ -210,6 +210,9 @@ public abstract class JobServiceEngine {
      * information.
      */
     public void jobFinished(JobParameters params, boolean needsReschedule) {
+        if (params == null) {
+            throw new NullPointerException("params");
+        }
         Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
         m.arg2 = needsReschedule ? 1 : 0;
         m.sendToTarget();
index 06b0aac..54a7e5c 100644 (file)
@@ -18,6 +18,8 @@ package android.app.trust;
 
 import android.Manifest;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Looper;
@@ -31,6 +33,7 @@ import com.android.internal.widget.LockPatternUtils;
  * See {@link com.android.server.trust.TrustManagerService}
  * @hide
  */
+@SystemService(Context.TRUST_SERVICE)
 public class TrustManager {
 
     private static final int MSG_TRUST_CHANGED = 1;
index 5d1550f..15e5ea5 100644 (file)
@@ -24,6 +24,7 @@ interface IStorageStatsManager {
     boolean isQuotaSupported(String volumeUuid, String callingPackage);
     long getTotalBytes(String volumeUuid, String callingPackage);
     long getFreeBytes(String volumeUuid, String callingPackage);
+    long getCacheBytes(String volumeUuid, String callingPackage);
     long getCacheQuotaBytes(String volumeUuid, int uid, String callingPackage);
     StorageStats queryStatsForPackage(String volumeUuid, String packageName, int userId, String callingPackage);
     StorageStats queryStatsForUid(String volumeUuid, int uid, String callingPackage);
index 6cd4e92..ef262e0 100644 (file)
@@ -19,6 +19,7 @@ package android.app.usage;
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.app.usage.NetworkStats.Bucket;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -82,6 +83,7 @@ import android.util.Log;
  * the above permission, even to access an app's own data usage, and carrier-privileged apps were
  * not included.
  */
+@SystemService(Context.NETWORK_STATS_SERVICE)
 public class NetworkStatsManager {
     private static final String TAG = "NetworkStatsManager";
     private static final boolean DBG = false;
index d9d958c..7c68079 100644 (file)
@@ -20,6 +20,7 @@ import static android.os.storage.StorageManager.convert;
 
 import android.annotation.BytesLong;
 import android.annotation.NonNull;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.WorkerThread;
 import android.content.Context;
@@ -50,6 +51,7 @@ import java.util.UUID;
  * application.
  * </p>
  */
+@SystemService(Context.STORAGE_STATS_SERVICE)
 public class StorageStatsManager {
     private final Context mContext;
     private final IStorageStatsManager mService;
@@ -142,6 +144,24 @@ public class StorageStatsManager {
         return getFreeBytes(convert(uuid));
     }
 
+    /** {@hide} */
+    public @BytesLong long getCacheBytes(@NonNull UUID storageUuid) throws IOException {
+        try {
+            return mService.getCacheBytes(convert(storageUuid), mContext.getOpPackageName());
+        } catch (ParcelableException e) {
+            e.maybeRethrow(IOException.class);
+            throw new RuntimeException(e);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    /** {@hide} */
+    @Deprecated
+    public long getCacheBytes(String uuid) throws IOException {
+        return getCacheBytes(convert(uuid));
+    }
+
     /**
      * Return storage statistics for a specific package on the requested storage
      * volume.
index 75a4a53..1f939f9 100644 (file)
@@ -16,7 +16,9 @@
 
 package android.app.usage;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.os.RemoteException;
@@ -51,6 +53,7 @@ import java.util.Map;
  * the permission implies intention to use the API and the user of the device can grant permission
  * through the Settings application.
  */
+@SystemService(Context.USAGE_STATS_SERVICE)
 public final class UsageStatsManager {
 
     /**
@@ -252,7 +255,6 @@ public final class UsageStatsManager {
      * Temporarily whitelist the specified app for a short duration. This is to allow an app
      * receiving a high priority message to be able to access the network and acquire wakelocks
      * even if the device is in power-save mode or the app is currently considered inactive.
-     * The caller must hold the CHANGE_DEVICE_IDLE_TEMP_WHITELIST permission.
      * @param packageName The package name of the app to whitelist.
      * @param duration Duration to whitelist the app for, in milliseconds. It is recommended that
      * this be limited to 10s of seconds. Requested duration will be clamped to a few minutes.
@@ -261,6 +263,7 @@ public final class UsageStatsManager {
      * @see #isAppInactive(String)
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CHANGE_DEVICE_IDLE_TEMP_WHITELIST)
     public void whitelistAppTemporarily(String packageName, long duration, UserHandle user) {
         try {
             mService.whitelistAppTemporarily(packageName, duration, user.getIdentifier());
index 6327f34..969b19e 100644 (file)
@@ -20,6 +20,7 @@ import android.annotation.BroadcastBehavior;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -51,6 +52,7 @@ import java.util.List;
  * <a href="{@docRoot}guide/topics/appwidgets/index.html">App Widgets</a> developer guide.</p>
  * </div>
  */
+@SystemService(Context.APPWIDGET_SERVICE)
 public class AppWidgetManager {
 
     /**
index c7191ba..e2fa38a 100644 (file)
@@ -18,6 +18,7 @@ package android.bluetooth;
 
 import android.Manifest;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
 import android.util.Log;
@@ -48,6 +49,7 @@ import java.util.List;
  * @see Context#getSystemService
  * @see BluetoothAdapter#getDefaultAdapter()
  */
+@SystemService(Context.BLUETOOTH_SERVICE)
 public final class BluetoothManager {
     private static final String TAG = "BluetoothManager";
     private static final boolean DBG = true;
index f802e8d..914e8fd 100644 (file)
@@ -47,7 +47,9 @@ public final class ScanRecord {
     private static final int DATA_TYPE_LOCAL_NAME_SHORT = 0x08;
     private static final int DATA_TYPE_LOCAL_NAME_COMPLETE = 0x09;
     private static final int DATA_TYPE_TX_POWER_LEVEL = 0x0A;
-    private static final int DATA_TYPE_SERVICE_DATA = 0x16;
+    private static final int DATA_TYPE_SERVICE_DATA_16_BIT = 0x16;
+    private static final int DATA_TYPE_SERVICE_DATA_32_BIT = 0x20;
+    private static final int DATA_TYPE_SERVICE_DATA_128_BIT = 0x21;
     private static final int DATA_TYPE_MANUFACTURER_SPECIFIC_DATA = 0xFF;
 
     // Flags of the advertising data.
@@ -224,10 +226,16 @@ public final class ScanRecord {
                     case DATA_TYPE_TX_POWER_LEVEL:
                         txPowerLevel = scanRecord[currentPos];
                         break;
-                    case DATA_TYPE_SERVICE_DATA:
-                        // The first two bytes of the service data are service data UUID in little
-                        // endian. The rest bytes are service data.
+                    case DATA_TYPE_SERVICE_DATA_16_BIT:
+                    case DATA_TYPE_SERVICE_DATA_32_BIT:
+                    case DATA_TYPE_SERVICE_DATA_128_BIT:
                         int serviceUuidLength = BluetoothUuid.UUID_BYTES_16_BIT;
+                        if (fieldType == DATA_TYPE_SERVICE_DATA_32_BIT) {
+                         serviceUuidLength = BluetoothUuid.UUID_BYTES_32_BIT;
+                        } else if (fieldType == DATA_TYPE_SERVICE_DATA_128_BIT) {
+                         serviceUuidLength = BluetoothUuid.UUID_BYTES_128_BIT;
+                        }
+
                         byte[] serviceDataUuidBytes = extractBytes(scanRecord, currentPos,
                                 serviceUuidLength);
                         ParcelUuid serviceDataUuid = BluetoothUuid.parseUuidFrom(
index 4e70e3f..dabe608 100644 (file)
@@ -21,6 +21,7 @@ import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.Application;
 import android.app.PendingIntent;
@@ -47,6 +48,7 @@ import java.util.List;
  *
  * @see AssociationRequest
  */
+@SystemService(Context.COMPANION_DEVICE_SERVICE)
 public final class CompanionDeviceManager {
 
     private static final boolean DEBUG = false;
index f1c2f34..718e465 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.SystemService;
 import android.os.Handler;
 import android.os.Message;
 import android.os.RemoteException;
@@ -29,10 +30,6 @@ import java.util.ArrayList;
  * the global clipboard.
  *
  * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
- *
- * <p>
  * The ClipboardManager API itself is very simple: it consists of methods
  * to atomically get and set the current primary clipboard data.  That data
  * is expressed as a {@link ClipData} object, which defines the protocol
@@ -44,9 +41,8 @@ import java.util.ArrayList;
  * <a href="{@docRoot}guide/topics/clipboard/copy-paste.html">Copy and Paste</a>
  * developer guide.</p>
  * </div>
- *
- * @see android.content.Context#getSystemService
  */
+@SystemService(Context.CLIPBOARD_SERVICE)
 public class ClipboardManager extends android.text.ClipboardManager {
     private final Context mContext;
     private final IClipboard mService;
index 10594af..db80c72 100644 (file)
@@ -1630,13 +1630,13 @@ public abstract class Context {
     /**
      * Version of {@link #startActivity(Intent)} that allows you to specify the
      * user the activity will be started for.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS_FULL permission.
+     * that are not pre-installed on the system image.
      * @param intent The description of the activity to start.
      * @param user The UserHandle of the user to start this activity for.
      * @throws ActivityNotFoundException &nbsp;
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public void startActivityAsUser(@RequiresPermission Intent intent, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
@@ -1672,8 +1672,7 @@ public abstract class Context {
     /**
      * Version of {@link #startActivity(Intent, Bundle)} that allows you to specify the
      * user the activity will be started for.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS_FULL permission.
+     * that are not pre-installed on the system image.
      * @param intent The description of the activity to start.
      * @param options Additional options for how the Activity should be started.
      * May be null if there are no options.  See {@link android.app.ActivityOptions}
@@ -1683,6 +1682,7 @@ public abstract class Context {
      * @throws ActivityNotFoundException &nbsp;
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public void startActivityAsUser(@RequiresPermission Intent intent, @Nullable Bundle options,
             UserHandle userId) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -1781,6 +1781,7 @@ public abstract class Context {
      * @see #startActivities(Intent[])
      * @see PackageManager#resolveActivity
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public void startActivitiesAsUser(Intent[] intents, Bundle options, UserHandle userHandle) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
     }
@@ -2081,20 +2082,19 @@ public abstract class Context {
     /**
      * Version of {@link #sendBroadcast(Intent)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      * @param intent The intent to broadcast
      * @param user UserHandle to send the intent to.
      * @see #sendBroadcast(Intent)
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user);
 
     /**
      * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
@@ -2105,14 +2105,14 @@ public abstract class Context {
      *
      * @see #sendBroadcast(Intent, String)
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission);
 
     /**
      * Version of {@link #sendBroadcast(Intent, String, Bundle)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
@@ -2127,14 +2127,14 @@ public abstract class Context {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission, @Nullable Bundle options);
 
     /**
      * Version of {@link #sendBroadcast(Intent, String)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @param intent The Intent to broadcast; all receivers matching this
      *               Intent will receive the broadcast.
@@ -2148,6 +2148,7 @@ public abstract class Context {
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission, int appOp);
 
@@ -2156,8 +2157,7 @@ public abstract class Context {
      * {@link #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)}
      * that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
@@ -2181,6 +2181,7 @@ public abstract class Context {
      *
      * @see #sendOrderedBroadcast(Intent, String, BroadcastReceiver, Handler, int, String, Bundle)
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendOrderedBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, @Nullable String receiverPermission, BroadcastReceiver resultReceiver,
             @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2192,6 +2193,7 @@ public abstract class Context {
      *       BroadcastReceiver, Handler, int, String, Bundle)
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             @Nullable String receiverPermission, int appOp, BroadcastReceiver resultReceiver,
             @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2203,6 +2205,7 @@ public abstract class Context {
      *       BroadcastReceiver, Handler, int, String, Bundle)
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract void sendOrderedBroadcastAsUser(Intent intent, UserHandle user,
             @Nullable String receiverPermission, int appOp, @Nullable Bundle options,
             BroadcastReceiver resultReceiver, @Nullable Handler scheduler, int initialCode,
@@ -2307,8 +2310,7 @@ public abstract class Context {
     /**
      * <p>Version of {@link #sendStickyBroadcast(Intent)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * @deprecated Sticky broadcasts should not be used.  They provide no security (anyone
      * can access them), no protection (anyone can modify them), and many other problems.
@@ -2324,6 +2326,10 @@ public abstract class Context {
      * @see #sendBroadcast(Intent)
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void sendStickyBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user);
 
@@ -2332,6 +2338,10 @@ public abstract class Context {
      * This is just here for sending CONNECTIVITY_ACTION.
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void sendStickyBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, Bundle options);
 
@@ -2340,8 +2350,7 @@ public abstract class Context {
      * {@link #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)}
      * that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * <p>See {@link BroadcastReceiver} for more information on Intent broadcasts.
      *
@@ -2369,6 +2378,10 @@ public abstract class Context {
      * @see #sendStickyOrderedBroadcast(Intent, BroadcastReceiver, Handler, int, String, Bundle)
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void sendStickyOrderedBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user, BroadcastReceiver resultReceiver,
             @Nullable Handler scheduler, int initialCode, @Nullable String initialData,
@@ -2377,8 +2390,7 @@ public abstract class Context {
     /**
      * <p>Version of {@link #removeStickyBroadcast(Intent)} that allows you to specify the
      * user the broadcast will be sent to.  This is not available to applications
-     * that are not pre-installed on the system image.  Using it requires holding
-     * the INTERACT_ACROSS_USERS permission.
+     * that are not pre-installed on the system image.
      *
      * <p>You must hold the {@link android.Manifest.permission#BROADCAST_STICKY}
      * permission in order to use this API.  If you do not hold that
@@ -2396,6 +2408,10 @@ public abstract class Context {
      * @see #sendStickyBroadcastAsUser
      */
     @Deprecated
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.INTERACT_ACROSS_USERS,
+            android.Manifest.permission.BROADCAST_STICKY
+    })
     public abstract void removeStickyBroadcastAsUser(@RequiresPermission Intent intent,
             UserHandle user);
 
@@ -2562,9 +2578,7 @@ public abstract class Context {
      * @hide
      * Same as {@link #registerReceiver(BroadcastReceiver, IntentFilter, String, Handler)
      * but for a specific user.  This receiver will receiver broadcasts that
-     * are sent to the requested user.  It
-     * requires holding the {@link android.Manifest.permission#INTERACT_ACROSS_USERS_FULL}
-     * permission.
+     * are sent to the requested user.
      *
      * @param receiver The BroadcastReceiver to handle the broadcast.
      * @param user UserHandle to send the intent to.
@@ -2583,6 +2597,7 @@ public abstract class Context {
      * @see #unregisterReceiver
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public abstract Intent registerReceiverAsUser(BroadcastReceiver receiver,
             UserHandle user, IntentFilter filter, @Nullable String broadcastPermission,
             @Nullable Handler scheduler);
@@ -2691,6 +2706,7 @@ public abstract class Context {
      * @hide like {@link #startForegroundService(Intent)} but for a specific user.
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract ComponentName startForegroundServiceAsUser(Intent service, UserHandle user);
 
     /**
@@ -2728,11 +2744,13 @@ public abstract class Context {
      * @hide like {@link #startService(Intent)} but for a specific user.
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract ComponentName startServiceAsUser(Intent service, UserHandle user);
 
     /**
      * @hide like {@link #stopService(Intent)} but for a specific user.
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public abstract boolean stopServiceAsUser(Intent service, UserHandle user);
 
     /**
@@ -2792,6 +2810,7 @@ public abstract class Context {
      */
     @SystemApi
     @SuppressWarnings("unused")
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public boolean bindServiceAsUser(@RequiresPermission Intent service, ServiceConnection conn,
             int flags, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
@@ -2803,6 +2822,7 @@ public abstract class Context {
      *
      * @hide
      */
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS)
     public boolean bindServiceAsUser(Intent service, ServiceConnection conn, int flags,
             Handler handler, UserHandle user) {
         throw new RuntimeException("Not implemented. Must override in a subclass.");
index 88aae66..b463ec6 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.content;
 
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.admin.DevicePolicyManager;
 import android.content.pm.ApplicationInfo;
@@ -120,6 +121,7 @@ import java.util.List;
  * @see DevicePolicyManager#setRestrictionsProvider(ComponentName, ComponentName)
  * @see DevicePolicyManager#setApplicationRestrictions(ComponentName, String, Bundle)
  */
+@SystemService(Context.RESTRICTIONS_SERVICE)
 public class RestrictionsManager {
 
     private static final String TAG = "RestrictionsManager";
index 7aaf453..2ebfa8f 100644 (file)
@@ -360,7 +360,7 @@ interface IPackageManager {
      * the operation is completed
      */
      void freeStorageAndNotify(in String volumeUuid, in long freeStorageSize,
-             IPackageDataObserver observer);
+             int storageFlags, IPackageDataObserver observer);
 
     /**
      * Free storage by deleting LRU sorted list of cache files across
@@ -384,7 +384,7 @@ interface IPackageManager {
      * to indicate that no call back is desired.
      */
      void freeStorage(in String volumeUuid, in long freeStorageSize,
-             in IntentSender pi);
+             int storageFlags, in IntentSender pi);
 
     /**
      * Delete all the cache files in an applications cache directory
index 8ead0ec..ed41e79 100644 (file)
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.TestApi;
 import android.app.PendingIntent;
@@ -79,6 +80,7 @@ import java.util.List;
  * Note as of Android O, apps on a managed profile are no longer allowed to access apps on the
  * main profile.  Apps can only access profiles returned by {@link #getProfiles()}.
  */
+@SystemService(Context.LAUNCHER_APPS_SERVICE)
 public class LauncherApps {
 
     static final String TAG = "LauncherApps";
index 4e11233..7f3f35f 100644 (file)
@@ -473,6 +473,7 @@ public class PackageInstaller {
 
     /** {@hide} */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INSTALL_PACKAGES)
     public void setPermissionsResult(int sessionId, boolean accepted) {
         try {
             mInstaller.setPermissionsResult(sessionId, accepted);
@@ -1156,6 +1157,7 @@ public class PackageInstaller {
 
         /** {@hide} */
         @SystemApi
+        @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
         public void setAllocateAggressive(boolean allocateAggressive) {
             if (allocateAggressive) {
                 installFlags |= PackageManager.INSTALL_ALLOCATE_AGGRESSIVE;
index a68c097..be2cd10 100644 (file)
@@ -3208,8 +3208,7 @@ public abstract class PackageManager {
 
     /**
      * Return a List of all packages that are installed on the device, for a
-     * specific user. Requesting a list of installed packages for another user
-     * will require the permission INTERACT_ACROSS_USERS_FULL.
+     * specific user.
      *
      * @param flags Additional option flags to modify the data returned.
      * @param userId The user for whom the installed packages are to be listed
@@ -3224,6 +3223,7 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
     public abstract List<PackageInfo> getInstalledPackagesAsUser(@PackageInfoFlags int flags,
             @UserIdInt int userId);
 
@@ -3365,6 +3365,7 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
     public abstract void grantRuntimePermission(@NonNull String packageName,
             @NonNull String permissionName, @NonNull UserHandle user);
 
@@ -3390,6 +3391,7 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
     public abstract void revokeRuntimePermission(@NonNull String packageName,
             @NonNull String permissionName, @NonNull UserHandle user);
 
@@ -3404,6 +3406,10 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+    })
     public abstract @PermissionFlags int getPermissionFlags(String permissionName,
             String packageName, @NonNull UserHandle user);
 
@@ -3420,6 +3426,10 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
+            android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
+    })
     public abstract void updatePermissionFlags(String permissionName,
             String packageName, @PermissionFlags int flagMask, @PermissionFlags int flagValues,
             @NonNull UserHandle user);
@@ -4719,6 +4729,7 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT)
     public abstract void verifyIntentFilter(int verificationId, int verificationCode,
             List<String> failedDomains);
 
@@ -4766,6 +4777,7 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
     public abstract boolean updateIntentVerificationStatusAsUser(String packageName, int status,
             @UserIdInt int userId);
 
@@ -4826,6 +4838,7 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_PREFERRED_APPLICATIONS)
     public abstract boolean setDefaultBrowserPackageNameAsUser(String packageName,
             @UserIdInt int userId);
 
@@ -5289,6 +5302,7 @@ public abstract class PackageManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
     public abstract void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener);
 
     /**
index 4cee2df..99700df 100644 (file)
@@ -18,7 +18,11 @@ package android.content.pm;
 
 import android.content.ComponentName;
 import android.content.Intent;
+import android.content.pm.PackageManager.ApplicationInfoFlags;
+import android.content.pm.PackageManager.ComponentInfoFlags;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.PackageManager.PackageInfoFlags;
+import android.content.pm.PackageManager.ResolveInfoFlags;
 import android.os.Bundle;
 import android.util.SparseArray;
 
@@ -133,16 +137,40 @@ public abstract class PackageManagerInternal {
     public abstract boolean isPermissionsReviewRequired(String packageName, int userId);
 
     /**
-     * Gets all of the information we know about a particular package.
-     *
-     * @param packageName The package name to find.
-     * @param userId The user under which to check.
-     *
-     * @return An {@link ApplicationInfo} containing information about the
-     *         package, or {@code null} if no application exists with that
-     *         package name.
+     * Retrieve all of the information we know about a particular package/application.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#getPackageInfo(String, int)
+     */
+    public abstract PackageInfo getPackageInfo(String packageName,
+            @PackageInfoFlags int flags, int filterCallingUid, int userId);
+
+    /**
+     * Retrieve all of the information we know about a particular package/application.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#getApplicationInfo(String, int)
+     */
+    public abstract ApplicationInfo getApplicationInfo(String packageName,
+            @ApplicationInfoFlags int flags, int filterCallingUid, int userId);
+
+    /**
+     * Retrieve all of the information we know about a particular activity class.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#getActivityInfo(ComponentName, int)
+     */
+    public abstract ActivityInfo getActivityInfo(ComponentName component,
+            @ComponentInfoFlags int flags, int filterCallingUid, int userId);
+
+    /**
+     * Retrieve all activities that can be performed for the given intent.
+     * @param filterCallingUid The results will be filtered in the context of this UID instead
+     * of the calling UID.
+     * @see PackageManager#queryIntentActivities(Intent, int)
      */
-    public abstract ApplicationInfo getApplicationInfo(String packageName, int userId);
+    public abstract List<ResolveInfo> queryIntentActivities(Intent intent,
+            @ResolveInfoFlags int flags, int filterCallingUid, int userId);
 
     /**
      * Interface to {@link com.android.server.pm.PackageManagerService#getHomeActivitiesAsUser}.
index 9b0bab4..5e5a6fc 100644 (file)
@@ -7000,6 +7000,7 @@ public class PackageParser {
             return null;
         }
         if (!copyNeeded(flags, a.owner, state, a.metaData, userId)) {
+            updateApplicationInfo(a.info.applicationInfo, flags, state);
             return a.info;
         }
         // Make shallow copies so we can store the metadata safely
@@ -7088,6 +7089,7 @@ public class PackageParser {
             return null;
         }
         if (!copyNeeded(flags, s.owner, state, s.metaData, userId)) {
+            updateApplicationInfo(s.info.applicationInfo, flags, state);
             return s.info;
         }
         // Make shallow copies so we can store the metadata safely
@@ -7183,6 +7185,7 @@ public class PackageParser {
         if (!copyNeeded(flags, p.owner, state, p.metaData, userId)
                 && ((flags & PackageManager.GET_URI_PERMISSION_PATTERNS) != 0
                         || p.info.uriPermissionPatterns == null)) {
+            updateApplicationInfo(p.info.applicationInfo, flags, state);
             return p.info;
         }
         // Make shallow copies so we can store the metadata safely
index f779aeb..c0b82b4 100644 (file)
@@ -17,6 +17,7 @@ package android.content.pm;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.app.Activity;
@@ -24,6 +25,7 @@ import android.app.usage.UsageStatsManager;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
+import android.graphics.drawable.AdaptiveIconDrawable;
 import android.os.Build.VERSION_CODES;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -335,6 +337,14 @@ import java.util.List;
  * {@link #isRequestPinShortcutSupported()}. Based on this return value, you might decide to hide
  * the option in your app that allows users to pin a shortcut.
  *
+ * <p class="note"><strong>Note:</strong> See also the support library APIs
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
+ * Context)} and
+ * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
+ * Context, ShortcutInfoCompat, IntentSender)}, which works on Android versions lower than
+ * {@link VERSION_CODES#O} by falling back to the deprecated private intent
+ * {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+ *
  * <h4>Custom Activity for Pinning Shortcuts</h4>
  *
  * <p>You can also create a specialized activity that helps users create shortcuts, complete with
@@ -569,6 +579,7 @@ import java.util.List;
  * All shortcut information is stored in credential encrypted storage, so no shortcuts can be
  * accessed when the user is locked.
  */
+@SystemService(Context.SHORTCUT_SERVICE)
 public class ShortcutManager {
     private static final String TAG = "ShortcutManager";
 
@@ -889,7 +900,7 @@ public class ShortcutManager {
      *
      * <p> Note that this method returns max width of icon's visible part. Hence, it does not take
      * into account the inset introduced by {@link AdaptiveIconDrawable}. To calculate bitmap image
-     * to function as {@link AcaptiveIconDrawable}, multiply
+     * to function as {@link AdaptiveIconDrawable}, multiply
      * 1 + 2 * {@link AdaptiveIconDrawable#getExtraInsetFraction()} to the returned size.
      */
     public int getIconMaxWidth() {
@@ -938,8 +949,15 @@ public class ShortcutManager {
      * Return {@code TRUE} if the app is running on a device whose default launcher supports
      * {@link #requestPinShortcut(ShortcutInfo, IntentSender)}.
      *
-     * <p><b>Note:</b> The return value may change in subsequent calls, if the user changes
-     * the default launcher app.
+     * <p>The return value may change in subsequent calls if the user changes the default launcher
+     * app.
+     *
+     * <p><b>Note:</b> See also the support library counterpart
+     * {@link android.support.v4.content.pm.ShortcutManagerCompat#isRequestPinShortcutSupported(
+     * Context)}, which supports Android versions lower than {@link VERSION_CODES#O} using the
+     * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+     *
+     * @see #requestPinShortcut(ShortcutInfo, IntentSender)
      */
     public boolean isRequestPinShortcutSupported() {
         try {
@@ -963,6 +981,12 @@ public class ShortcutManager {
      * package calls this API multiple times in a row. One possible strategy is to ignore any
      * previous requests.
      *
+     * <p><b>Note:</b> See also the support library counterpart
+     * {@link android.support.v4.content.pm.ShortcutManagerCompat#requestPinShortcut(
+     * Context, ShortcutInfoCompat, IntentSender)},
+     * which supports Android versions lower than {@link VERSION_CODES#O} using the
+     * legacy private intent {@code com.android.launcher.action.INSTALL_SHORTCUT}.
+     *
      * @param shortcut Shortcut to pin.  If an app wants to pin an existing (either static
      *     or dynamic) shortcut, then it only needs to have an ID. Although other fields don't have
      *     to be set, the target shortcut must be enabled.
index b221e16..c7a33ff 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -24,14 +25,8 @@ import android.util.Log;
 
 /**
  * Class that operates consumer infrared on the device.
- *
- * <p>
- * To obtain an instance of the system infrared transmitter, call
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with
- * {@link android.content.Context#CONSUMER_IR_SERVICE} as the argument.
- * </p>
  */
+@SystemService(Context.CONSUMER_IR_SERVICE)
 public final class ConsumerIrManager {
     private static final String TAG = "ConsumerIr";
 
index ed56391..4bc62b1 100644 (file)
@@ -17,6 +17,8 @@
 package android.hardware;
 
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Build;
 import android.os.Handler;
 import android.os.MemoryFile;
@@ -30,10 +32,7 @@ import java.util.List;
 /**
  * <p>
  * SensorManager lets you access the device's {@link android.hardware.Sensor
- * sensors}. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#SENSOR_SERVICE}.
+ * sensors}.
  * </p>
  * <p>
  * Always make sure to disable sensors you don't need, especially when your
@@ -79,6 +78,7 @@ import java.util.List;
  * @see Sensor
  *
  */
+@SystemService(Context.SENSOR_SERVICE)
 public abstract class SensorManager {
     /** @hide */
     protected static final String TAG = "SensorManager";
index 83f7649..610f6a5 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.hardware;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
@@ -25,6 +26,7 @@ import java.io.IOException;
 /**
  * @hide
  */
+@SystemService(Context.SERIAL_SERVICE)
 public class SerialManager {
     private static final String TAG = "SerialManager";
 
index f61032e..1b150bf 100644 (file)
@@ -17,6 +17,7 @@
 package android.hardware.camera2;
 
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
@@ -44,15 +45,11 @@ import java.util.ArrayList;
  * <p>A system service manager for detecting, characterizing, and connecting to
  * {@link CameraDevice CameraDevices}.</p>
  *
- * <p>You can get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p>
- *
- * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre>
- *
  * <p>For more details about communicating with camera devices, read the Camera
  * developer guide or the {@link android.hardware.camera2 camera2}
  * package documentation.</p>
  */
+@SystemService(Context.CAMERA_SERVICE)
 public final class CameraManager {
 
     private static final String TAG = "CameraManager";
index 266be9a..6a02b6b 100644 (file)
@@ -18,6 +18,7 @@ package android.hardware.display;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.media.projection.MediaProjection;
 import android.os.Handler;
@@ -29,13 +30,8 @@ import java.util.ArrayList;
 
 /**
  * Manages the properties of attached displays.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#DISPLAY_SERVICE}.
- * </p>
  */
+@SystemService(Context.DISPLAY_SERVICE)
 public final class DisplayManager {
     private static final String TAG = "DisplayManager";
     private static final boolean DEBUG = false;
index 324a08c..b51a791 100644 (file)
@@ -19,6 +19,7 @@ package android.hardware.fingerprint;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.os.Binder;
@@ -47,12 +48,8 @@ import static android.Manifest.permission.USE_FINGERPRINT;
 
 /**
  * A class that coordinates access to the fingerprint hardware.
- * <p>
- * Use {@link android.content.Context#getSystemService(java.lang.String)}
- * with argument {@link android.content.Context#FINGERPRINT_SERVICE} to get
- * an instance of this class.
  */
-
+@SystemService(Context.FINGERPRINT_SERVICE)
 public class FingerprintManager {
     private static final String TAG = "FingerprintManager";
     private static final boolean DEBUG = true;
index 27e2a50..a772cbe 100644 (file)
 package android.hardware.hdmi;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.SuppressLint;
+import android.content.Context;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.os.RemoteException;
 import android.util.ArrayMap;
 import android.util.Log;
@@ -37,6 +41,7 @@ import android.util.Log;
  * @hide
  */
 @SystemApi
+@SystemService(Context.HDMI_CONTROL_SERVICE)
 public final class HdmiControlManager {
     private static final String TAG = "HdmiControlManager";
 
@@ -295,6 +300,7 @@ public final class HdmiControlManager {
      * See {@link HdmiDeviceInfo#DEVICE_TV}
      */
     @Nullable
+    @SuppressLint("Doclava125")
     public HdmiClient getClient(int type) {
         if (mService == null) {
             return null;
@@ -319,6 +325,7 @@ public final class HdmiControlManager {
      * @return {@link HdmiPlaybackClient} instance. {@code null} on failure.
      */
     @Nullable
+    @SuppressLint("Doclava125")
     public HdmiPlaybackClient getPlaybackClient() {
         return (HdmiPlaybackClient) getClient(HdmiDeviceInfo.DEVICE_PLAYBACK);
     }
@@ -333,6 +340,7 @@ public final class HdmiControlManager {
      * @return {@link HdmiTvClient} instance. {@code null} on failure.
      */
     @Nullable
+    @SuppressLint("Doclava125")
     public HdmiTvClient getTvClient() {
         return (HdmiTvClient) getClient(HdmiDeviceInfo.DEVICE_TV);
     }
@@ -343,6 +351,7 @@ public final class HdmiControlManager {
      *
      * @param isStandbyModeOn target status of the system's standby mode
      */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
     public void setStandbyMode(boolean isStandbyModeOn) {
         try {
             mService.setStandbyMode(isStandbyModeOn);
@@ -403,6 +412,7 @@ public final class HdmiControlManager {
      * @param listener {@link HotplugEventListener} instance
      * @see HdmiControlManager#removeHotplugEventListener(HotplugEventListener)
      */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
     public void addHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
             Log.e(TAG, "HdmiControlService is not available");
@@ -426,6 +436,7 @@ public final class HdmiControlManager {
      *
      * @param listener {@link HotplugEventListener} instance to be removed
      */
+    @RequiresPermission(android.Manifest.permission.HDMI_CEC)
     public void removeHotplugEventListener(HotplugEventListener listener) {
         if (mService == null) {
             Log.e(TAG, "HdmiControlService is not available");
index 631b77d..5149e93 100644 (file)
@@ -21,6 +21,7 @@ import com.android.internal.os.SomeArgs;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -53,13 +54,8 @@ import java.util.List;
 
 /**
  * Provides information about input devices and available key layouts.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument
- * {@link android.content.Context#INPUT_SERVICE}.
- * </p>
  */
+@SystemService(Context.INPUT_SERVICE)
 public final class InputManager {
     private static final String TAG = "InputManager";
     private static final boolean DEBUG = false;
index 7c4df47..6050046 100644 (file)
  */
 package android.hardware.location;
 
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -33,6 +36,7 @@ import android.util.Log;
  * @hide
  */
 @SystemApi
+@SystemService(Context.CONTEXTHUB_SERVICE)
 public final class ContextHubManager {
 
     private static final String TAG = "ContextHubManager";
@@ -91,6 +95,7 @@ public final class ContextHubManager {
      * Get a handle to all the context hubs in the system
      * @return array of context hub handles
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int[] getContextHubHandles() {
         try {
             return mService.getContextHubHandles();
@@ -107,6 +112,7 @@ public final class ContextHubManager {
      *
      * @see ContextHubInfo
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public ContextHubInfo getContextHubInfo(int hubHandle) {
         try {
             return mService.getContextHubInfo(hubHandle);
@@ -134,6 +140,7 @@ public final class ContextHubManager {
      *
      * @see NanoApp
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int loadNanoApp(int hubHandle, NanoApp app) {
         try {
             return mService.loadNanoApp(hubHandle, app);
@@ -157,6 +164,7 @@ public final class ContextHubManager {
      * @return 0 if the command for unloading was sent to the context hub;
      *         -1 otherwise
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int unloadNanoApp(int nanoAppHandle) {
         try {
             return mService.unloadNanoApp(nanoAppHandle);
@@ -191,6 +199,7 @@ public final class ContextHubManager {
      *
      * @see NanoAppInstanceInfo
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public NanoAppInstanceInfo getNanoAppInstanceInfo(int nanoAppHandle) {
         try {
             return mService.getNanoAppInstanceInfo(nanoAppHandle);
@@ -209,6 +218,7 @@ public final class ContextHubManager {
      *
      * @return int[] Array of handles to any found nano apps
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int[] findNanoAppOnHub(int hubHandle, NanoAppFilter filter) {
         try {
             return mService.findNanoAppOnHub(hubHandle, filter);
@@ -236,6 +246,7 @@ public final class ContextHubManager {
      *
      * @return int 0 on success, -1 otherwise
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public int sendMessage(int hubHandle, int nanoAppHandle, ContextHubMessage message) {
         try {
             return mService.sendMessage(hubHandle, nanoAppHandle, message);
@@ -253,6 +264,7 @@ public final class ContextHubManager {
      *
      * @return int 0 on success, -1 otherwise
      */
+    @SuppressLint("Doclava125")
     public int registerCallback(Callback callback) {
         return registerCallback(callback, null);
     }
@@ -281,6 +293,7 @@ public final class ContextHubManager {
      *
      * @return int 0 on success, -1 otherwise
      */
+    @SuppressLint("Doclava125")
     public int registerCallback(Callback callback, Handler handler) {
         synchronized(this) {
             if (mCallback != null) {
@@ -302,6 +315,7 @@ public final class ContextHubManager {
      *
      * @return int 0 on success, -1 otherwise
      */
+    @SuppressLint("Doclava125")
     public int unregisterCallback(Callback callback) {
       synchronized(this) {
           if (callback != mCallback) {
index 14bb923..403b13c 100644 (file)
@@ -17,6 +17,7 @@
 package android.hardware.radio;
 
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Parcel;
@@ -32,6 +33,7 @@ import java.util.Arrays;
  * @hide
  */
 @SystemApi
+@SystemService(Context.RADIO_SERVICE)
 public class RadioManager {
 
     /** Method return status: successful operation */
index b2a2aaf..33a92fd 100644 (file)
@@ -19,6 +19,7 @@ package android.hardware.usb;
 
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.app.PendingIntent;
 import android.content.ComponentName;
@@ -38,18 +39,13 @@ import java.util.HashMap;
  * This class allows you to access the state of USB and communicate with USB devices.
  * Currently only host mode is supported in the public API.
  *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * {@samplecode
- * UsbManager manager = (UsbManager) getSystemService(Context.USB_SERVICE);}
- *
  * <div class="special reference">
  * <h3>Developer Guides</h3>
  * <p>For more information about communicating with USB hardware, read the
  * <a href="{@docRoot}guide/topics/connectivity/usb/index.html">USB developer guide</a>.</p>
  * </div>
  */
+@SystemService(Context.USB_SERVICE)
 public class UsbManager {
     private static final String TAG = "UsbManager";
 
index b0cc38c..e64cbcd 100644 (file)
@@ -23,6 +23,7 @@ import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -64,9 +65,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 /**
  * Class that answers queries about the state of network connectivity. It also
- * notifies applications when network connectivity changes. Get an instance
- * of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.CONNECTIVITY_SERVICE)}.
+ * notifies applications when network connectivity changes.
  * <p>
  * The primary responsibilities of this class are to:
  * <ol>
@@ -80,6 +79,7 @@ import java.util.concurrent.atomic.AtomicInteger;
  * traffic</li>
  * </ol>
  */
+@SystemService(Context.CONNECTIVITY_SERVICE)
 public class ConnectivityManager {
     private static final String TAG = "ConnectivityManager";
 
@@ -2105,6 +2105,7 @@ public class ConnectivityManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void startTethering(int type, boolean showProvisioningUi,
             final OnStartTetheringCallback callback, Handler handler) {
         checkNotNull(callback, "OnStartTetheringCallback cannot be null.");
@@ -2139,6 +2140,7 @@ public class ConnectivityManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public void stopTethering(int type) {
         try {
             mService.stopTethering(type);
index 664b7b4..31a3096 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.net.IEthernetManager;
 import android.net.IEthernetServiceListener;
@@ -31,6 +32,7 @@ import java.util.ArrayList;
  *
  * @hide
  */
+@SystemService(Context.ETHERNET_SERVICE)
 public class EthernetManager {
     private static final String TAG = "EthernetManager";
     private static final int MSG_AVAILABILITY_CHANGED = 1000;
index 114e46e..e3cda5e 100644 (file)
@@ -18,6 +18,8 @@ package android.net;
 import static com.android.internal.util.Preconditions.checkNotNull;
 
 import android.annotation.NonNull;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
@@ -34,12 +36,9 @@ import java.net.Socket;
  * This class contains methods for managing IPsec sessions, which will perform kernel-space
  * encryption and decryption of socket or Network traffic.
  *
- * <p>An IpSecManager may be obtained by calling {@link
- * android.content.Context#getSystemService(String) Context#getSystemService(String)} with {@link
- * android.content.Context#IPSEC_SERVICE Context#IPSEC_SERVICE}
- *
  * @hide
  */
+@SystemService(Context.IPSEC_SERVICE)
 public final class IpSecManager {
     private static final String TAG = "IpSecManager";
 
index 6de28b7..c119b63 100644 (file)
@@ -66,15 +66,7 @@ public class NetworkBadging {
      */
     @NonNull public static Drawable getWifiIcon(
             @IntRange(from=0, to=4) int signalLevel, @Badging int badging, @Nullable Theme theme) {
-        Resources resources = Resources.getSystem();
-        if (badging == BADGING_NONE) {
-            return resources.getDrawable(getWifiSignalResource(signalLevel), theme);
-        }
-        Drawable[] layers = new Drawable[] {
-                resources.getDrawable(getBadgedWifiSignalResource(signalLevel), theme),
-                resources.getDrawable(getWifiBadgeResource(badging), theme)
-        };
-        return new LayerDrawable(layers);
+        return Resources.getSystem().getDrawable(getWifiSignalResource(signalLevel), theme);
     }
 
     /**
@@ -134,31 +126,4 @@ public class NetworkBadging {
                 throw new IllegalArgumentException("Invalid signal level: " + signalLevel);
         }
     }
-
-    /**
-     * Returns the wifi quality badge resource id for the the given badging balue.
-     *
-     * <p>This badge should be displayed with the badge signal resource retrieved from
-     * {@link #getBadgedWifiSignalResource(int)}.
-     *
-     * @param badging {@see NetworkBadging#Badging} from {@link ScoredNetwork#calculateBadge(int)}.
-     * @return the @DrawableRes for the icon or {@link View#NO_ID} for
-     *         {@link NetworkBadging#BADGING_NONE}
-     * @throws IllegalArgumentException for an invalid badging value.
-     * @hide
-     */
-    @DrawableRes private static int getWifiBadgeResource(@Badging int badging) {
-        switch (badging) {
-            case BADGING_NONE:
-                return View.NO_ID;
-            case BADGING_SD:
-                return com.android.internal.R.drawable.ic_signal_wifi_badged_sd;
-            case BADGING_HD:
-                return com.android.internal.R.drawable.ic_signal_wifi_badged_hd;
-            case BADGING_4K:
-                return com.android.internal.R.drawable.ic_signal_wifi_badged_4k;
-            default:
-                throw new IllegalArgumentException("No resource found for badge: " + badging);
-        }
-    }
 }
index 43fab03..4d94a55 100644 (file)
@@ -19,6 +19,7 @@ package android.net;
 import static android.content.pm.PackageManager.GET_SIGNATURES;
 import static android.net.NetworkPolicy.CYCLE_NONE;
 
+import android.annotation.SystemService;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.Intent;
@@ -40,6 +41,7 @@ import java.util.TimeZone;
  *
  * {@hide}
  */
+@SystemService(Context.NETWORK_POLICY_SERVICE)
 public class NetworkPolicyManager {
 
     /* POLICY_* are masks and can be ORed, although currently they are not.*/
index 9f6e45c..7e0c9ce 100644 (file)
@@ -19,9 +19,11 @@ package android.net;
 import android.Manifest.permission;
 import android.annotation.IntDef;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -34,12 +36,6 @@ import java.util.List;
 /**
  * Class that manages communication between network subsystems and a network scorer.
  *
- * <p>You can get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)}:
- *
- * <pre>NetworkScoreManager manager =
- *     (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE)</pre>
- *
  * <p>A network scorer is any application which:
  * <ul>
  * <li>Declares the {@link permission#SCORE_NETWORKS} permission.
@@ -51,6 +47,7 @@ import java.util.List;
  * @hide
  */
 @SystemApi
+@SystemService(Context.NETWORK_SCORE_SERVICE)
 public class NetworkScoreManager {
     /**
      * Activity action: ask the user to change the active network scorer. This will show a dialog
@@ -243,6 +240,7 @@ public class NetworkScoreManager {
      * @hide
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
     public NetworkScorerAppData getActiveScorer() {
         try {
             return mService.getActiveScorer();
@@ -276,6 +274,7 @@ public class NetworkScoreManager {
      * @return whether the update was successful.
      * @throws SecurityException if the caller is not the active scorer.
      */
+    @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
     public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
         try {
             return mService.updateScores(networks);
@@ -296,6 +295,7 @@ public class NetworkScoreManager {
      * @return whether the clear was successful.
      * @throws SecurityException if the caller is not the active scorer or privileged.
      */
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
     public boolean clearScores() throws SecurityException {
         try {
             return mService.clearScores();
@@ -316,6 +316,7 @@ public class NetworkScoreManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SCORE_NETWORKS)
     public boolean setActiveScorer(String packageName) throws SecurityException {
         try {
             return mService.setActiveScorer(packageName);
@@ -331,6 +332,7 @@ public class NetworkScoreManager {
      *
      * @throws SecurityException if the caller is neither the active scorer nor the system.
      */
+    @RequiresPermission(android.Manifest.permission.REQUEST_NETWORK_SCORES)
     public void disableScoring() throws SecurityException {
         try {
             mService.disableScoring();
index fc66395..f934616 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.net;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.DownloadManager;
 import android.app.backup.BackupManager;
@@ -243,6 +244,7 @@ public class TrafficStats {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public static void setThreadStatsUid(int uid) {
         NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
     }
@@ -255,6 +257,7 @@ public class TrafficStats {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public static void clearThreadStatsUid() {
         NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
     }
index c6daa15..2d9860c 100644 (file)
@@ -19,6 +19,7 @@ package android.net;
 import static android.system.OsConstants.AF_INET;
 import static android.system.OsConstants.AF_INET6;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.Activity;
 import android.app.PendingIntent;
@@ -177,6 +178,7 @@ public class VpnService extends Service {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CONTROL_VPN)
     public static void prepareAndAuthorize(Context context) {
         IConnectivityManager cm = getService();
         String packageName = context.getPackageName();
index 1dde3ca..2d480a1 100644 (file)
@@ -17,6 +17,7 @@
 package android.net.nsd;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.os.Handler;
@@ -113,11 +114,9 @@ import com.android.internal.util.Protocol;
  * http://www.iana.org/form/ports-service. Existing services can be found at
  * http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xml
  *
- * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.NSD_SERVICE)}.
- *
  * {@see NsdServiceInfo}
  */
+@SystemService(Context.NSD_SERVICE)
 public final class NsdManager {
     private static final String TAG = NsdManager.class.getSimpleName();
     private static final boolean DBG = false;
index c027d54..133146d 100644 (file)
@@ -25,6 +25,6 @@ import android.nfc.Tag;
 interface IAppCallback
 {
     BeamShareData createBeamShareData(byte peerLlcpVersion);
-    void onNdefPushComplete(byte peerLlcpVersion);
-    void onTagDiscovered(in Tag tag);
+    oneway void onNdefPushComplete(byte peerLlcpVersion);
+    oneway void onTagDiscovered(in Tag tag);
 }
index 2c9ce3f..093a9b4 100644 (file)
@@ -938,7 +938,7 @@ public final class NdefRecord implements Parcelable {
      */
     void writeToByteBuffer(ByteBuffer buffer, boolean mb, boolean me) {
         boolean sr = mPayload.length < 256;
-        boolean il = mId.length > 0;
+        boolean il = mTnf == TNF_EMPTY ? true : mId.length > 0;
 
         byte flags = (byte)((mb ? FLAG_MB : 0) | (me ? FLAG_ME : 0) |
                 (sr ? FLAG_SR : 0) | (il ? FLAG_IL : 0) | mTnf);
@@ -966,7 +966,7 @@ public final class NdefRecord implements Parcelable {
         int length = 3 + mType.length + mId.length + mPayload.length;
 
         boolean sr = mPayload.length < 256;
-        boolean il = mId.length > 0;
+        boolean il = mTnf == TNF_EMPTY ? true : mId.length > 0;
 
         if (!sr) length += 3;
         if (il) length += 1;
index 783c25a..48869c7 100644 (file)
@@ -18,6 +18,7 @@ package android.nfc;
 
 import java.util.HashMap;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
@@ -725,6 +726,7 @@ public final class NfcAdapter {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean enable() {
         try {
             return sService.enable();
@@ -753,6 +755,7 @@ public final class NfcAdapter {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean disable() {
         try {
             return sService.disable(true);
@@ -767,6 +770,7 @@ public final class NfcAdapter {
      * @hide
     */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean disable(boolean persist) {
         try {
             return sService.disable(persist);
@@ -1552,6 +1556,7 @@ public final class NfcAdapter {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean enableNdefPush() {
         if (!sHasNfcFeature) {
             throw new UnsupportedOperationException();
@@ -1570,6 +1575,7 @@ public final class NfcAdapter {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean disableNdefPush() {
         synchronized (NfcAdapter.class) {
             if (!sHasNfcFeature) {
@@ -1736,6 +1742,7 @@ public final class NfcAdapter {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean addNfcUnlockHandler(final NfcUnlockHandler unlockHandler,
                                        String[] tagTechnologies) {
         synchronized (NfcAdapter.class) {
@@ -1785,6 +1792,7 @@ public final class NfcAdapter {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS)
     public boolean removeNfcUnlockHandler(NfcUnlockHandler unlockHandler) {
         synchronized (NfcAdapter.class) {
             if (!sHasNfcFeature) {
index ea08014..50d6745 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.nfc;
 
+import android.annotation.SystemService;
 import android.content.Context;
 
 /**
@@ -34,9 +35,9 @@ import android.content.Context;
  * <a href="{@docRoot}guide/topics/nfc/index.html">Near Field Communication</a> developer guide.</p>
  * </div>
  *
- * @see Context#getSystemService
  * @see NfcAdapter#getDefaultAdapter(android.content.Context)
  */
+@SystemService(Context.NFC_SERVICE)
 public final class NfcManager {
     private final NfcAdapter mAdapter;
 
index 734d89e..f715f50 100644 (file)
@@ -16,6 +16,8 @@
 
 package android.os;
 
+import android.annotation.SystemService;
+import android.content.Context;
 import android.hardware.health.V1_0.Constants;
 import com.android.internal.app.IBatteryStats;
 
@@ -24,6 +26,7 @@ import com.android.internal.app.IBatteryStats;
  * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent, and
  * provides a method for querying battery and charging properties.
  */
+@SystemService(Context.BATTERY_SERVICE)
 public class BatteryManager {
     /**
      * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
index 499d6bb..635df4c 100644 (file)
@@ -162,6 +162,11 @@ public abstract class BatteryStats implements Parcelable {
     public static final int AGGREGATED_WAKE_TYPE_PARTIAL = 20;
 
     /**
+     * A constant indicating a bluetooth scan timer for unoptimized scans.
+     */
+    public static final int BLUETOOTH_UNOPTIMIZED_SCAN_ON = 21;
+
+    /**
      * Include all of the data in the stats, including previously saved data.
      */
     public static final int STATS_SINCE_CHARGED = 0;
@@ -191,8 +196,12 @@ public abstract class BatteryStats implements Parcelable {
      * New in version 21:
      *   - Actual (not just apportioned) Wakelock time is also recorded.
      *   - Aggregated partial wakelock time (per uid, instead of per wakelock) is recorded.
+     *   - BLE scan result count
+     *   - CPU frequency time per uid
+     * New in version 22:
+     *   - BLE scan result background count, BLE unoptimized scan time
      */
-    static final String CHECKIN_VERSION = "21";
+    static final String CHECKIN_VERSION = "23";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -217,9 +226,10 @@ public abstract class BatteryStats implements Parcelable {
     private static final String STATE_TIME_DATA = "st";
     // wl line is:
     // BATTERY_STATS_CHECKIN_VERSION, uid, which, "wl", name,
-    // full totalTime,    'f', count, current duration, max duration, total duration,
-    // partial totalTime, 'p', count, current duration, max duration, total duration,
-    // window totalTime,  'w', count, current duration, max duration, total duration
+    // full        totalTime, 'f',  count, current duration, max duration, total duration,
+    // partial     totalTime, 'p',  count, current duration, max duration, total duration,
+    // bg partial  totalTime, 'bp', count, current duration, max duration, total duration,
+    // window      totalTime, 'w',  count, current duration, max duration, total duration
     // [Currently, full and window wakelocks have durations current = max = total = -1]
     private static final String WAKELOCK_DATA = "wl";
     // awl line is:
@@ -565,7 +575,10 @@ public abstract class BatteryStats implements Parcelable {
         public abstract Timer getForegroundActivityTimer();
         public abstract Timer getBluetoothScanTimer();
         public abstract Timer getBluetoothScanBackgroundTimer();
+        public abstract Timer getBluetoothUnoptimizedScanTimer();
+        public abstract Timer getBluetoothUnoptimizedScanBackgroundTimer();
         public abstract Counter getBluetoothScanResultCounter();
+        public abstract Counter getBluetoothScanResultBgCounter();
 
         public abstract long[] getCpuFreqTimes(int which);
         public abstract long[] getScreenOffCpuFreqTimes(int which);
@@ -3038,6 +3051,7 @@ public abstract class BatteryStats implements Parcelable {
             boolean wifiOnly) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+        final long rawRealtimeMs = (rawRealtime + 500) / 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
         final long whichBatteryRealtime = computeBatteryRealtime(rawRealtime, which);
@@ -3424,15 +3438,33 @@ public abstract class BatteryStats implements Parcelable {
                     final int count = bleTimer.getCountLocked(which);
                     final Timer bleTimerBg = u.getBluetoothScanBackgroundTimer();
                     final int countBg = bleTimerBg != null ? bleTimerBg.getCountLocked(which) : 0;
-                    final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                     // 'actualTime' are unpooled and always since reset (regardless of 'which')
                     final long actualTime = bleTimer.getTotalDurationMsLocked(rawRealtimeMs);
                     final long actualTimeBg = bleTimerBg != null ?
                             bleTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0;
+                    // Result counters
                     final int resultCount = u.getBluetoothScanResultCounter() != null ?
                             u.getBluetoothScanResultCounter().getCountLocked(which) : 0;
+                    final int resultCountBg = u.getBluetoothScanResultBgCounter() != null ?
+                            u.getBluetoothScanResultBgCounter().getCountLocked(which) : 0;
+                    // Unoptimized scan timer. Unpooled and since reset (regardless of 'which').
+                    final Timer unoptimizedScanTimer = u.getBluetoothUnoptimizedScanTimer();
+                    final long unoptimizedScanTotalTime = unoptimizedScanTimer != null ?
+                            unoptimizedScanTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
+                    final long unoptimizedScanMaxTime = unoptimizedScanTimer != null ?
+                            unoptimizedScanTimer.getMaxDurationMsLocked(rawRealtimeMs) : 0;
+                    // Unoptimized bg scan timer. Unpooled and since reset (regardless of 'which').
+                    final Timer unoptimizedScanTimerBg =
+                            u.getBluetoothUnoptimizedScanBackgroundTimer();
+                    final long unoptimizedScanTotalTimeBg = unoptimizedScanTimerBg != null ?
+                            unoptimizedScanTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0;
+                    final long unoptimizedScanMaxTimeBg = unoptimizedScanTimerBg != null ?
+                            unoptimizedScanTimerBg.getMaxDurationMsLocked(rawRealtimeMs) : 0;
+
                     dumpLine(pw, uid, category, BLUETOOTH_MISC_DATA, totalTime, count,
-                            countBg, actualTime, actualTimeBg, resultCount);
+                            countBg, actualTime, actualTimeBg, resultCount, resultCountBg,
+                            unoptimizedScanTotalTime, unoptimizedScanTotalTimeBg,
+                            unoptimizedScanMaxTime, unoptimizedScanMaxTimeBg);
                 }
             }
 
@@ -3454,11 +3486,11 @@ public abstract class BatteryStats implements Parcelable {
 
             if (u.getAggregatedPartialWakelockTimer() != null) {
                 final Timer timer = u.getAggregatedPartialWakelockTimer();
-                // Convert from microseconds to milliseconds with rounding
-                final long totTimeMs = (timer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                // Times are since reset (regardless of 'which')
+                final long totTimeMs = timer.getTotalDurationMsLocked(rawRealtimeMs);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTimeMs = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
                 dumpLine(pw, uid, category, AGGREGATED_WAKELOCK_DATA, totTimeMs, bgTimeMs);
             }
 
@@ -3469,8 +3501,11 @@ public abstract class BatteryStats implements Parcelable {
                 sb.setLength(0);
                 linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_FULL),
                         rawRealtime, "f", which, linePrefix);
-                linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL),
+                final Timer pTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+                linePrefix = printWakeLockCheckin(sb, pTimer,
                         rawRealtime, "p", which, linePrefix);
+                linePrefix = printWakeLockCheckin(sb, pTimer != null ? pTimer.getSubTimer() : null,
+                        rawRealtime, "bp", which, linePrefix);
                 linePrefix = printWakeLockCheckin(sb, wl.getWakeTime(WAKE_TYPE_WINDOW),
                         rawRealtime, "w", which, linePrefix);
 
@@ -3492,7 +3527,7 @@ public abstract class BatteryStats implements Parcelable {
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, SYNC_DATA, "\"" + syncs.keyAt(isy) + "\"",
@@ -3508,7 +3543,7 @@ public abstract class BatteryStats implements Parcelable {
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 if (totalTime != 0) {
                     dumpLine(pw, uid, category, JOB_DATA, "\"" + jobs.keyAt(ij) + "\"",
@@ -3539,7 +3574,6 @@ public abstract class BatteryStats implements Parcelable {
                         final int count = timer.getCountLocked(which);
                         final Timer bgTimer = se.getSensorBackgroundTime();
                         final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : 0;
-                        final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                         // 'actualTime' are unpooled and always since reset (regardless of 'which')
                         final long actualTime = timer.getTotalDurationMsLocked(rawRealtimeMs);
                         final long bgActualTime = bgTimer != null ?
@@ -3680,6 +3714,7 @@ public abstract class BatteryStats implements Parcelable {
             int reqUid, boolean wifiOnly) {
         final long rawUptime = SystemClock.uptimeMillis() * 1000;
         final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
+        final long rawRealtimeMs = (rawRealtime + 500) / 1000;
         final long batteryUptime = getBatteryUptime(rawUptime);
 
         final long whichBatteryUptime = computeBatteryUptime(rawUptime, which);
@@ -4620,39 +4655,98 @@ public abstract class BatteryStats implements Parcelable {
                     final int count = bleTimer.getCountLocked(which);
                     final Timer bleTimerBg = u.getBluetoothScanBackgroundTimer();
                     final int countBg = bleTimerBg != null ? bleTimerBg.getCountLocked(which) : 0;
-                    final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                     // 'actualTime' are unpooled and always since reset (regardless of 'which')
                     final long actualTimeMs = bleTimer.getTotalDurationMsLocked(rawRealtimeMs);
                     final long actualTimeMsBg = bleTimerBg != null ?
                             bleTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0;
+                    // Result counters
                     final int resultCount = u.getBluetoothScanResultCounter() != null ?
                             u.getBluetoothScanResultCounter().getCountLocked(which) : 0;
+                    final int resultCountBg = u.getBluetoothScanResultBgCounter() != null ?
+                            u.getBluetoothScanResultBgCounter().getCountLocked(which) : 0;
+                    // Unoptimized scan timer. Unpooled and since reset (regardless of 'which').
+                    final Timer unoptimizedScanTimer = u.getBluetoothUnoptimizedScanTimer();
+                    final long unoptimizedScanTotalTime = unoptimizedScanTimer != null ?
+                            unoptimizedScanTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
+                    final long unoptimizedScanMaxTime = unoptimizedScanTimer != null ?
+                            unoptimizedScanTimer.getMaxDurationMsLocked(rawRealtimeMs) : 0;
+                    // Unoptimized bg scan timer. Unpooled and since reset (regardless of 'which').
+                    final Timer unoptimizedScanTimerBg =
+                            u.getBluetoothUnoptimizedScanBackgroundTimer();
+                    final long unoptimizedScanTotalTimeBg = unoptimizedScanTimerBg != null ?
+                            unoptimizedScanTimerBg.getTotalDurationMsLocked(rawRealtimeMs) : 0;
+                    final long unoptimizedScanMaxTimeBg = unoptimizedScanTimerBg != null ?
+                            unoptimizedScanTimerBg.getMaxDurationMsLocked(rawRealtimeMs) : 0;
 
                     sb.setLength(0);
-                    sb.append(prefix);
-                    sb.append("    ");
-                    sb.append("Bluetooth Scan");
-                    sb.append(": ");
                     if (actualTimeMs != totalTimeMs) {
+                        sb.append(prefix);
+                        sb.append("    Bluetooth Scan (total blamed realtime): ");
                         formatTimeMs(sb, totalTimeMs);
-                        sb.append("blamed realtime, ");
+                        sb.append(" (");
+                        sb.append(count);
+                        sb.append(" times)");
+                        if (bleTimer.isRunningLocked()) {
+                            sb.append(" (currently running)");
+                        }
+                        sb.append("\n");
                     }
-                    formatTimeMs(sb, actualTimeMs); // since reset, regardless of 'which'
-                    sb.append("realtime (");
+
+                    sb.append(prefix);
+                    sb.append("    Bluetooth Scan (total actual realtime): ");
+                    formatTimeMs(sb, actualTimeMs); // since reset, ignores 'which'
+                    sb.append(" (");
                     sb.append(count);
                     sb.append(" times)");
                     if (bleTimer.isRunningLocked()) {
-                            sb.append(" (running)");
+                            sb.append(" (currently running)");
                     }
-                    if (actualTimeMsBg != 0 || countBg > 0) {
-                        sb.append(", ");
-                        formatTimeMs(sb, actualTimeMsBg); // since reset, regardless of 'which'
-                        sb.append("background (");
+                    sb.append("\n");
+                    if (actualTimeMsBg > 0 || countBg > 0) {
+                        sb.append(prefix);
+                        sb.append("    Bluetooth Scan (background realtime): ");
+                        formatTimeMs(sb, actualTimeMsBg); // since reset, ignores 'which'
+                        sb.append(" (");
                         sb.append(countBg);
                         sb.append(" times)");
+                        if (bleTimerBg != null && bleTimerBg.isRunningLocked()) {
+                            sb.append(" (currently running in background)");
+                        }
+                        sb.append("\n");
                     }
-                    sb.append("; Results count ");
+
+                    sb.append(prefix);
+                    sb.append("    Bluetooth Scan Results: ");
                     sb.append(resultCount);
+                    sb.append(" (");
+                    sb.append(resultCountBg);
+                    sb.append(" in background)");
+
+                    if (unoptimizedScanTotalTime > 0 || unoptimizedScanTotalTimeBg > 0) {
+                        sb.append("\n");
+                        sb.append(prefix);
+                        sb.append("    Unoptimized Bluetooth Scan (realtime): ");
+                        formatTimeMs(sb, unoptimizedScanTotalTime); // since reset, ignores 'which'
+                        sb.append(" (max ");
+                        formatTimeMs(sb, unoptimizedScanMaxTime); // since reset, ignores 'which'
+                        sb.append(")");
+                        if (unoptimizedScanTimer != null
+                                && unoptimizedScanTimer.isRunningLocked()) {
+                            sb.append(" (currently running unoptimized)");
+                        }
+                        if (unoptimizedScanTimerBg != null && unoptimizedScanTotalTimeBg > 0) {
+                            sb.append("\n");
+                            sb.append(prefix);
+                            sb.append("    Unoptimized Bluetooth Scan (background realtime): ");
+                            formatTimeMs(sb, unoptimizedScanTotalTimeBg); // since reset
+                            sb.append(" (max ");
+                            formatTimeMs(sb, unoptimizedScanMaxTimeBg); // since reset
+                            sb.append(")");
+                            if (unoptimizedScanTimerBg.isRunningLocked()) {
+                                sb.append(" (currently running unoptimized in background)");
+                            }
+                        }
+                    }
                     pw.println(sb.toString());
                     uidActivity = true;
                 }
@@ -4696,8 +4790,11 @@ public abstract class BatteryStats implements Parcelable {
                 sb.append(wakelocks.keyAt(iw));
                 linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_FULL), rawRealtime,
                         "full", which, linePrefix);
-                linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_PARTIAL), rawRealtime,
+                final Timer pTimer = wl.getWakeTime(WAKE_TYPE_PARTIAL);
+                linePrefix = printWakeLock(sb, pTimer, rawRealtime,
                         "partial", which, linePrefix);
+                linePrefix = printWakeLock(sb, pTimer != null ? pTimer.getSubTimer() : null,
+                        rawRealtime, "background partial", which, linePrefix);
                 linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_WINDOW), rawRealtime,
                         "window", which, linePrefix);
                 linePrefix = printWakeLock(sb, wl.getWakeTime(WAKE_TYPE_DRAW), rawRealtime,
@@ -4725,10 +4822,10 @@ public abstract class BatteryStats implements Parcelable {
                     final Timer aggTimer = u.getAggregatedPartialWakelockTimer();
                     // Convert from microseconds to milliseconds with rounding
                     actualTotalPartialWakelock =
-                            (aggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000;
+                            aggTimer.getTotalDurationMsLocked(rawRealtimeMs);
                     final Timer bgAggTimer = aggTimer.getSubTimer();
                     actualBgPartialWakelock = bgAggTimer != null ?
-                            (bgAggTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : 0;
+                            bgAggTimer.getTotalDurationMsLocked(rawRealtimeMs) : 0;
                 }
 
                 if (actualTotalPartialWakelock != 0 || actualBgPartialWakelock != 0 ||
@@ -4796,7 +4893,7 @@ public abstract class BatteryStats implements Parcelable {
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 sb.setLength(0);
                 sb.append(prefix);
@@ -4830,7 +4927,7 @@ public abstract class BatteryStats implements Parcelable {
                 final int count = timer.getCountLocked(which);
                 final Timer bgTimer = timer.getSubTimer();
                 final long bgTime = bgTimer != null ?
-                        (bgTimer.getTotalTimeLocked(rawRealtime, which) + 500) / 1000 : -1;
+                        bgTimer.getTotalDurationMsLocked(rawRealtimeMs) : -1;
                 final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : -1;
                 sb.setLength(0);
                 sb.append(prefix);
@@ -4889,7 +4986,6 @@ public abstract class BatteryStats implements Parcelable {
                     final int count = timer.getCountLocked(which);
                     final Timer bgTimer = se.getSensorBackgroundTime();
                     final int bgCount = bgTimer != null ? bgTimer.getCountLocked(which) : 0;
-                    final long rawRealtimeMs = (rawRealtime + 500) / 1000;
                     // 'actualTime' are unpooled and always since reset (regardless of 'which')
                     final long actualTime = timer.getTotalDurationMsLocked(rawRealtimeMs);
                     final long bgActualTime = bgTimer != null ?
index db84b6f..97f0e0c 100644 (file)
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.util.Log;
@@ -36,13 +37,10 @@ import java.util.zip.GZIPInputStream;
  * enqueued data exceeds the maximum size.  You can think of this as a
  * persistent, system-wide, blob-oriented "logcat".
  *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService}
- * with {@link android.content.Context#DROPBOX_SERVICE}.
- *
  * <p>DropBoxManager entries are not sent anywhere directly, but other system
  * services and debugging tools may scan and upload entries for processing.
  */
+@SystemService(Context.DROPBOX_SERVICE)
 public class DropBoxManager {
     private static final String TAG = "DropBoxManager";
 
index 67edefc..aad202e 100644 (file)
@@ -17,6 +17,7 @@ package android.os;
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.hardware.thermal.V1_0.Constants;
 import android.util.Log;
@@ -28,6 +29,7 @@ import java.lang.annotation.RetentionPolicy;
  * The HardwarePropertiesManager class provides a mechanism of accessing hardware state of a
  * device: CPU, GPU and battery temperatures, CPU usage per core, fan speed, etc.
  */
+@SystemService(Context.HARDWARE_PROPERTIES_SERVICE)
 public class HardwarePropertiesManager {
 
     private static final String TAG = HardwarePropertiesManager.class.getSimpleName();
index 976d594..bc8e2e4 100644 (file)
@@ -16,7 +16,9 @@
 
 package android.os;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.content.Context;
 import android.os.IIncidentManager;
@@ -31,6 +33,7 @@ import android.util.Slog;
  */
 @SystemApi
 @TestApi
+@SystemService(Context.INCIDENT_SERVICE)
 public class IncidentManager {
     private static final String TAG = "incident";
 
@@ -46,6 +49,10 @@ public class IncidentManager {
     /**
      * Take an incident report and put it in dropbox.
      */
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.DUMP,
+            android.Manifest.permission.PACKAGE_USAGE_STATS
+    })
     public void reportIncident(IncidentReportArgs args) {
         final IIncidentManager service = IIncidentManager.Stub.asInterface(
                 ServiceManager.getService("incident"));
@@ -76,6 +83,10 @@ public class IncidentManager {
      * {@link android.util.proto.ProtoOutputStream#bytes bytes()} method to retrieve
      * the encoded data for the header.
      */
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.DUMP,
+            android.Manifest.permission.PACKAGE_USAGE_STATS
+    })
     public void reportIncident(String settingName, byte[] headerProto) {
         // Sections
         String setting = Settings.System.getString(mContext.getContentResolver(), settingName);
index 7d1369f..a85ed9c 100644 (file)
 package android.os;
 
 import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.util.Log;
 import java.lang.annotation.Retention;
@@ -32,9 +34,6 @@ import java.lang.annotation.RetentionPolicy;
  * Do not acquire {@link WakeLock}s unless you really need them, use the minimum levels
  * possible, and be sure to release them as soon as possible.
  * </p><p>
- * You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- * </p><p>
  * The primary API you'll use is {@link #newWakeLock(int, String) newWakeLock()}.
  * This will create a {@link PowerManager.WakeLock} object.  You can then use methods
  * on the wake lock object to control the power state of the device.
@@ -102,6 +101,7 @@ import java.lang.annotation.RetentionPolicy;
  * permission in an {@code <uses-permission>} element of the application's manifest.
  * </p>
  */
+@SystemService(Context.POWER_SERVICE)
 public final class PowerManager {
     private static final String TAG = "PowerManager";
 
@@ -689,6 +689,10 @@ public final class PowerManager {
      * @hide Requires signature or system permission.
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.DEVICE_POWER,
+            android.Manifest.permission.USER_ACTIVITY
+    })
     public void userActivity(long when, int event, int flags) {
         try {
             mService.userActivity(when, event, flags);
index d2598c7..ba339a3 100644 (file)
@@ -18,7 +18,10 @@ package android.os;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -67,6 +70,7 @@ import sun.security.pkcs.SignerInfo;
  * recovery system (the separate partition that can be used to install
  * system updates, wipe user data, etc.)
  */
+@SystemService(Context.RECOVERY_SERVICE)
 public class RecoverySystem {
     private static final String TAG = "RecoverySystem";
 
@@ -387,6 +391,7 @@ public class RecoverySystem {
      * {@hide}
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public static boolean verifyPackageCompatibility(File compatibilityFile) throws IOException {
         try (InputStream inputStream = new FileInputStream(compatibilityFile)) {
             return verifyPackageCompatibility(inputStream);
@@ -409,6 +414,7 @@ public class RecoverySystem {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void processPackage(Context context,
                                       File packageFile,
                                       final ProgressListener listener,
@@ -469,6 +475,7 @@ public class RecoverySystem {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void processPackage(Context context,
                                       File packageFile,
                                       final ProgressListener listener)
@@ -490,6 +497,7 @@ public class RecoverySystem {
      * @throws IOException  if writing the recovery command file
      * fails, or if the reboot itself fails.
      */
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void installPackage(Context context, File packageFile)
             throws IOException {
         installPackage(context, packageFile, false);
@@ -511,6 +519,7 @@ public class RecoverySystem {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void installPackage(Context context, File packageFile, boolean processed)
             throws IOException {
         synchronized (sRequestLock) {
@@ -602,6 +611,7 @@ public class RecoverySystem {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void scheduleUpdateOnBoot(Context context, File packageFile)
             throws IOException {
         String filename = packageFile.getCanonicalPath();
@@ -639,6 +649,7 @@ public class RecoverySystem {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.RECOVERY)
     public static void cancelScheduledUpdate(Context context)
             throws IOException {
         RecoverySystem rs = (RecoverySystem) context.getSystemService(Context.RECOVERY_SERVICE);
@@ -777,6 +788,10 @@ public class RecoverySystem {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(allOf = {
+            android.Manifest.permission.RECOVERY,
+            android.Manifest.permission.REBOOT
+    })
     public static void rebootWipeAb(Context context, File packageFile, String reason)
             throws IOException {
         String reasonArg = null;
index 7bd3bf6..a7fc2e7 100644 (file)
@@ -23,6 +23,7 @@ import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.annotation.UserIdInt;
 import android.annotation.WorkerThread;
@@ -63,6 +64,7 @@ import java.util.List;
  * <p>
  * See {@link DevicePolicyManager#ACTION_PROVISION_MANAGED_PROFILE} for more on managed profiles.
  */
+@SystemService(Context.USER_SERVICE)
 public class UserManager {
 
     private static final String TAG = "UserManager";
@@ -1038,12 +1040,12 @@ public class UserManager {
 
     /**
      * Checks if the calling app is running in a managed profile.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @return whether the caller is in a managed profile.
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isManagedProfile() {
         // No need for synchronization.  Once it becomes non-null, it'll be non-null forever.
         // Worst case we might end up calling the AIDL method multiple times but that's fine.
@@ -1067,6 +1069,7 @@ public class UserManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public boolean isManagedProfile(@UserIdInt int userId) {
         if (userId == UserHandle.myUserId()) {
             return isManagedProfile();
@@ -1252,7 +1255,6 @@ public class UserManager {
      * @hide
      *
      * Returns who set a user restriction on a user.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
      * @return The source of user restriction. Any combination of {@link #RESTRICTION_NOT_SET},
@@ -1263,6 +1265,7 @@ public class UserManager {
     @Deprecated
     @SystemApi
     @UserRestrictionSource
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public int getUserRestrictionSource(String restrictionKey, UserHandle userHandle) {
         try {
             return mService.getUserRestrictionSource(restrictionKey, userHandle.getIdentifier());
@@ -1275,12 +1278,12 @@ public class UserManager {
      * @hide
      *
      * Returns a list of users who set a user restriction on a given user.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param restrictionKey the string key representing the restriction
      * @param userHandle the UserHandle of the user for whom to retrieve the restrictions.
      * @return a list of user ids enforcing this restriction.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public List<EnforcingUser> getUserRestrictionSources(
             String restrictionKey, UserHandle userHandle) {
         try {
@@ -1622,9 +1625,10 @@ public class UserManager {
     /**
      * @hide
      *
-     * Returns the preferred account name for user creation. Requires MANAGE_USERS permission.
+     * Returns the preferred account name for user creation.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public String getSeedAccountName() {
         try {
             return mService.getSeedAccountName();
@@ -1636,9 +1640,10 @@ public class UserManager {
     /**
      * @hide
      *
-     * Returns the preferred account type for user creation. Requires MANAGE_USERS permission.
+     * Returns the preferred account type for user creation.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public String getSeedAccountType() {
         try {
             return mService.getSeedAccountType();
@@ -1650,11 +1655,11 @@ public class UserManager {
     /**
      * @hide
      *
-     * Returns the preferred account's options bundle for user creation. Requires MANAGE_USERS
-     * permission.
+     * Returns the preferred account's options bundle for user creation.
      * @return Any options set by the requestor that created the user.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public PersistableBundle getSeedAccountOptions() {
         try {
             return mService.getSeedAccountOptions();
@@ -1686,9 +1691,10 @@ public class UserManager {
 
     /**
      * @hide
-     * Clears the seed information used to create this user. Requires MANAGE_USERS permission.
+     * Clears the seed information used to create this user.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public void clearSeedAccountData() {
         try {
             mService.clearSeedAccountData();
@@ -1771,13 +1777,13 @@ public class UserManager {
 
     /**
      * Returns serial numbers of all users on this device.
-     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      *
      * @param excludeDying specify if the list should exclude users being removed.
      * @return the list of serial numbers of users that exist on the device.
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MANAGE_USERS)
     public long[] getSerialNumbersOfUsers(boolean excludeDying) {
         try {
             List<UserInfo> users = mService.getUsers(excludeDying);
index 2f0eeca..8078fb8 100644 (file)
@@ -17,6 +17,7 @@
 package android.os;
 
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.app.ActivityThread;
 import android.content.Context;
 import android.media.AudioAttributes;
@@ -27,10 +28,8 @@ import android.util.Log;
  * <p>
  * If your process exits, any vibration you started will stop.
  * </p>
- *
- * To obtain an instance of the system vibrator, call
- * {@link Context#getSystemService} with {@link Context#VIBRATOR_SERVICE} as the argument.
  */
+@SystemService(Context.VIBRATOR_SERVICE)
 public abstract class Vibrator {
     private static final String TAG = "Vibrator";
 
index 7c0af25..bba4cd1 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.os.health;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.BatteryStats;
 import android.os.Process;
@@ -40,6 +41,7 @@ import com.android.internal.app.IBatteryStats;
  * JobScheduler}), and while that can affect charging rates, it is still preferable
  * to actually draining the battery.
  */
+@SystemService(Context.SYSTEM_HEALTH_SERVICE)
 public class SystemHealthManager {
     private final IBatteryStats mBatteryStats;
 
index f361c54..5046735 100644 (file)
@@ -25,7 +25,9 @@ import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.WorkerThread;
 import android.app.ActivityThread;
 import android.content.ContentResolver;
@@ -98,11 +100,8 @@ import java.util.concurrent.atomic.AtomicInteger;
  * guarantee the security of the OBB file itself: if any program modifies the
  * OBB, there is no guarantee that a read from that OBB will produce the
  * expected output.
- * <p>
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String)} with an
- * argument of {@link android.content.Context#STORAGE_SERVICE}.
  */
+@SystemService(Context.STORAGE_SERVICE)
 public class StorageManager {
     private static final String TAG = "StorageManager";
 
@@ -1404,23 +1403,7 @@ public class StorageManager {
 
     /** {@hide} */
     public static File maybeTranslateEmulatedPathToInternal(File path) {
-        final IStorageManager storageManager = IStorageManager.Stub.asInterface(
-                ServiceManager.getService("mount"));
-        try {
-            final VolumeInfo[] vols = storageManager.getVolumes(0);
-            for (VolumeInfo vol : vols) {
-                if ((vol.getType() == VolumeInfo.TYPE_EMULATED
-                        || vol.getType() == VolumeInfo.TYPE_PUBLIC) && vol.isMountedReadable()) {
-                    final File internalPath = FileUtils.rewriteAfterRename(vol.getPath(),
-                            vol.getInternalPath(), path);
-                    if (internalPath != null && internalPath.exists()) {
-                        return internalPath;
-                    }
-                }
-            }
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        // Disabled now that FUSE has been replaced by sdcardfs
         return path;
     }
 
@@ -1642,11 +1625,20 @@ public class StorageManager {
      */
     @RequiresPermission(android.Manifest.permission.ALLOCATE_AGGRESSIVE)
     @SystemApi
-    public static final int FLAG_ALLOCATE_AGGRESSIVE = 1;
+    public static final int FLAG_ALLOCATE_AGGRESSIVE = 1 << 0;
+
+    /**
+     * Flag indicating that a disk space allocation request should defy any
+     * reserved disk space.
+     *
+     * @hide
+     */
+    public static final int FLAG_ALLOCATE_DEFY_RESERVED = 1 << 1;
 
     /** @hide */
     @IntDef(flag = true, value = {
             FLAG_ALLOCATE_AGGRESSIVE,
+            FLAG_ALLOCATE_DEFY_RESERVED,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface AllocateFlags {}
@@ -1692,8 +1684,9 @@ public class StorageManager {
 
     /** @hide */
     @SystemApi
-    public long getAllocatableBytes(@NonNull UUID storageUuid, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public long getAllocatableBytes(@NonNull UUID storageUuid,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         try {
             return mStorageManager.getAllocatableBytes(convert(storageUuid), flags);
         } catch (ParcelableException e) {
@@ -1706,8 +1699,9 @@ public class StorageManager {
 
     /** @removed */
     @Deprecated
-    public long getAllocatableBytes(@NonNull File path, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public long getAllocatableBytes(@NonNull File path,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         return getAllocatableBytes(getUuidForPath(path), flags);
     }
 
@@ -1740,8 +1734,9 @@ public class StorageManager {
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void allocateBytes(@NonNull UUID storageUuid, @BytesLong long bytes,
-            @AllocateFlags int flags) throws IOException {
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         try {
             mStorageManager.allocateBytes(convert(storageUuid), bytes, flags);
         } catch (ParcelableException e) {
@@ -1753,8 +1748,9 @@ public class StorageManager {
 
     /** @removed */
     @Deprecated
-    public void allocateBytes(@NonNull File path, @BytesLong long bytes, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public void allocateBytes(@NonNull File path, @BytesLong long bytes,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         allocateBytes(getUuidForPath(path), bytes, flags);
     }
 
@@ -1789,8 +1785,9 @@ public class StorageManager {
 
     /** @hide */
     @SystemApi
-    public void allocateBytes(FileDescriptor fd, @BytesLong long bytes, @AllocateFlags int flags)
-            throws IOException {
+    @SuppressLint("Doclava125")
+    public void allocateBytes(FileDescriptor fd, @BytesLong long bytes,
+            @RequiresPermission @AllocateFlags int flags) throws IOException {
         final File file = ParcelFileDescriptor.getFile(fd);
         for (int i = 0; i < 3; i++) {
             try {
index 8ee0517..e8ff2e2 100644 (file)
@@ -19,6 +19,7 @@ package android.print;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.app.Application.ActivityLifecycleCallbacks;
 import android.content.ComponentName;
@@ -57,14 +58,6 @@ import java.util.Map;
 
 /**
  * System level service for accessing the printing capabilities of the platform.
- * <p>
- * To obtain a handle to the print manager do the following:
- * </p>
- *
- * <pre>
- * PrintManager printManager =
- *         (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
- * </pre>
  *
  * <h3>Print mechanics</h3>
  * <p>
@@ -109,6 +102,7 @@ import java.util.Map;
  * @see PrintJob
  * @see PrintJobInfo
  */
+@SystemService(Context.PRINT_SERVICE)
 public final class PrintManager {
 
     private static final String LOG_TAG = "PrintManager";
index 5408e13..70ef035 100644 (file)
@@ -8915,15 +8915,11 @@ public final class ContactsContract {
          * ambiguous then the activity should prompt the user for the recipient to send the message
          * to.
          * <p>
-         * Voice Assistant may provide additional information to messaging app about which account
-         * to use for sending a message by populating {@link #EXTRA_SENDER_ACCOUNT_HASH}.
-         * <p>
          * Output: nothing
          *
          * @see #EXTRA_RECIPIENT_CONTACT_URI
          * @see #EXTRA_RECIPIENT_CONTACT_CHAT_ID
          * @see #EXTRA_RECIPIENT_CONTACT_NAME
-         * @see #EXTRA_SENDER_ACCOUNT_HASH
          * @see #METADATA_ACCOUNT_TYPE
          * @see #METADATA_MIMETYPE
          */
@@ -8982,21 +8978,6 @@ public final class ContactsContract {
                 "android.provider.extra.RECIPIENT_CONTACT_NAME";
 
         /**
-         * This optional extra specifies the hash of the account that should be used by messaging
-         * app for sending voice message with {@link #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS}. The
-         * value of this extra is a {@code String} and should be the value of {@link
-         * android.accounts.Account#hashCode()} for some account returned by {@link
-         * android.accounts.AccountManager#getAccounts()}.
-         * <p>
-         * If the extra is not specified, the app can decide which account to use.
-         * <p>
-         * If the account specified in the extra cannot be used for any reason (account missing, not
-         * usable by the app, etc), the message should not be sent.
-         */
-        public static final String EXTRA_SENDER_ACCOUNT_HASH =
-                "android.provider.extra.SENDER_ACCOUNT_HASH";
-
-        /**
          * A string associated with an {@link #ACTION_VOICE_SEND_MESSAGE_TO_CONTACTS} activity
          * describing {@link RawContacts#ACCOUNT_TYPE} for the corresponding Contacts Provider
          * implementation.
index 3cd54b8..6a17ed1 100755 (executable)
@@ -9817,13 +9817,49 @@ public final class Settings {
         public static final String ENABLE_EPHEMERAL_FEATURE = "enable_ephemeral_feature";
 
         /**
-         * The duration for caching uninstalled instant apps.
+         * The min period for caching installed instant apps in milliseconds.
          * <p>
          * Type: long
          * @hide
          */
-        public static final String UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS =
-                "uninstalled_instant_app_cache_duration_millis";
+        public static final String INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD =
+                "installed_instant_app_min_cache_period";
+
+        /**
+         * The max period for caching installed instant apps in milliseconds.
+         * <p>
+         * Type: long
+         * @hide
+         */
+        public static final String INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD =
+                "installed_instant_app_max_cache_period";
+
+        /**
+         * The min period for caching uninstalled instant apps in milliseconds.
+         * <p>
+         * Type: long
+         * @hide
+         */
+        public static final String UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD =
+                "uninstalled_instant_app_min_cache_period";
+
+        /**
+         * The max period for caching uninstalled instant apps in milliseconds.
+         * <p>
+         * Type: long
+         * @hide
+         */
+        public static final String UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD =
+                "uninstalled_instant_app_max_cache_period";
+
+        /**
+         * The min period for caching unused static shared libs in milliseconds.
+         * <p>
+         * Type: long
+         * @hide
+         */
+        public static final String UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD =
+                "unused_static_shared_lib_min_cache_period";
 
         /**
          * Allows switching users when system user is locked.
index 251d346..6956c8a 100644 (file)
@@ -114,7 +114,7 @@ public final class FillContext implements Parcelable {
      *
      * @hide
      */
-    @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId[] ids) {
+    @NonNull public ViewNode[] findViewNodesByAutofillIds(@NonNull AutofillId... ids) {
         final LinkedList<ViewNode> nodesToProcess = new LinkedList<>();
         final ViewNode[] foundNodes = new AssistStructure.ViewNode[ids.length];
 
index 31b2dcc..d1ebc6e 100644 (file)
@@ -318,6 +318,17 @@ public class StatusBarNotification implements Parcelable {
     }
 
     /**
+     * The ID passed to setGroup(), or the override, or null.
+     * @hide
+     */
+    public String getGroup() {
+        if (overrideGroupKey != null) {
+            return overrideGroupKey;
+        }
+        return getNotification().getGroup();
+    }
+
+    /**
      * Sets the override group key.
      */
     public void setOverrideGroupKey(String overrideGroupKey) {
index c4fbe5e..e2ade87 100644 (file)
 package android.service.oemlock;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.RemoteException;
 
 /**
@@ -31,6 +34,7 @@ import android.os.RemoteException;
  * @hide
  */
 @SystemApi
+@SystemService(Context.OEM_LOCK_SERVICE)
 public class OemLockManager {
     private IOemLockService mService;
 
@@ -55,6 +59,7 @@ public class OemLockManager {
      *
      * @see #isOemUnlockAllowedByCarrier()
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE)
     public void setOemUnlockAllowedByCarrier(boolean allowed, @Nullable byte[] signature) {
         try {
             mService.setOemUnlockAllowedByCarrier(allowed, signature);
@@ -69,6 +74,7 @@ public class OemLockManager {
      *
      * @see #setOemUnlockAllowedByCarrier(boolean, byte[])
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_CARRIER_OEM_UNLOCK_STATE)
     public boolean isOemUnlockAllowedByCarrier() {
         try {
             return mService.isOemUnlockAllowedByCarrier();
@@ -86,6 +92,7 @@ public class OemLockManager {
      *
      * @see #isOemUnlockAllowedByUser()
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE)
     public void setOemUnlockAllowedByUser(boolean allowed) {
         try {
             mService.setOemUnlockAllowedByUser(allowed);
@@ -100,6 +107,7 @@ public class OemLockManager {
      *
      * @see #setOemUnlockAllowedByUser(boolean)
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_USER_OEM_UNLOCK_STATE)
     public boolean isOemUnlockAllowedByUser() {
         try {
             return mService.isOemUnlockAllowedByUser();
index 326796a..fa75ad3 100644 (file)
 
 package android.service.persistentdata;
 
-import android.annotation.SystemApi;
 import android.annotation.IntDef;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.RemoteException;
-import android.util.Slog;
+import android.service.oemlock.OemLockManager;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -43,6 +47,7 @@ import java.lang.annotation.RetentionPolicy;
  * @hide
  */
 @SystemApi
+@SystemService(Context.PERSISTENT_DATA_BLOCK_SERVICE)
 public class PersistentDataBlockManager {
     private static final String TAG = PersistentDataBlockManager.class.getSimpleName();
     private IPersistentDataBlockService sService;
@@ -85,6 +90,7 @@ public class PersistentDataBlockManager {
      *
      * @param data the data to write
      */
+    @SuppressLint("Doclava125")
     public int write(byte[] data) {
         try {
             return sService.write(data);
@@ -96,6 +102,7 @@ public class PersistentDataBlockManager {
     /**
      * Returns the data block stored on the persistent partition.
      */
+    @SuppressLint("Doclava125")
     public byte[] read() {
         try {
             return sService.read();
@@ -109,6 +116,7 @@ public class PersistentDataBlockManager {
      *
      * Return -1 on error.
      */
+    @RequiresPermission(android.Manifest.permission.ACCESS_PDB_STATE)
     public int getDataBlockSize() {
         try {
             return sService.getDataBlockSize();
@@ -136,6 +144,7 @@ public class PersistentDataBlockManager {
      * It will also prevent any further {@link #write} operation until reboot,
      * in order to prevent a potential race condition. See b/30352311.
      */
+    @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
     public void wipe() {
         try {
             sService.wipe();
@@ -149,6 +158,7 @@ public class PersistentDataBlockManager {
      *
      * @deprecated use {@link OemLockManager#setOemUnlockAllowedByUser(boolean)} instead.
      */
+    @RequiresPermission(android.Manifest.permission.OEM_UNLOCK_STATE)
     public void setOemUnlockEnabled(boolean enabled) {
         try {
             sService.setOemUnlockEnabled(enabled);
@@ -162,6 +172,10 @@ public class PersistentDataBlockManager {
      *
      * @deprecated use {@link OemLockManager#isOemUnlockAllowedByUser()} instead.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_OEM_UNLOCK_STATE,
+            android.Manifest.permission.OEM_UNLOCK_STATE
+    })
     public boolean getOemUnlockEnabled() {
         try {
             return sService.getOemUnlockEnabled();
@@ -177,6 +191,10 @@ public class PersistentDataBlockManager {
      * {@link #FLASH_LOCK_UNLOCKED} if device bootloader is unlocked, or {@link #FLASH_LOCK_UNKNOWN}
      * if this information cannot be ascertained on this device.
      */
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_OEM_UNLOCK_STATE,
+            android.Manifest.permission.OEM_UNLOCK_STATE
+    })
     @FlashLockState
     public int getFlashLockState() {
         try {
index a2a129d..625dd9e 100644 (file)
@@ -235,6 +235,8 @@ public class VoiceInteractionSession implements KeyEvent.Callback, ComponentCall
 
         @Override
         public void hide() {
+            // Remove any pending messages to show the session
+            mHandlerCaller.removeMessages(MSG_SHOW);
             mHandlerCaller.sendMessage(mHandlerCaller.obtainMessage(MSG_HIDE));
         }
 
index adf4938..480abc1 100644 (file)
@@ -1593,7 +1593,7 @@ public final class ProtoOutputStream {
         assertNotCompacted();
         final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_FIXED64);
 
-        writeRepeatedFixed64(id, val);
+        writeRepeatedFixed64Impl(id, val);
     }
 
     private void writeRepeatedFixed64Impl(int id, long val) {
@@ -1720,7 +1720,7 @@ public final class ProtoOutputStream {
         assertNotCompacted();
         final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_SFIXED64);
 
-        writeRepeatedSFixed64(id, val);
+        writeRepeatedSFixed64Impl(id, val);
     }
 
     private void writeRepeatedSFixed64Impl(int id, long val) {
@@ -1785,7 +1785,7 @@ public final class ProtoOutputStream {
         assertNotCompacted();
         final int id = checkFieldId(fieldId, FIELD_COUNT_REPEATED | FIELD_TYPE_BOOL);
 
-        writeRepeatedBool(id, val);
+        writeRepeatedBoolImpl(id, val);
     }
 
     private void writeRepeatedBoolImpl(int id, boolean val) {
index c6e1989..86a5fb7 100644 (file)
@@ -1,6 +1,6 @@
 package android.view;
 
-import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -15,19 +15,19 @@ import android.os.Parcelable;
  */
 public class AppTransitionAnimationSpec implements Parcelable {
     public final int taskId;
-    public final Bitmap bitmap;
+    public final GraphicBuffer buffer;
     public final Rect rect;
 
-    public AppTransitionAnimationSpec(int taskId, Bitmap bitmap, Rect rect) {
+    public AppTransitionAnimationSpec(int taskId, GraphicBuffer buffer, Rect rect) {
         this.taskId = taskId;
-        this.bitmap = bitmap;
         this.rect = rect;
+        this.buffer = buffer;
     }
 
     public AppTransitionAnimationSpec(Parcel in) {
         taskId = in.readInt();
-        bitmap = in.readParcelable(null);
         rect = in.readParcelable(null);
+        buffer = in.readParcelable(null);
     }
 
     @Override
@@ -38,9 +38,8 @@ public class AppTransitionAnimationSpec implements Parcelable {
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeInt(taskId);
-        dest.writeParcelable(bitmap, 0 /* flags */);
         dest.writeParcelable(rect, 0 /* flags */);
-
+        dest.writeParcelable(buffer, 0);
     }
 
     public static final Parcelable.Creator<AppTransitionAnimationSpec> CREATOR
@@ -56,6 +55,6 @@ public class AppTransitionAnimationSpec implements Parcelable {
 
     @Override
     public String toString() {
-        return "{taskId: " + taskId + ", bitmap: " + bitmap + ", rect: " + rect + "}";
+        return "{taskId: " + taskId + ", buffer: " + buffer + ", rect: " + rect + "}";
     }
 }
index dbeb747..d2dcb56 100644 (file)
@@ -30,6 +30,14 @@ interface IPinnedStackController {
     oneway void setIsMinimized(boolean isMinimized);
 
     /**
+     * Notifies the controller of the current min edge size, this is needed to allow the system to
+     * properly calculate the aspect ratio of the expanded PIP.  The given {@param minEdgeSize} is
+     * always bounded to be larger than the default minEdgeSize, so the caller can call this method
+     * with 0 to reset to the default size.
+     */
+    oneway void setMinEdgeSize(int minEdgeSize);
+
+    /**
      * @return what WM considers to be the current device rotation.
      */
     int getDisplayRotation();
index a2ff4f7..58a6a5e 100644 (file)
@@ -26,6 +26,7 @@ import com.android.internal.policy.IShortcutService;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -96,9 +97,9 @@ interface IWindowManager
             int startHeight);
     void overridePendingAppTransitionClipReveal(int startX, int startY,
             int startWidth, int startHeight);
-    void overridePendingAppTransitionThumb(in Bitmap srcThumb, int startX, int startY,
+    void overridePendingAppTransitionThumb(in GraphicBuffer srcThumb, int startX, int startY,
             IRemoteCallback startedCallback, boolean scaleUp);
-    void overridePendingAppTransitionAspectScaledThumb(in Bitmap srcThumb, int startX,
+    void overridePendingAppTransitionAspectScaledThumb(in GraphicBuffer srcThumb, int startX,
             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
             boolean scaleUp);
     /**
index f987e4e..47b8d92 100644 (file)
@@ -18,6 +18,7 @@ package android.view;
 
 import android.annotation.LayoutRes;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -47,10 +48,7 @@ import java.util.HashMap;
  * {@link android.app.Activity#getLayoutInflater()} or
  * {@link Context#getSystemService} to retrieve a standard LayoutInflater instance
  * that is already hooked up to the current context and correctly configured
- * for the device you are running on.  For example:
- *
- * <pre>LayoutInflater inflater = (LayoutInflater)context.getSystemService
- *      (Context.LAYOUT_INFLATER_SERVICE);</pre>
+ * for the device you are running on.
  *
  * <p>
  * To create a new LayoutInflater with an additional {@link Factory} for your
@@ -64,9 +62,8 @@ import java.util.HashMap;
  * to use LayoutInflater with an XmlPullParser over a plain XML file at runtime;
  * it only works with an XmlPullParser returned from a compiled resource
  * (R.<em>something</em> file.)
- *
- * @see Context#getSystemService
  */
+@SystemService(Context.LAYOUT_INFLATER_SERVICE)
 public abstract class LayoutInflater {
 
     private static final String TAG = LayoutInflater.class.getSimpleName();
@@ -923,8 +920,11 @@ public abstract class LayoutInflater {
                             + " include tag: <include layout=\"@layout/layoutID\" />");
                 }
 
-                // Attempt to resolve the "?attr/name" string to an identifier.
-                layout = context.getResources().getIdentifier(value.substring(1), null, null);
+                // Attempt to resolve the "?attr/name" string to an attribute
+                // within the default (e.g. application) package.
+                layout = context.getResources().getIdentifier(
+                        value.substring(1), "attr", context.getPackageName());
+
             }
 
             // The layout might be referencing a theme attribute.
index 2c9b2e4..ef78559 100644 (file)
@@ -31,7 +31,8 @@ import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Build;
 import android.os.Handler;
-import android.os.Message;
+import android.os.IBinder;
+import android.os.Looper;
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -120,34 +121,11 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
     final Rect mTmpRect = new Rect();
     final Configuration mConfiguration = new Configuration();
 
-    static final int KEEP_SCREEN_ON_MSG = 1;
-    static final int DRAW_FINISHED_MSG = 2;
-
     int mSubLayer = APPLICATION_MEDIA_SUBLAYER;
 
     boolean mIsCreating = false;
     private volatile boolean mRtHandlingPositionUpdates = false;
 
-    final Handler mHandler = new Handler() {
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case KEEP_SCREEN_ON_MSG: {
-                    setKeepScreenOn(msg.arg1 != 0);
-                } break;
-                case DRAW_FINISHED_MSG: {
-                    mDrawFinished = true;
-                    if (mAttachedToWindow) {
-                        mParent.requestTransparentRegion(SurfaceView.this);
-
-                        notifyDrawFinished();
-                        invalidate();
-                    }
-                } break;
-            }
-        }
-    };
-
     private final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
             = new ViewTreeObserver.OnScrollChangedListener() {
                     @Override
@@ -287,6 +265,22 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
         updateSurface();
     }
 
+    private void performDrawFinished() {
+        if (mPendingReportDraws > 0) {
+            mDrawFinished = true;
+            if (mAttachedToWindow) {
+                mParent.requestTransparentRegion(SurfaceView.this);
+                
+                notifyDrawFinished();
+                invalidate();
+            }
+        } else {
+            Log.e(TAG, System.identityHashCode(this) + "finished drawing"
+                    + " but no pending report draw (extra call"
+                    + " to draw completion runnable?)");
+        }
+    }
+
     void notifyDrawFinished() {
         ViewRootImpl viewRoot = getViewRootImpl();
         if (viewRoot != null) {
@@ -459,6 +453,14 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
         }
     }
 
+    private void updateOpaqueFlag() {
+        if (!PixelFormat.formatHasAlpha(mRequestedFormat)) {
+            mSurfaceFlags |= SurfaceControl.OPAQUE;
+        } else {
+            mSurfaceFlags &= ~SurfaceControl.OPAQUE;
+        }
+    }
+
     private Rect getParentSurfaceInsets() {
         final ViewRootImpl root = getViewRootImpl();
         if (root == null) {
@@ -529,7 +531,9 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
                 if (creating) {
                     mSurfaceSession = new SurfaceSession(viewRoot.mSurface);
                     mDeferredDestroySurfaceControl = mSurfaceControl;
-                    mSurfaceControl = new SurfaceControl(mSurfaceSession,
+
+                    updateOpaqueFlag();
+                    mSurfaceControl = new SurfaceControlWithBackground(mSurfaceSession,
                             "SurfaceView - " + viewRoot.getTitle().toString(),
                             mSurfaceWidth, mSurfaceHeight, mFormat,
                             mSurfaceFlags);
@@ -751,7 +755,9 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
             mDeferredDestroySurfaceControl = null;
         }
 
-        mHandler.sendEmptyMessage(DRAW_FINISHED_MSG);
+        runOnUiThread(() -> {
+            performDrawFinished();
+        });
     }
 
     private void setParentSpaceRectangle(Rect position, long frameNumber) {
@@ -880,6 +886,15 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
                 + "type=" + type, new Throwable());
     }
 
+    private void runOnUiThread(Runnable runnable) {
+        Handler handler = getHandler();
+        if (handler != null && handler.getLooper() != Looper.myLooper()) {
+            handler.post(runnable);
+        } else {
+            runnable.run();
+        }
+    }
+
     /**
      * Check to see if the surface has fixed size dimensions or if the surface's
      * dimensions are dimensions are dependent on its current layout.
@@ -960,9 +975,7 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
 
         @Override
         public void setKeepScreenOn(boolean screenOn) {
-            Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG);
-            msg.arg1 = screenOn ? 1 : 0;
-            mHandler.sendMessage(msg);
+            runOnUiThread(() -> SurfaceView.this.setKeepScreenOn(screenOn));
         }
 
         /**
@@ -1069,4 +1082,126 @@ public class SurfaceView extends View implements ViewRootImpl.WindowStoppedCallb
             return mSurfaceFrame;
         }
     };
+
+    class SurfaceControlWithBackground extends SurfaceControl {
+        private SurfaceControl mBackgroundControl;
+        private boolean mOpaque = true;
+        public boolean mVisible = false;
+
+        public SurfaceControlWithBackground(SurfaceSession s,
+                        String name, int w, int h, int format, int flags)
+                       throws Exception {
+            super(s, name, w, h, format, flags);
+            mBackgroundControl = new SurfaceControl(s, "Background for - " + name, w, h,
+                    PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
+            mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
+        }
+
+        @Override
+        public void setAlpha(float alpha) {
+            super.setAlpha(alpha);
+            mBackgroundControl.setAlpha(alpha);
+        }
+
+        @Override
+        public void setLayer(int zorder) {
+            super.setLayer(zorder);
+            // -3 is below all other child layers as SurfaceView never goes below -2
+            mBackgroundControl.setLayer(-3);
+        }
+
+        @Override
+        public void setPosition(float x, float y) {
+            super.setPosition(x, y);
+            mBackgroundControl.setPosition(x, y);
+        }
+
+        @Override
+        public void setSize(int w, int h) {
+            super.setSize(w, h);
+            mBackgroundControl.setSize(w, h);
+        }
+
+        @Override
+        public void setWindowCrop(Rect crop) {
+            super.setWindowCrop(crop);
+            mBackgroundControl.setWindowCrop(crop);
+        }
+
+        @Override
+        public void setFinalCrop(Rect crop) {
+            super.setFinalCrop(crop);
+            mBackgroundControl.setFinalCrop(crop);
+        }
+
+        @Override
+        public void setLayerStack(int layerStack) {
+            super.setLayerStack(layerStack);
+            mBackgroundControl.setLayerStack(layerStack);
+        }
+
+        @Override
+        public void setOpaque(boolean isOpaque) {
+            super.setOpaque(isOpaque);
+            mOpaque = isOpaque;
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void setSecure(boolean isSecure) {
+            super.setSecure(isSecure);
+        }
+
+        @Override
+        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+            super.setMatrix(dsdx, dtdx, dsdy, dtdy);
+            mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
+        }
+
+        @Override
+        public void hide() {
+            super.hide();
+            mVisible = false;
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void show() {
+            super.show();
+            mVisible = true;
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void destroy() {
+            super.destroy();
+            mBackgroundControl.destroy();
+         }
+
+        @Override
+        public void release() {
+            super.release();
+            mBackgroundControl.release();
+        }
+
+        @Override
+        public void setTransparentRegionHint(Region region) {
+            super.setTransparentRegionHint(region);
+            mBackgroundControl.setTransparentRegionHint(region);
+        }
+
+        @Override
+        public void deferTransactionUntil(IBinder handle, long frame) {
+            super.deferTransactionUntil(handle, frame);
+            mBackgroundControl.deferTransactionUntil(handle, frame);
+        }
+
+        void updateBackgroundVisibility() {
+            if (mOpaque && mVisible) {
+                mBackgroundControl.show();
+            } else {
+                mBackgroundControl.hide();
+            }
+        }
+    }
 }
index 25a58e6..7cec957 100644 (file)
@@ -341,6 +341,7 @@ public final class ThreadedRenderer {
 
     private boolean mEnabled;
     private boolean mRequested = true;
+    private boolean mIsOpaque = false;
 
     ThreadedRenderer(Context context, boolean translucent, String name) {
         final TypedArray a = context.obtainStyledAttributes(null, R.styleable.Lighting, 0, 0);
@@ -355,6 +356,7 @@ public final class ThreadedRenderer {
         long rootNodePtr = nCreateRootRenderNode();
         mRootNode = RenderNode.adopt(rootNodePtr);
         mRootNode.setClipToBounds(false);
+        mIsOpaque = !translucent;
         mNativeProxy = nCreateProxy(translucent, rootNodePtr);
         nSetName(mNativeProxy, name);
 
@@ -571,7 +573,12 @@ public final class ThreadedRenderer {
      * Change the ThreadedRenderer's opacity
      */
     void setOpaque(boolean opaque) {
-        nSetOpaque(mNativeProxy, opaque && !mHasInsets);
+        mIsOpaque = opaque && !mHasInsets;
+        nSetOpaque(mNativeProxy, mIsOpaque);
+    }
+
+    boolean isOpaque() {
+        return mIsOpaque;
     }
 
     /**
index b51e77c..a9c85f0 100644 (file)
@@ -964,115 +964,155 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
 
     /**
-     * This view contains an email address.
+     * Hint indicating that this view can be autofilled with an email address.
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_EMAIL_ADDRESS}"
-     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_EMAIL_ADDRESS}</code>).
+     *
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_EMAIL_ADDRESS = "emailAddress";
 
     /**
-     * The view contains a real name.
+     * Hint indicating that this view can be autofilled with a user's real name.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_NAME}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_NAME}" to
-     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_NAME = "name";
 
     /**
-     * The view contains a user name.
+     * Hint indicating that this view can be autofilled with a username.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_USERNAME}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_USERNAME}" to
-     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_USERNAME = "username";
 
     /**
-     * The view contains a password.
+     * Hint indicating that this view can be autofilled with a password.
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PASSWORD}" to
-     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_PASSWORD}</code>).
+     *
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_PASSWORD = "password";
 
     /**
-     * The view contains a phone number.
+     * Hint indicating that this view can be autofilled with a phone number.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_PHONE}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_PHONE}" to
-     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_PHONE = "phone";
 
     /**
-     * The view contains a postal address.
+     * Hint indicating that this view can be autofilled with a postal address.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_ADDRESS}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_ADDRESS}"
-     * to <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_POSTAL_ADDRESS = "postalAddress";
 
     /**
-     * The view contains a postal code.
+     * Hint indicating that this view can be autofilled with a postal code.
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value #AUTOFILL_HINT_POSTAL_CODE}" to
-     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}.
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_POSTAL_CODE}</code>).
+     *
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_POSTAL_CODE = "postalCode";
 
     /**
-     * The view contains a credit card number.
+     * Hint indicating that this view can be autofilled with a credit card number.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_NUMBER}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value
-     * #AUTOFILL_HINT_CREDIT_CARD_NUMBER}" to <a href="#attr_android:autofillHint"> {@code
-     * android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_NUMBER = "creditCardNumber";
 
     /**
-     * The view contains a credit card security code.
+     * Hint indicating that this view can be autofilled with a credit card security code.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value
-     * #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE}" to <a href="#attr_android:autofillHint"> {@code
-     * android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE = "creditCardSecurityCode";
 
     /**
-     * The view contains a credit card expiration date.
+     * Hint indicating that this view can be autofilled with a credit card expiration date.
+     *
+     * <p>It should be used when the credit card expiration date is represented by just one view;
+     * if it is represented by more than one (for example, one view for the month and another view
+     * for the year), then each of these views should use the hint specific for the unit
+     * ({@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
+     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH},
+     * or {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}).
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value
-     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE}" to <a href="#attr_android:autofillHint"> {@code
-     * android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE =
             "creditCardExpirationDate";
 
     /**
-     * The view contains the month a credit card expires.
+     * Hint indicating that this view can be autofilled with a credit card expiration month.
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value
-     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}" to <a href="#attr_android:autofillHint"> {@code
-     * android:autofillHint}.
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH}</code>).
+     *
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH =
             "creditCardExpirationMonth";
 
     /**
-     * The view contains the year a credit card expires.
+     * Hint indicating that this view can be autofilled with a credit card expiration year.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value
-     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}" to <a href="#attr_android:autofillHint"> {@code
-     * android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR =
             "creditCardExpirationYear";
 
     /**
-     * The view contains the day a credit card expires.
+     * Hint indicating that this view can be autofilled with a credit card expiration day.
+     *
+     * <p>Can be used with either {@link #setAutofillHints(String[])} or
+     * <a href="#attr_android:autofillHint"> {@code android:autofillHint}</a> (in which case the
+     * value should be <code>{@value #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}</code>).
      *
-     * Use with {@link #setAutofillHints(String[])}, or set "{@value
-     * #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY}" to <a href="#attr_android:autofillHint"> {@code
-     * android:autofillHint}.
+     * <p>See {@link #setAutofillHints(String...)} for more info about autofill hints.
      */
     public static final String AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY = "creditCardExpirationDay";
 
@@ -1099,6 +1139,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
 
     /**
      * Autofill type for views that cannot be autofilled.
+     *
+     * <p>Typically used when the view is read-only; for example, a text label.
+     *
+     * @see #getAutofillType()
      */
     public static final int AUTOFILL_TYPE_NONE = 0;
 
@@ -1108,6 +1152,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
      * {@link AutofillValue#forText(CharSequence)}, and the value passed to autofill a
      * {@link View} can be fetched through {@link AutofillValue#getTextValue()}.
+     *
+     * @see #getAutofillType()
      */
     public static final int AUTOFILL_TYPE_TEXT = 1;
 
@@ -1117,6 +1163,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
      * {@link AutofillValue#forToggle(boolean)}, and the value passed to autofill a
      * {@link View} can be fetched through {@link AutofillValue#getToggleValue()}.
+     *
+     * @see #getAutofillType()
      */
     public static final int AUTOFILL_TYPE_TOGGLE = 2;
 
@@ -1130,6 +1178,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      *
      * <p>The available options in the selection list are typically provided by
      * {@link android.app.assist.AssistStructure.ViewNode#getAutofillOptions()}.
+     *
+     * @see #getAutofillType()
      */
     public static final int AUTOFILL_TYPE_LIST = 3;
 
@@ -1142,6 +1192,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * <p>{@link AutofillValue} instances for autofilling a {@link View} can be obtained through
      * {@link AutofillValue#forDate(long)}, and the values passed to
      * autofill a {@link View} can be fetched through {@link AutofillValue#getDateValue()}.
+     *
+     * @see #getAutofillType()
      */
     public static final int AUTOFILL_TYPE_DATE = 4;
 
@@ -1158,26 +1210,41 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
 
     /**
      * Automatically determine whether a view is important for autofill.
+     *
+     * @see #isImportantForAutofill()
+     * @see #setImportantForAutofill(int)
      */
     public static final int IMPORTANT_FOR_AUTOFILL_AUTO = 0x0;
 
     /**
      * The view is important for autofill, and its children (if any) will be traversed.
+     *
+     * @see #isImportantForAutofill()
+     * @see #setImportantForAutofill(int)
      */
     public static final int IMPORTANT_FOR_AUTOFILL_YES = 0x1;
 
     /**
      * The view is not important for autofill, but its children (if any) will be traversed.
+     *
+     * @see #isImportantForAutofill()
+     * @see #setImportantForAutofill(int)
      */
     public static final int IMPORTANT_FOR_AUTOFILL_NO = 0x2;
 
     /**
      * The view is important for autofill, but its children (if any) will not be traversed.
+     *
+     * @see #isImportantForAutofill()
+     * @see #setImportantForAutofill(int)
      */
     public static final int IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS = 0x4;
 
     /**
      * The view is not important for autofill, and its children (if any) will not be traversed.
+     *
+     * @see #isImportantForAutofill()
+     * @see #setImportantForAutofill(int)
      */
     public static final int IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS = 0x8;
 
@@ -7326,23 +7393,70 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Called when assist structure is being retrieved from a view as part of an autofill request.
+     * Populates a {@link ViewStructure} to fullfil an autofill request.
+     *
+     * <p>The structure should contain at least the following properties:
+     * <ul>
+     *   <li>Autofill id ({@link ViewStructure#setAutofillId(AutofillId, int)}).
+     *   <li>Autofill type ({@link ViewStructure#setAutofillType(int)}).
+     *   <li>Autofill value ({@link ViewStructure#setAutofillValue(AutofillValue)}).
+     *   <li>Whether the data is sensitive ({@link ViewStructure#setDataIsSensitive(boolean)}).
+     * </ul>
+     *
+     * <p>It's also recommended to set the following properties - the more properties the structure
+     * has, the higher the changes of an {@link android.service.autofill.AutofillService} properly
+     * using the structure:
+     *
+     * <ul>
+     *   <li>Autofill hints ({@link ViewStructure#setAutofillHints(String[])}).
+     *   <li>Autofill options ({@link ViewStructure#setAutofillOptions(CharSequence[])}) when the
+     *       view can only be filled with predefined values (typically used when the autofill type
+     *       is {@link #AUTOFILL_TYPE_LIST}).
+     *   <li>Resource id ({@link ViewStructure#setId(int, String, String, String)}).
+     *   <li>Class name ({@link ViewStructure#setClassName(String)}).
+     *   <li>Content description ({@link ViewStructure#setContentDescription(CharSequence)}).
+     *   <li>Visual properties such as visibility ({@link ViewStructure#setVisibility(int)}),
+     *       dimensions ({@link ViewStructure#setDimens(int, int, int, int, int, int)}), and
+     *       opacity ({@link ViewStructure#setOpaque(boolean)}).
+     *   <li>For views representing text fields, text properties such as the text itself
+     *       ({@link ViewStructure#setText(CharSequence)}), text hints
+     *       ({@link ViewStructure#setHint(CharSequence)}, input type
+     *       ({@link ViewStructure#setInputType(int)}),
+     *   <li>For views representing HTML nodes, its web domain
+     *       ({@link ViewStructure#setWebDomain(String)}) and HTML properties
+     *       (({@link ViewStructure#setHtmlInfo(android.view.ViewStructure.HtmlInfo)}).
+     * </ul>
+     *
+     * <p>The default implementation of this method already sets most of these properties based on
+     * related {@link View} methods (for example, the autofill id is set using
+     * {@link #getAutofillId()}, the autofill type set using {@link #getAutofillType()}, etc.),
+     * and views in the standard Android widgets library also override it to set their
+     * relevant properties (for example, {@link android.widget.TextView} already sets the text
+     * properties), so it's recommended to only override this method
+     * (and call {@code super.onProvideAutofillStructure()}) when:
      *
-     * <p>This method already provides most of what's needed for autofill, but should be overridden
-     * when:
      * <ul>
      *   <li>The view contents does not include PII (Personally Identifiable Information), so it
-     * can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
-     *   <li>It must set fields such {@link ViewStructure#setText(CharSequence)},
-     * {@link ViewStructure#setAutofillOptions(CharSequence[])},
-     * or {@link ViewStructure#setWebDomain(String)}.
-     *   <li> The {@code left} and {@code top} values set in
-     * {@link ViewStructure#setDimens(int, int, int, int, int, int)} need to be relative to the next
-     * {@link ViewGroup#isImportantForAutofill() included} parent in the structure.
+     *       can call {@link ViewStructure#setDataIsSensitive(boolean)} passing {@code false}.
+     *   <li>The view can only be autofilled with predefined options, so it can call
+     *       {@link ViewStructure#setAutofillOptions(CharSequence[])}.
      * </ul>
      *
-     * @param structure Fill in with structured view data. The default implementation
-     * fills in all data that can be inferred from the view itself.
+     * <p><b>NOTE:</b> the {@code left} and {@code top} values set in
+     * {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the next
+     * {@link ViewGroup#isImportantForAutofill()} predecessor view included in the structure.
+     *
+     * <p>Views support the Autofill Framework mainly by:
+     * <ul>
+     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
+     *   <li>Notifying the Android System when the view value changed by calling
+     *       {@link AutofillManager#notifyValueChanged(View)}.
+     *   <li>Implementing the methods that autofill the view.
+     * </ul>
+     * <p>This method is responsible for the former; {@link #autofill(AutofillValue)} is responsible
+     * for the latter.
+     *
+     * @param structure fill in with structured view data for autofill purposes.
      * @param flags optional flags.
      *
      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
@@ -7470,32 +7584,56 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Called when assist structure is being retrieved from a view as part of an autofill request
-     * to generate additional virtual structure under this view.
+     * Populates a {@link ViewStructure} containing virtual children to fullfil an autofill
+     * request.
+     *
+     * <p>This method should be used when the view manages a virtual structure under this view. For
+     * example, a view that draws input fields using {@link #draw(Canvas)}.
      *
      * <p>When implementing this method, subclasses must follow the rules below:
      *
-     * <ol>
-     * <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
-     * children.
-     * <li>Call
-     * {@link android.view.autofill.AutofillManager#notifyViewEntered} and
-     * {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
-     * when the focus inside the view changed.
-     * <li>Call {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int,
-     * AutofillValue)} when the value of a child changed.
-     * <li>Call {@link AutofillManager#commit()} when the autofill context
-     * of the view structure changed and you want the current autofill interaction if such
-     * to be commited.
-     * <li>Call {@link AutofillManager#cancel()} when the autofill context
-     * of the view structure changed and you want the current autofill interaction if such
-     * to be cancelled.
-     * <li> The {@code left} and {@code top} values set in
-     * {@link ViewStructure#setDimens(int, int, int, int, int, int)} need to be relative to the next
-     * {@link ViewGroup#isImportantForAutofill() included} parent in the structure.
-     * </ol>
+     * <ul>
+     *   <li>Add virtual children by calling the {@link ViewStructure#newChild(int)} or
+     *       {@link ViewStructure#asyncNewChild(int)} methods, where the {@code id} is an unique id
+     *       identifying the children in the virtual structure.
+     *   <li>The children hierarchy can have multiple levels if necessary, but ideally it should
+     *       exclude intermediate levels that are irrelevant for autofill; that would improve the
+     *       autofill performance.
+     *   <li>Also implement {@link #autofill(SparseArray)} to autofill the virtual
+     *       children.
+     *   <li>Set the autofill properties of the child structure as defined by
+     *       {@link #onProvideAutofillStructure(ViewStructure, int)}, using
+     *       {@link ViewStructure#setAutofillId(AutofillId, int)} to set its autofill id.
+     *   <li>Call {@link android.view.autofill.AutofillManager#notifyViewEntered(View, int, Rect)}
+     *       and/or {@link android.view.autofill.AutofillManager#notifyViewExited(View, int)}
+     *       when the focused virtual child changed.
+     *   <li>Call
+     *    {@link android.view.autofill.AutofillManager#notifyValueChanged(View, int, AutofillValue)}
+     *       when the value of a virtual child changed.
+     *   <li>Call {@link AutofillManager#commit()} when the autofill context of the view structure
+     *       changed and the current context should be committed (for example, when the user tapped
+     *       a {@code SUBMIT} button in an HTML page).
+     *   <li>Call {@link AutofillManager#cancel()} when the autofill context of the view structure
+     *       changed and the current context should be canceled (for example, when the user tapped
+     *       a {@code CANCEL} button in an HTML page).
+     *   <li>Provide ways for users to manually request autofill by calling
+     *       {@link AutofillManager#requestAutofill(View, int, Rect)}.
+     *   <li>The {@code left} and {@code top} values set in
+     *       {@link ViewStructure#setDimens(int, int, int, int, int, int)} must be relative to the
+     *       next {@link ViewGroup#isImportantForAutofill()} predecessor view included in the
+     *       structure.
+     * </ul>
      *
-     * @param structure Fill in with structured view data.
+     * <p>Views with virtual children support the Autofill Framework mainly by:
+     * <ul>
+     *   <li>Providing the metadata defining what the virtual children mean and how they can be
+     *       autofilled.
+     *   <li>Implementing the methods that autofill the virtual children.
+     * </ul>
+     * <p>This method is responsible for the former; {@link #autofill(SparseArray)} is responsible
+     * for the latter.
+     *
+     * @param structure fill in with virtual children data for autofill purposes.
      * @param flags optional flags.
      *
      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
@@ -7506,15 +7644,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     /**
      * Automatically fills the content of this view with the {@code value}.
      *
-     * <p>By default does nothing, but views should override it (and {@link #getAutofillType()},
-     * {@link #getAutofillValue()}, and {@link #onProvideAutofillStructure(ViewStructure, int)}
-     * to support the Autofill Framework.
-     *
-     * <p>Typically, it is implemented by:
+     * <p>Views support the Autofill Framework mainly by:
+     * <ul>
+     *   <li>Providing the metadata defining what the view means and how it can be autofilled.
+     *   <li>Implementing the methods that autofill the view.
+     * </ul>
+     * <p>{@link #onProvideAutofillStructure(ViewStructure, int)} is responsible for the former,
+     * this method is responsible for latter.
      *
+     * <p>This method does nothing by default, but when overridden it typically:
      * <ol>
-     * <li>Calling the proper getter method on {@link AutofillValue} to fetch the actual value.
-     * <li>Passing the actual value to the equivalent setter in the view.
+     *   <li>Checks if the provided value matches the expected type (which is defined by
+     *       {@link #getAutofillType()}).
+     *   <li>Checks if the view is editable - if it isn't, it should return right away.
+     *   <li>Call the proper getter method on {@link AutofillValue} to fetch the actual value.
+     *   <li>Pass the actual value to the equivalent setter in the view.
      * </ol>
      *
      * <p>For example, a text-field view could implement the method this way:
@@ -7533,7 +7677,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * </pre>
      *
      * <p>If the value is updated asynchronously the next call to
-     * {@link AutofillManager#notifyValueChanged(View)} must happen <u>after</u> the value was
+     * {@link AutofillManager#notifyValueChanged(View)} must happen <b>after</b> the value was
      * changed to the autofilled value. If not, the view will not be considered autofilled.
      *
      * @param value value to be autofilled.
@@ -7542,11 +7686,19 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Automatically fills the content of a virtual views.
+     * Automatically fills the content of the virtual children within this view.
      *
-     * <p>See {@link #autofill(AutofillValue)} and
-     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info.
-     * <p>To indicate that a virtual view was autofilled
+     * <p>Views with virtual children support the Autofill Framework mainly by:
+     * <ul>
+     *   <li>Providing the metadata defining what the virtual children mean and how they can be
+     *       autofilled.
+     *   <li>Implementing the methods that autofill the virtual children.
+     * </ul>
+     * <p>{@link #onProvideAutofillVirtualStructure(ViewStructure, int)} is responsible for the
+     * former, this method is responsible for the latter - see {@link #autofill(AutofillValue)} and
+     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} for more info about autofill.
+     *
+     * <p><b>NOTE:</b> to indicate that a virtual view was autofilled,
      * <code>?android:attr/autofilledHighlight</code> should be drawn over it until the data
      * changes.
      *
@@ -7558,9 +7710,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Gets the unique identifier of this view on the screen for Autofill purposes.
+     * Gets the unique identifier of this view in the screen, for autofill purposes.
      *
-     * @return The View's Autofill id.
+     * @return The View's autofill id.
      */
     public final AutofillId getAutofillId() {
         if (mAutofillId == null) {
@@ -7572,20 +7724,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Describes the autofill type that should be used on calls to
-     * {@link #autofill(AutofillValue)} and {@link #autofill(SparseArray)}.
+     * Describes the autofill type of this view, so an
+     * {@link android.service.autofill.AutofillService} can create the proper {@link AutofillValue}
+     * when autofilling the view.
      *
-     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it (and
-     * {@link #autofill(AutofillValue)} to support the Autofill Framework.
+     * <p>By default returns {@link #AUTOFILL_TYPE_NONE}, but views should override it to properly
+     * support the Autofill Framework.
+     *
+     * @return either {@link #AUTOFILL_TYPE_NONE}, {@link #AUTOFILL_TYPE_TEXT},
+     * {@link #AUTOFILL_TYPE_LIST}, {@link #AUTOFILL_TYPE_DATE}, or {@link #AUTOFILL_TYPE_TOGGLE}.
+     *
+     * @see #onProvideAutofillStructure(ViewStructure, int)
+     * @see #autofill(AutofillValue)
      */
     public @AutofillType int getAutofillType() {
         return AUTOFILL_TYPE_NONE;
     }
 
     /**
-     * Describes the content of a view so that a autofill service can fill in the appropriate data.
+     * Gets the hints that help an {@link android.service.autofill.AutofillService} determine how
+     * to autofill the view with the user's data.
+     *
+     * <p>See {@link #setAutofillHints(String...)} for more info about these hints.
      *
-     * @return The hints set via the attribute or {@code null} if no hint it set.
+     * @return The hints set via the attribute or {@link #setAutofillHints(String...)}, or
+     * {@code null} if no hints were set.
      *
      * @attr ref android.R.styleable#View_autofillHints
      */
@@ -7604,9 +7767,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     /**
      * Gets the {@link View}'s current autofill value.
      *
-     * <p>By default returns {@code null}, but views should override it (and
-     * {@link #autofill(AutofillValue)}, and {@link #getAutofillType()} to support the Autofill
-     * Framework.
+     * <p>By default returns {@code null}, but views should override it to properly support the
+     * Autofill Framework.
+     *
+     * @see #onProvideAutofillStructure(ViewStructure, int)
+     * @see #autofill(AutofillValue)
      */
     @Nullable
     public AutofillValue getAutofillValue() {
@@ -7614,9 +7779,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Gets the mode for determining whether this View is important for autofill.
+     * Gets the mode for determining whether this view is important for autofill.
      *
-     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+     * <p>See {@link #setImportantForAutofill(int)} and {@link #isImportantForAutofill()} for more
+     * info about this mode.
      *
      * @return {@link #IMPORTANT_FOR_AUTOFILL_AUTO} by default, or value passed to
      * {@link #setImportantForAutofill(int)}.
@@ -7637,20 +7803,29 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Sets the mode for determining whether this View is important for autofill.
-     *
-     * <p>This property controls how this view is presented to the autofill components
-     * which help users to fill credentials, addresses, etc. For example, views
-     * that contain labels and input fields are useful for autofill components to
-     * determine the user context and provide values for the inputs. Note that the
-     * user can always override this by manually triggering autotill which would
-     * expose the view to the autofill provider.
+     * Sets the mode for determining whether this view is considered important for autofill.
      *
      * <p>The platform determines the importance for autofill automatically but you
-     * can use this method to customize the behavior. See the autofill modes below
-     * for more details.
+     * can use this method to customize the behavior. For example:
+     *
+     * <ol>
+     *   <li>When the view contents is irrelevant for autofill (for example, a text field used in a
+     *       "Captcha" challenge), it should be {@link #IMPORTANT_FOR_AUTOFILL_NO}.
+     *   <li>When both the view and its children are irrelevant for autofill (for example, the root
+     *       view of an activity containing a spreadhseet editor), it should be
+     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}.
+     *   <li>When the view content is relevant for autofill but its children aren't (for example,
+     *       a credit card expiration date represented by a custom view that overrides the proper
+     *       autofill methods and has 2 children representing the month and year), it should
+     *       be {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}.
+     * </ol>
      *
-     * <p>See {@link #setImportantForAutofill(int)} for more info about this mode.
+     * <p><b>NOTE:</strong> setting the mode as does {@link #IMPORTANT_FOR_AUTOFILL_NO} or
+     * {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS} does not guarantee the view (and its
+     * children) will be always be considered not important; for example, when the user explicitly
+     * makes an autofill request, all views are considered important. See
+     * {@link #isImportantForAutofill()} for more details about how the View's importance for
+     * autofill is used.
      *
      * @param mode {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, {@link #IMPORTANT_FOR_AUTOFILL_YES},
      * {@link #IMPORTANT_FOR_AUTOFILL_NO}, {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS},
@@ -7666,40 +7841,51 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
 
     /**
      * Hints the Android System whether the {@link android.app.assist.AssistStructure.ViewNode}
-     * associated with this View should be included in a {@link ViewStructure} used for
-     * autofill purposes.
+     * associated with this view is considered important for autofill purposes.
      *
      * <p>Generally speaking, a view is important for autofill if:
      * <ol>
-     * <li>The view can-be autofilled by an {@link android.service.autofill.AutofillService}.
-     * <li>The view contents can help an {@link android.service.autofill.AutofillService} to
-     * autofill other views.
+     * <li>The view can be autofilled by an {@link android.service.autofill.AutofillService}.
+     * <li>The view contents can help an {@link android.service.autofill.AutofillService}
+     *     determine how other views can be autofilled.
      * <ol>
      *
      * <p>For example, view containers should typically return {@code false} for performance reasons
-     * (since the important info is provided by their children), but if the container is actually
-     * whose children are part of a compound view, it should return {@code true} (and then override
-     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
-     * {@link #onProvideAutofillStructure(ViewStructure, int)} so its children are not included in
-     * the structure). On the other hand, views representing labels or editable fields should
-     * typically return {@code true}, but in some cases they could return {@code false} (for
-     * example, if they're part of a "Captcha" mechanism).
-     *
-     * <p>By default, this method returns {@code true} if {@link #getImportantForAutofill()} returns
-     * {@link #IMPORTANT_FOR_AUTOFILL_YES}, {@code false } if it returns
-     * {@link #IMPORTANT_FOR_AUTOFILL_NO}, and use some heuristics to define the importance when it
-     * returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}. Hence, it should rarely be overridden - Views
-     * should use {@link #setImportantForAutofill(int)} instead.
-     *
-     * <p><strong>Note:</strong> returning {@code false} does not guarantee the view will be
-     * excluded from the structure; for example, if the user explicitly requested autofill, the
-     * View might be always included.
-     *
-     * <p>This decision applies just for the view, not its children - if the view children are not
-     * important for autofill, the view should override
-     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} to simply call
-     * {@link #onProvideAutofillStructure(ViewStructure, int)} (instead of calling
-     * {@link #dispatchProvideAutofillStructure(ViewStructure, int)} for each child).
+     * (since the important info is provided by their children), but if its properties have relevant
+     * information (for example, a resource id called {@code credentials}, it should return
+     * {@code true}. On the other hand, views representing labels or editable fields should
+     * typically return {@code true}, but in some cases they could return {@code false}
+     * (for example, if they're part of a "Captcha" mechanism).
+     *
+     * <p>The value returned by this method depends on the value returned by
+     * {@link #getImportantForAutofill()}:
+     *
+     * <ol>
+     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_YES} or
+     *       {@link #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS}, then it returns {@code true}
+     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_NO} or
+     *       {@link #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS}, then it returns {@code false}
+     *   <li>if it returns {@link #IMPORTANT_FOR_AUTOFILL_AUTO}, then it uses some simple heuristics
+     *       that can return {@code true} in some cases (like a container with a resource id),
+     *       but {@code false} in most.
+     *   <li>otherwise, it returns {@code false}.
+     * </ol>
+     *
+     * <p>When a view is considered important for autofill:
+     * <ul>
+     *   <li>The view might automatically trigger an autofill request when focused on.
+     *   <li>The contents of the view are included in the {@link ViewStructure} used in an autofill
+     *       request.
+     * </ul>
+     *
+     * <p>On the other hand, when a view is considered not important for autofill:
+     * <ul>
+     *   <li>The view never automatically triggers autofill requests, but it can trigger a manual
+     *       request through {@link AutofillManager#requestAutofill(View)}.
+     *   <li>The contents of the view are not included in the {@link ViewStructure} used in an
+     *       autofill request, unless the request has the
+     *       {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag.
+     * </ul>
      *
      * @return whether the view is considered important for autofill.
      *
@@ -7709,6 +7895,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * @see #IMPORTANT_FOR_AUTOFILL_NO
      * @see #IMPORTANT_FOR_AUTOFILL_YES_EXCLUDE_DESCENDANTS
      * @see #IMPORTANT_FOR_AUTOFILL_NO_EXCLUDE_DESCENDANTS
+     * @see AutofillManager#requestAutofill(View)
      */
     public final boolean isImportantForAutofill() {
         // Check parent mode to ensure we're not hidden.
@@ -7833,29 +8020,38 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Dispatch creation of {@link ViewStructure} down the hierarchy.
+     * Dispatches creation of a {@link ViewStructure}s for autofill purposes down the hierarchy,
+     * when an Assist structure is being created as part of an autofill request.
      *
      * <p>The default implementation does the following:
-     *
      * <ul>
      *   <li>Sets the {@link AutofillId} in the structure.
      *   <li>Calls {@link #onProvideAutofillStructure(ViewStructure, int)}.
      *   <li>Calls {@link #onProvideAutofillVirtualStructure(ViewStructure, int)}.
      * </ul>
      *
-     * <p>When overridden, it must either call
-     * {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
-     * set the {@link AutofillId} in the structure (for example, by calling
-     * {@code structure.setAutofillId(getAutofillId())}).
+     * <p>Typically, this method should only be overridden by subclasses that provide a view
+     * hierarchy (such as {@link ViewGroup}) - other classes should override
+     * {@link #onProvideAutofillStructure(ViewStructure, int)} or
+     * {@link #onProvideAutofillVirtualStructure(ViewStructure, int)} instead.
      *
-     * <p>When providing your implementation you need to decide how to handle
-     * the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag which instructs you
-     * to report all views to the structure regardless if {@link #isImportantForAutofill()}
-     * returns true. We encourage you respect the importance property for a better
-     * user experience in your app. If the flag is not set then you should filter out
-     * not important views to optimize autofill performance in your app.
+     * <p>When overridden, it must:
      *
-     * @param structure Fill in with structured view data.
+     * <ul>
+     *   <li>Either call
+     *       {@code super.dispatchProvideAutofillStructure(structure, flags)} or explicitly
+     *       set the {@link AutofillId} in the structure (for example, by calling
+     *       {@code structure.setAutofillId(getAutofillId())}).
+     *   <li>Decide how to handle the {@link #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS} flag - when
+     *       set, all views in the structure should be considered important for autofill,
+     *       regardless of what {@link #isImportantForAutofill()} returns. We encourage you to
+     *       respect this flag to provide a better user experience - this flag is typically used
+     *       when an user explicitly requested autofill. If the flag is not set,
+     *       then only views marked as important for autofill should be included in the
+     *       structure - skipping non-important views optimizes the overall autofill performance.
+     * </ul>
+     *
+     * @param structure fill in with structured view data for autofill purposes.
      * @param flags optional flags.
      *
      * @see #AUTOFILL_FLAG_INCLUDE_NOT_IMPORTANT_VIEWS
@@ -9250,8 +9446,26 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
     }
 
     /**
-     * Sets the hints that helps the autofill service to select the appropriate data to fill the
-     * view.
+     * Sets the hints that help an {@link android.service.autofill.AutofillService} determine how
+     * to autofill the view with the user's data.
+     *
+     * <p>Typically, there is only one way to autofill a view, but there could be more than one.
+     * For example, if the application accepts either an username or email address to identify
+     * an user.
+     *
+     * <p>These hints are not validated by the Android System, but passed "as is" to the service.
+     * Hence, they can have any value, but it's recommended to use the {@code AUTOFILL_HINT_}
+     * constants such as:
+     * {@link #AUTOFILL_HINT_USERNAME}, {@link #AUTOFILL_HINT_PASSWORD},
+     * {@link #AUTOFILL_HINT_EMAIL_ADDRESS},
+     * {@link #AUTOFILL_HINT_NAME},
+     * {@link #AUTOFILL_HINT_PHONE},
+     * {@link #AUTOFILL_HINT_POSTAL_ADDRESS}, {@link #AUTOFILL_HINT_POSTAL_CODE},
+     * {@link #AUTOFILL_HINT_CREDIT_CARD_NUMBER}, {@link #AUTOFILL_HINT_CREDIT_CARD_SECURITY_CODE},
+     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DATE},
+     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_DAY},
+     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_MONTH} or
+     * {@link #AUTOFILL_HINT_CREDIT_CARD_EXPIRATION_YEAR}.
      *
      * @param autofillHints The autofill hints to set. If the array is emtpy, {@code null} is set.
      * @attr ref android.R.styleable#View_autofillHints
@@ -9966,12 +10180,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                 // Going from one cluster to another, so save last-focused.
                 // This covers cluster jumps because they are always FOCUS_DOWN
                 oldFocus.setFocusedInCluster(oldCluster);
+                if (!(oldFocus.mParent instanceof ViewGroup)) {
+                    return;
+                }
                 if (direction == FOCUS_FORWARD || direction == FOCUS_BACKWARD) {
                     // This is a result of ordered navigation so consider navigation through
                     // the previous cluster "complete" and clear its last-focused memory.
-                    if (oldFocus.mParent instanceof ViewGroup) {
-                        ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
-                    }
+                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
+                } else if (oldFocus instanceof ViewGroup
+                        && ((ViewGroup) oldFocus).getDescendantFocusability()
+                                == ViewGroup.FOCUS_AFTER_DESCENDANTS
+                        && ViewRootImpl.isViewDescendantOf(this, oldFocus)) {
+                    // This means oldFocus is not focusable since it obviously has a focusable
+                    // child (this). Don't restore focus to it in the future.
+                    ((ViewGroup) oldFocus.mParent).clearFocusedInCluster(oldFocus);
                 }
             }
         }
@@ -13018,7 +13240,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
                 // about in case nothing has focus.  even if this specific view
                 // isn't focusable, it may contain something that is, so let
                 // the root view try to give this focus if nothing else does.
-                if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
+                if ((mParent != null)) {
                     mParent.focusableViewAvailable(this);
                 }
             }
@@ -19809,18 +20031,23 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      * Check whether we need to draw a default focus highlight when this view gets focused,
      * which requires:
      * <ul>
-     *     <li>In the background, {@link android.R.attr#state_focused} is not defined.</li>
+     *     <li>In both background and foreground, {@link android.R.attr#state_focused}
+     *         is not defined.</li>
      *     <li>This view is not in touch mode.</li>
      *     <li>This view doesn't opt out for a default focus highlight, via
      *         {@link #setDefaultFocusHighlightEnabled(boolean)}.</li>
      *     <li>This view is attached to window.</li>
      * </ul>
      * @return {@code true} if a default focus highlight is needed.
+     * @hide
      */
-    private boolean isDefaultFocusHighlightNeeded(Drawable background) {
-        final boolean hasFocusStateSpecified = background == null || !background.isStateful()
-                || !background.hasFocusStateSpecified();
-        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && hasFocusStateSpecified
+    @TestApi
+    public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
+        final boolean lackFocusState = (background == null || !background.isStateful()
+                || !background.hasFocusStateSpecified())
+                && (foreground == null || !foreground.isStateful()
+                || !foreground.hasFocusStateSpecified());
+        return !isInTouchMode() && getDefaultFocusHighlightEnabled() && lackFocusState
                 && isAttachedToWindow() && sUseDefaultFocusHighlight;
     }
 
@@ -19832,7 +20059,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
      */
     private void switchDefaultFocusHighlight() {
         if (isFocused()) {
-            final boolean needed = isDefaultFocusHighlightNeeded(mBackground);
+            final boolean needed = isDefaultFocusHighlightNeeded(mBackground,
+                    mForegroundInfo == null ? null : mForegroundInfo.mDrawable);
             final boolean active = mDefaultFocusHighlight != null;
             if (needed && !active) {
                 setDefaultFocusHighlight(getDefaultFocusHighlightDrawable());
index 09464ee..4b79b8c 100644 (file)
@@ -833,8 +833,9 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
     public void focusableViewAvailable(View v) {
         if (mParent != null
                 // shortcut: don't report a new focusable view if we block our descendants from
-                // getting focus
+                // getting focus or if we're not visible
                 && (getDescendantFocusability() != FOCUS_BLOCK_DESCENDANTS)
+                && ((mViewFlags & VISIBILITY_MASK) == VISIBLE)
                 && (isFocusableInTouchMode() || !shouldBlockFocusForTouchscreen())
                 // shortcut: don't report a new focusable view if we already are focused
                 // (and we don't prefer our descendants)
@@ -1159,18 +1160,25 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
         // Determine whether we have a focused descendant.
         final int descendantFocusability = getDescendantFocusability();
         if (descendantFocusability != FOCUS_BLOCK_DESCENDANTS) {
-            final int count = mChildrenCount;
-            final View[] children = mChildren;
+            return hasFocusableChild(dispatchExplicit);
+        }
 
-            for (int i = 0; i < count; i++) {
-                final View child = children[i];
+        return false;
+    }
 
-                // In case the subclass has overridden has[Explicit]Focusable, dispatch
-                // to the expected one for each child even though we share logic here.
-                if ((dispatchExplicit && child.hasExplicitFocusable())
-                        || (!dispatchExplicit && child.hasFocusable())) {
-                    return true;
-                }
+    boolean hasFocusableChild(boolean dispatchExplicit) {
+        // Determine whether we have a focusable descendant.
+        final int count = mChildrenCount;
+        final View[] children = mChildren;
+
+        for (int i = 0; i < count; i++) {
+            final View child = children[i];
+
+            // In case the subclass has overridden has[Explicit]Focusable, dispatch
+            // to the expected one for each child even though we share logic here.
+            if ((dispatchExplicit && child.hasExplicitFocusable())
+                    || (!dispatchExplicit && child.hasFocusable())) {
+                return true;
             }
         }
 
@@ -3230,7 +3238,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             // will refer to a view not-in a cluster.
             return restoreFocusInCluster(View.FOCUS_DOWN);
         }
-        if (isKeyboardNavigationCluster()) {
+        if (isKeyboardNavigationCluster() || (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
             return false;
         }
         int descendentFocusability = getDescendantFocusability();
@@ -3248,7 +3256,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
                 return true;
             }
         }
-        if (descendentFocusability == FOCUS_AFTER_DESCENDANTS) {
+        if (descendentFocusability == FOCUS_AFTER_DESCENDANTS && !hasFocusableChild(false)) {
             return super.requestFocus(FOCUS_DOWN, null);
         }
         return false;
@@ -4914,7 +4922,8 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
             child.mParent = this;
         }
 
-        if (child.hasFocus()) {
+        final boolean childHasFocus = child.hasFocus();
+        if (childHasFocus) {
             requestChildFocus(child, child.findFocus());
         }
 
index 28ded55..2605b4a 100644 (file)
@@ -40,6 +40,7 @@ import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -2330,7 +2331,7 @@ public final class ViewRootImpl implements ViewParent,
 
         // Remember if we must report the next draw.
         if ((relayoutResult & WindowManagerGlobal.RELAYOUT_RES_FIRST_TIME) != 0) {
-            mReportNextDraw = true;
+            reportNextDraw();
         }
 
         boolean cancelDraw = mAttachInfo.mTreeObserver.dispatchOnPreDraw() || !isViewVisible;
@@ -2651,6 +2652,15 @@ public final class ViewRootImpl implements ViewParent,
 
     @Override
     public void onPreDraw(DisplayListCanvas canvas) {
+        // If mCurScrollY is not 0 then this influences the hardwareYOffset. The end result is we
+        // can apply offsets that are not handled by anything else, resulting in underdraw as
+        // the View is shifted (thus shifting the window background) exposing unpainted
+        // content. To handle this with minimal glitches we just clear to BLACK if the window
+        // is opaque. If it's not opaque then HWUI already internally does a glClear to
+        // transparent, so there's no risk of underdraw on non-opaque surfaces.
+        if (mCurScrollY != 0 && mHardwareYOffset != 0 && mAttachInfo.mThreadedRenderer.isOpaque()) {
+            canvas.drawColor(Color.BLACK);
+        }
         canvas.translate(-mHardwareXOffset, -mHardwareYOffset);
     }
 
@@ -2668,7 +2678,7 @@ public final class ViewRootImpl implements ViewParent,
     void outputDisplayList(View view) {
         view.mRenderNode.output();
         if (mAttachInfo.mThreadedRenderer != null) {
-            ((ThreadedRenderer)mAttachInfo.mThreadedRenderer).serializeDisplayListTree();
+            mAttachInfo.mThreadedRenderer.serializeDisplayListTree();
         }
     }
 
@@ -2731,11 +2741,8 @@ public final class ViewRootImpl implements ViewParent,
     /**
      * A count of the number of calls to pendingDrawFinished we
      * require to notify the WM drawing is complete.
-     *
-     * This starts at 1, for the ViewRootImpl surface itself.
-     * Subsurfaces may debt the value with drawPending.
      */
-    int mDrawsNeededToReport = 1;
+    int mDrawsNeededToReport = 0;
 
     /**
      * Delay notifying WM of draw finished until
@@ -2761,7 +2768,7 @@ public final class ViewRootImpl implements ViewParent,
 
     private void reportDrawFinished() {
         try {
-            mDrawsNeededToReport = 1;
+            mDrawsNeededToReport = 0;
             mWindowSession.finishDrawing(mWindow);
         } catch (RemoteException e) {
             // Have fun!
@@ -3772,13 +3779,12 @@ public final class ViewRootImpl implements ViewParent,
                     args.recycle();
 
                     if (msg.what == MSG_RESIZED_REPORT) {
-                        mReportNextDraw = true;
+                        reportNextDraw();
                     }
 
                     if (mView != null && framesChanged) {
                         forceLayout(mView);
                     }
-
                     requestLayout();
                 }
                 break;
@@ -7343,6 +7349,14 @@ public final class ViewRootImpl implements ViewParent,
         return false;
     }
 
+
+    private void reportNextDraw() {
+        if (mReportNextDraw == false) {
+            drawPending();
+        }
+        mReportNextDraw = true;
+    }
+
     /**
      * Force the window to report its next draw.
      * <p>
@@ -7352,7 +7366,7 @@ public final class ViewRootImpl implements ViewParent,
      * @hide
      */
     public void setReportNextDraw() {
-        mReportNextDraw = true;
+        reportNextDraw();
         invalidate();
     }
 
index ddfe697..0ecd20d 100644 (file)
@@ -269,6 +269,9 @@ public abstract class ViewStructure {
      * Create a new child {@link ViewStructure} in this view, putting into the list of
      * children at <var>index</var>.
      *
+     * <p><b>NOTE: </b>you must pre-allocate space for the child first, by calling either
+     * {@link #addChildCount(int)} or {@link #setChildCount(int)}.
+     *
      * @return Returns an fresh {@link ViewStructure} ready to be filled in.
      */
     public abstract ViewStructure newChild(int index);
@@ -279,6 +282,10 @@ public abstract class ViewStructure {
      * to build its content (and children etc).  Once done, some thread must call
      * {@link #asyncCommit} to tell the containing {@link ViewStructure} that the async
      * population is done.
+     *
+     * <p><b>NOTE: </b>you must pre-allocate space for the child first, by calling either
+     * {@link #addChildCount(int)} or {@link #setChildCount(int)}.
+     *
      * @return Returns an fresh {@link ViewStructure} ready to be filled in.
      */
     public abstract ViewStructure asyncNewChild(int index);
index 6dd8ecf..0d5c075 100644 (file)
@@ -624,6 +624,9 @@ public abstract class Window {
 
         /** Returns the current stack Id for the window. */
         int getWindowStackId() throws RemoteException;
+
+        /** Returns whether the window belongs to the task root. */
+        boolean isTaskRoot();
     }
 
     /**
@@ -2271,6 +2274,12 @@ public abstract class Window {
     public abstract void onMultiWindowModeChanged();
 
     /**
+     * Called when the activity changes to/from picture-in-picture mode.
+     * @hide
+     */
+    public abstract void onPictureInPictureModeChanged(boolean isInPictureInPictureMode);
+
+    /**
      * Called when the activity just relaunched.
      * @hide
      */
index 3f91476..4060b9a 100644 (file)
@@ -19,6 +19,7 @@ package android.view;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.KeyguardManager;
 import android.app.Presentation;
@@ -39,8 +40,6 @@ import java.util.Objects;
 
 /**
  * The interface that apps use to talk to the window manager.
- * <p>
- * Use <code>Context.getSystemService(Context.WINDOW_SERVICE)</code> to get one of these.
  * </p><p>
  * Each window manager instance is bound to a particular {@link Display}.
  * To obtain a {@link WindowManager} for a different display, use
@@ -52,10 +51,8 @@ import java.util.Objects;
  * {@link Presentation}.  The presentation will automatically obtain a
  * {@link WindowManager} and {@link Context} for that display.
  * </p>
- *
- * @see android.content.Context#getSystemService
- * @see android.content.Context#WINDOW_SERVICE
  */
+@SystemService(Context.WINDOW_SERVICE)
 public interface WindowManager extends ViewManager {
 
     /** @hide */
@@ -1903,6 +1900,7 @@ public interface WindowManager extends ViewManager {
          *
          * @hide
          */
+        @TestApi
         public CharSequence accessibilityTitle;
 
         /**
@@ -2185,6 +2183,7 @@ public interface WindowManager extends ViewManager {
         /** {@hide} */
         public static final int ACCESSIBILITY_ANCHOR_CHANGED = 1 << 24;
         /** {@hide} */
+        @TestApi
         public static final int ACCESSIBILITY_TITLE_CHANGED = 1 << 25;
         /** {@hide} */
         public static final int EVERYTHING_CHANGED = 0xffffffff;
index bf0e10f..55aed52 100644 (file)
@@ -225,6 +225,9 @@ public abstract class WindowManagerInternal {
      */
     public abstract boolean isKeyguardLocked();
 
+    /** @return {@code true} if the keyguard is going away. */
+    public abstract boolean isKeyguardGoingAway();
+
     /**
      * Gets the frame of a window given its token.
      *
index 7eb7bd9..41a8b8a 100644 (file)
@@ -24,6 +24,7 @@ import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.pm.PackageManager;
@@ -59,15 +60,6 @@ import java.util.List;
  * {@link android.view.View} changes etc. Parties interested in handling accessibility
  * events implement and register an accessibility service which extends
  * {@link android.accessibilityservice.AccessibilityService}.
- * <p>
- * To obtain a handle to the accessibility manager do the following:
- * </p>
- * <p>
- * <code>
- * <pre>AccessibilityManager accessibilityManager =
- *        (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE);</pre>
- * </code>
- * </p>
  *
  * @see AccessibilityEvent
  * @see AccessibilityNodeInfo
@@ -75,6 +67,7 @@ import java.util.List;
  * @see Context#getSystemService
  * @see Context#ACCESSIBILITY_SERVICE
  */
+@SystemService(Context.ACCESSIBILITY_SERVICE)
 public final class AccessibilityManager {
     private static final boolean DEBUG = false;
 
index 14f0b0a..d6455e7 100644 (file)
@@ -18,6 +18,7 @@ package android.view.accessibility;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
@@ -34,14 +35,8 @@ import java.util.Locale;
 /**
  * Contains methods for accessing and monitoring preferred video captioning state and visual
  * properties.
- * <p>
- * To obtain a handle to the captioning manager, do the following:
- * <p>
- * <code>
- * <pre>CaptioningManager captioningManager =
- *        (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);</pre>
- * </code>
  */
+@SystemService(Context.CAPTIONING_SERVICE)
 public class CaptioningManager {
     /** Default captioning enabled value. */
     private static final int DEFAULT_ENABLED = 0;
index a2aff93..310ec1c 100644 (file)
@@ -23,6 +23,7 @@ import static android.view.autofill.Helper.sVerbose;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentSender;
@@ -55,6 +56,7 @@ import java.util.Objects;
  *
  * <p>It is safe to call into this from any thread.
  */
+@SystemService(Context.AUTOFILL_MANAGER_SERVICE)
 public final class AutofillManager {
 
     private static final String TAG = "AutofillManager";
@@ -258,6 +260,11 @@ public final class AutofillManager {
          * @return The view, or {@code null} if not found
          */
         @Nullable View findViewByAccessibilityIdTraversal(int viewId);
+
+        /**
+         * Runs the specified action on the UI thread.
+         */
+        void runOnUiThread(Runnable action);
     }
 
     /**
@@ -1233,6 +1240,15 @@ public final class AutofillManager {
         return mService != null;
     }
 
+    private void post(Runnable runnable) {
+        final AutofillClient client = getClientLocked();
+        if (client == null) {
+            if (sVerbose) Log.v(TAG, "ignoring post() because client is null");
+            return;
+        }
+        client.runOnUiThread(runnable);
+    }
+
     /**
      * View tracking information. Once all tracked views become invisible the session is finished.
      */
@@ -1516,8 +1532,7 @@ public final class AutofillManager {
         public void setState(boolean enabled, boolean resetSession, boolean resetClient) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(
-                        () -> afm.setState(enabled, resetSession, resetClient));
+                afm.post(() -> afm.setState(enabled, resetSession, resetClient));
             }
         }
 
@@ -1525,8 +1540,7 @@ public final class AutofillManager {
         public void autofill(int sessionId, List<AutofillId> ids, List<AutofillValue> values) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(
-                        () -> afm.autofill(sessionId, ids, values));
+                afm.post(() -> afm.autofill(sessionId, ids, values));
             }
         }
 
@@ -1535,8 +1549,7 @@ public final class AutofillManager {
                 Intent fillInIntent) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(
-                        () -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent));
+                afm.post(() -> afm.authenticate(sessionId, authenticationId, intent, fillInIntent));
             }
         }
 
@@ -1545,9 +1558,8 @@ public final class AutofillManager {
                 Rect anchorBounds, IAutofillWindowPresenter presenter) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(
-                        () -> afm.requestShowFillUi(sessionId, id, width, height, anchorBounds,
-                                presenter));
+                afm.post(() -> afm.requestShowFillUi(sessionId, id, width, height, anchorBounds,
+                        presenter));
             }
         }
 
@@ -1555,7 +1567,7 @@ public final class AutofillManager {
         public void requestHideFillUi(int sessionId, AutofillId id) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() -> afm.requestHideFillUi(id));
+                afm.post(() -> afm.requestHideFillUi(id));
             }
         }
 
@@ -1563,7 +1575,7 @@ public final class AutofillManager {
         public void notifyNoFillUi(int sessionId, AutofillId id) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() -> afm.notifyNoFillUi(sessionId, id));
+                afm.post(() -> afm.notifyNoFillUi(sessionId, id));
             }
         }
 
@@ -1571,7 +1583,7 @@ public final class AutofillManager {
         public void startIntentSender(IntentSender intentSender) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() -> {
+                afm.post(() -> {
                     try {
                         afm.mContext.startIntentSender(intentSender, null, 0, 0, 0);
                     } catch (IntentSender.SendIntentException e) {
@@ -1586,7 +1598,7 @@ public final class AutofillManager {
                 boolean saveOnAllViewsInvisible, AutofillId[] fillableIds) {
             final AutofillManager afm = mAfm.get();
             if (afm != null) {
-                afm.mContext.getMainThreadHandler().post(() ->
+                afm.post(() ->
                         afm.setTrackedViews(sessionId, ids, saveOnAllViewsInvisible, fillableIds)
                 );
             }
index cd16a24..5f47638 100644 (file)
@@ -16,6 +16,8 @@
 
 package android.view.autofill;
 
+import static android.view.autofill.Helper.sVerbose;
+
 import android.annotation.NonNull;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
@@ -186,6 +188,10 @@ public class AutofillPopupWindow extends PopupWindow {
 
     @Override
     public void showAsDropDown(View anchor, int xoff, int yoff, int gravity) {
+        if (sVerbose) {
+            Log.v(TAG, "showAsDropDown(): anchor=" + anchor + ", xoff=" + xoff + ", yoff=" + yoff
+                    + ", isShowing(): " + isShowing());
+        }
         if (isShowing()) {
             return;
         }
index da9316c..e2f7979 100644 (file)
@@ -21,6 +21,7 @@ import static android.Manifest.permission.WRITE_SECURE_SETTINGS;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.graphics.Rect;
 import android.net.Uri;
@@ -73,8 +74,6 @@ import java.util.concurrent.TimeUnit;
 /**
  * Central system API to the overall input method framework (IMF) architecture,
  * which arbitrates interaction between applications and the current input method.
- * You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
  *
  * <p>Topics covered here:
  * <ol>
@@ -211,6 +210,7 @@ import java.util.concurrent.TimeUnit;
  * and want to make it available for use.</p>
  * </ul>
  */
+@SystemService(Context.INPUT_METHOD_SERVICE)
 public final class InputMethodManager {
     static final boolean DEBUG = false;
     static final String TAG = "InputMethodManager";
index 6b641db..efc88e2 100644 (file)
@@ -18,6 +18,7 @@ package android.view.textclassifier;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.ParcelFileDescriptor;
 import android.util.Log;
@@ -33,10 +34,8 @@ import java.util.Locale;
 
 /**
  * Interface to the text classification service.
- *
- * <p>You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService}.
  */
+@SystemService(Context.TEXT_CLASSIFICATION_SERVICE)
 public final class TextClassificationManager {
 
     private static final String LOG_TAG = "TextClassificationManager";
index b4e6c56..d9bfade 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.view.textservice;
 
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -30,8 +31,7 @@ import java.util.Locale;
 
 /**
  * System API to the overall text services, which arbitrates interaction between applications
- * and text services. You can retrieve an instance of this interface with
- * {@link Context#getSystemService(String) Context.getSystemService()}.
+ * and text services.
  *
  * The user can change the current text services in Settings. And also applications can specify
  * the target text services.
@@ -61,6 +61,7 @@ import java.util.Locale;
  * </ul>
  *
  */
+@SystemService(Context.TEXT_SERVICES_MANAGER_SERVICE)
 public final class TextServicesManager {
     private static final String TAG = TextServicesManager.class.getSimpleName();
     private static final boolean DBG = false;
index 9a39a17..121a8c5 100644 (file)
@@ -24,6 +24,8 @@ import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.database.DataSetObserver;
+import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.util.Log;
@@ -403,6 +405,7 @@ public class ActivityChooserView extends ViewGroup implements ActivityChooserMod
             }
             popupWindow.getListView().setContentDescription(mContext.getString(
                     R.string.activitychooserview_choose_application));
+            popupWindow.getListView().setSelector(new ColorDrawable(Color.TRANSPARENT));
         }
     }
 
index 1fef7cb..c19ee56 100644 (file)
@@ -3842,11 +3842,12 @@ public class Editor {
             }
 
             if (mTextView.canRequestAutofill()) {
-                final int mode = mTextView.getText().length() <= 0
-                        ? MenuItem.SHOW_AS_ACTION_IF_ROOM : MenuItem.SHOW_AS_ACTION_NEVER;
-                menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
-                        com.android.internal.R.string.autofill)
-                        .setShowAsAction(mode);
+                final String selected = mTextView.getSelectedText();
+                if (selected == null || selected.isEmpty()) {
+                    menu.add(Menu.NONE, TextView.ID_AUTOFILL, MENU_ITEM_ORDER_AUTOFILL,
+                            com.android.internal.R.string.autofill)
+                            .setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
+                }
             }
 
             if (mTextView.canPasteAsPlainText()) {
index 82071d7..fcb44af 100644 (file)
@@ -1718,20 +1718,17 @@ public class GridView extends AbsListView {
                     break;
 
                 case KeyEvent.KEYCODE_TAB:
-                    // XXX Sometimes it is useful to be able to TAB through the items in
+                    // TODO: Sometimes it is useful to be able to TAB through the items in
                     //     a GridView sequentially.  Unfortunately this can create an
                     //     asymmetry in TAB navigation order unless the list selection
                     //     always reverts to the top or bottom when receiving TAB focus from
-                    //     another widget.  Leaving this behavior disabled for now but
-                    //     perhaps it should be configurable (and more comprehensive).
-                    if (false) {
-                        if (event.hasNoModifiers()) {
-                            handled = resurrectSelectionIfNeeded()
-                                    || sequenceScroll(FOCUS_FORWARD);
-                        } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
-                            handled = resurrectSelectionIfNeeded()
-                                    || sequenceScroll(FOCUS_BACKWARD);
-                        }
+                    //     another widget.
+                    if (event.hasNoModifiers()) {
+                        handled = resurrectSelectionIfNeeded()
+                                || sequenceScroll(FOCUS_FORWARD);
+                    } else if (event.hasModifiers(KeyEvent.META_SHIFT_ON)) {
+                        handled = resurrectSelectionIfNeeded()
+                                || sequenceScroll(FOCUS_BACKWARD);
                     }
                     break;
             }
@@ -1991,7 +1988,7 @@ public class GridView extends AbsListView {
 
         if (!mStackFromBottom) {
             rowStart = childIndex - (childIndex % mNumColumns);
-            rowEnd = Math.max(rowStart + mNumColumns - 1, count);
+            rowEnd = Math.min(rowStart + mNumColumns - 1, count);
         } else {
             rowEnd = count - 1 - (invertedIndex - (invertedIndex % mNumColumns));
             rowStart = Math.max(0, rowEnd - mNumColumns + 1);
index 57818e2..1dc5b44 100644 (file)
@@ -19,6 +19,7 @@ package android.widget;
 import android.annotation.DrawableRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.TestApi;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.ColorStateList;
@@ -1640,4 +1641,13 @@ public class ImageView extends View {
         super.encodeProperties(stream);
         stream.addProperty("layout:baseline", getBaseline());
     }
+
+    /** @hide */
+    @Override
+    @TestApi
+    public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
+        final boolean lackFocusState = mDrawable == null || !mDrawable.isStateful()
+                || !mDrawable.hasFocusStateSpecified();
+        return super.isDefaultFocusHighlightNeeded(background, foreground) && lackFocusState;
+    }
 }
index 2f1f890..6b328ea 100644 (file)
@@ -1587,7 +1587,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
         if (textColorHighlight != 0) {
             setHighlightColor(textColorHighlight);
         }
-        setRawTextSize(textSize);
+        setRawTextSize(textSize, true /* shouldRequestLayout */);
         setElegantTextHeight(elegant);
         setLetterSpacing(letterSpacing);
         setFontFeatureSettings(fontFeatureSettings);
@@ -1757,7 +1757,10 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                             autoSizeMinTextSizeInPx,
                             autoSizeMaxTextSizeInPx,
                             DEFAULT_AUTO_SIZE_GRANULARITY_IN_PX);
-                    setupAutoSizeText();
+                    if (setupAutoSizeText()) {
+                        autoSizeText();
+                        invalidate();
+                    }
                     break;
                 default:
                     throw new IllegalArgumentException(
@@ -1807,7 +1810,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             validateAndSetAutoSizeTextTypeUniformConfiguration(autoSizeMinTextSizeInPx,
                     autoSizeMaxTextSizeInPx,
                     autoSizeStepGranularityInPx);
-            setupAutoSizeText();
+
+            if (setupAutoSizeText()) {
+                autoSizeText();
+                invalidate();
+            }
         }
     }
 
@@ -1856,7 +1863,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             } else {
                 mHasPresetAutoSizeValues = false;
             }
-            setupAutoSizeText();
+
+            if (setupAutoSizeText()) {
+                autoSizeText();
+                invalidate();
+            }
         }
     }
 
@@ -2014,20 +2025,19 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             : uniqueValidSizes.toArray();
     }
 
-    private void setupAutoSizeText() {
+    private boolean setupAutoSizeText() {
         if (supportsAutoSizeText() && mAutoSizeTextType == AUTO_SIZE_TEXT_TYPE_UNIFORM) {
             // Calculate the sizes set based on minimum size, maximum size and step size if we do
             // not have a predefined set of sizes or if the current sizes array is empty.
             if (!mHasPresetAutoSizeValues || mAutoSizeTextSizesInPx.length == 0) {
-                // Calculate sizes to choose from based on the current auto-size configuration.
-                int autoSizeValuesLength = (int) Math.ceil(
-                        (mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
-                                / mAutoSizeStepGranularityInPx);
-                // Also reserve a slot for the max size if it fits.
-                if ((mAutoSizeMaxTextSizeInPx - mAutoSizeMinTextSizeInPx)
-                        % mAutoSizeStepGranularityInPx == 0) {
+                int autoSizeValuesLength = 1;
+                float currentSize = Math.round(mAutoSizeMinTextSizeInPx);
+                while (Math.round(currentSize + mAutoSizeStepGranularityInPx)
+                        <= Math.round(mAutoSizeMaxTextSizeInPx)) {
                     autoSizeValuesLength++;
+                    currentSize += mAutoSizeStepGranularityInPx;
                 }
+
                 int[] autoSizeTextSizesInPx = new int[autoSizeValuesLength];
                 float sizeToAdd = mAutoSizeMinTextSizeInPx;
                 for (int i = 0; i < autoSizeValuesLength; i++) {
@@ -2038,8 +2048,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             }
 
             mNeedsAutoSizeText = true;
-            autoSizeText();
+        } else {
+            mNeedsAutoSizeText = false;
         }
+
+        return mNeedsAutoSizeText;
     }
 
     private int[] parseDimensionArray(TypedArray dimens) {
@@ -3387,7 +3400,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
 
         final int textSize = ta.getDimensionPixelSize(R.styleable.TextAppearance_textSize, 0);
         if (textSize != 0) {
-            setRawTextSize(textSize);
+            setRawTextSize(textSize, true /* shouldRequestLayout */);
         }
 
         final ColorStateList textColorHint = ta.getColorStateList(
@@ -3612,11 +3625,11 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
      */
     public void setTextSize(int unit, float size) {
         if (!isAutoSizeEnabled()) {
-            setTextSizeInternal(unit, size);
+            setTextSizeInternal(unit, size, true /* shouldRequestLayout */);
         }
     }
 
-    private void setTextSizeInternal(int unit, float size) {
+    private void setTextSizeInternal(int unit, float size, boolean shouldRequestLayout) {
         Context c = getContext();
         Resources r;
 
@@ -3626,15 +3639,15 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             r = c.getResources();
         }
 
-        setRawTextSize(TypedValue.applyDimension(
-                unit, size, r.getDisplayMetrics()));
+        setRawTextSize(TypedValue.applyDimension(unit, size, r.getDisplayMetrics()),
+                shouldRequestLayout);
     }
 
-    private void setRawTextSize(float size) {
+    private void setRawTextSize(float size, boolean shouldRequestLayout) {
         if (size != mTextPaint.getTextSize()) {
             mTextPaint.setTextSize(size);
 
-            if (mLayout != null) {
+            if (shouldRequestLayout && mLayout != null) {
                 // Do not auto-size right after setting the text size.
                 mNeedsAutoSizeText = false;
                 nullLayouts();
@@ -8257,22 +8270,44 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
      * Automatically computes and sets the text size.
      */
     private void autoSizeText() {
-        final int maxWidth = getWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
-        final int maxHeight = getHeight() - getExtendedPaddingBottom() - getExtendedPaddingTop();
-
-        if (maxWidth <= 0 || maxHeight <= 0) {
+        if (!isAutoSizeEnabled()) {
             return;
         }
 
-        synchronized (TEMP_RECTF) {
-            TEMP_RECTF.setEmpty();
-            TEMP_RECTF.right = maxWidth;
-            TEMP_RECTF.bottom = maxHeight;
-            final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
-            if (optimalTextSize != getTextSize()) {
-                setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize);
+        if (mNeedsAutoSizeText) {
+            if (getMeasuredWidth() <= 0 || getMeasuredHeight() <= 0) {
+                return;
+            }
+
+            final int availableWidth = mHorizontallyScrolling
+                    ? VERY_WIDE
+                    : getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
+            final int availableHeight = getMeasuredHeight() - getExtendedPaddingBottom()
+                    - getExtendedPaddingTop();
+
+            if (availableWidth <= 0 || availableHeight <= 0) {
+                return;
+            }
+
+            synchronized (TEMP_RECTF) {
+                TEMP_RECTF.setEmpty();
+                TEMP_RECTF.right = availableWidth;
+                TEMP_RECTF.bottom = availableHeight;
+                final float optimalTextSize = findLargestTextSizeWhichFits(TEMP_RECTF);
+
+                if (optimalTextSize != getTextSize()) {
+                    setTextSizeInternal(TypedValue.COMPLEX_UNIT_PX, optimalTextSize,
+                            false /* shouldRequestLayout */);
+
+                    makeNewLayout(availableWidth, 0 /* hintWidth */, UNKNOWN_BORING, UNKNOWN_BORING,
+                            mRight - mLeft - getCompoundPaddingLeft() - getCompoundPaddingRight(),
+                            false /* bringIntoView */);
+                }
             }
         }
+        // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
+        // after the next layout pass should set this to false.
+        mNeedsAutoSizeText = true;
     }
 
     /**
@@ -8314,11 +8349,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
         mTempTextPaint.set(getPaint());
         mTempTextPaint.setTextSize(suggestedSizeInPx);
 
-        final int availableWidth = mHorizontallyScrolling
-                ? VERY_WIDE
-                : getMeasuredWidth() - getTotalPaddingLeft() - getTotalPaddingRight();
         final StaticLayout.Builder layoutBuilder = StaticLayout.Builder.obtain(
-                text, 0, text.length(),  mTempTextPaint, availableWidth);
+                text, 0, text.length(),  mTempTextPaint, Math.round(availableSpace.right));
 
         layoutBuilder.setAlignment(getLayoutAlignment())
                 .setLineSpacing(getLineSpacingExtra(), getLineSpacingMultiplier())
@@ -8468,6 +8500,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                 // In a fixed-height view, so use our new text layout.
                 if (mLayoutParams.height != LayoutParams.WRAP_CONTENT
                         && mLayoutParams.height != LayoutParams.MATCH_PARENT) {
+                    autoSizeText();
                     invalidate();
                     return;
                 }
@@ -8476,6 +8509,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
                 // so use our new text layout.
                 if (mLayout.getHeight() == oldht
                         && (mHintLayout == null || mHintLayout.getHeight() == oldht)) {
+                    autoSizeText();
                     invalidate();
                     return;
                 }
@@ -8502,16 +8536,8 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
             mDeferScroll = -1;
             bringPointIntoView(Math.min(curs, mText.length()));
         }
-
-        if (isAutoSizeEnabled()) {
-            if (mNeedsAutoSizeText) {
-                // Call auto-size after the width and height have been calculated.
-                autoSizeText();
-            }
-            // Always try to auto-size if enabled. Functions that do not want to trigger auto-sizing
-            // after the next layout round should set this to false.
-            mNeedsAutoSizeText = true;
-        }
+        // Call auto-size after the width and height have been calculated.
+        autoSizeText();
     }
 
     private boolean isShowingHint() {
index 78566df..04f7c76 100644 (file)
@@ -129,7 +129,7 @@ interface IBatteryStats {
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
 
-    void noteBleScanStarted(in WorkSource ws);
+    void noteBleScanStarted(in WorkSource ws, boolean isUnoptimized);
     void noteBleScanStopped(in WorkSource ws);
     void noteResetBleScan();
     void noteBleScanResults(in WorkSource ws, int numNewResults);
index d19f1ec..bb54085 100644 (file)
@@ -109,17 +109,39 @@ public final class NightDisplayController {
     }
 
     /**
-     * Sets whether Night display should be activated.
+     * Sets whether Night display should be activated. This also sets the last activated time.
      *
      * @param activated {@code true} if Night display should be activated
      * @return {@code true} if the activated value was set successfully
      */
     public boolean setActivated(boolean activated) {
+        if (isActivated() != activated) {
+            Secure.putLongForUser(mContext.getContentResolver(),
+                    Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
+                    mUserId);
+        }
         return Secure.putIntForUser(mContext.getContentResolver(),
                 Secure.NIGHT_DISPLAY_ACTIVATED, activated ? 1 : 0, mUserId);
     }
 
     /**
+     * Returns the time when Night display's activation state last changed, or {@code null} if it
+     * has never been changed.
+     */
+    public Calendar getLastActivatedTime() {
+        final ContentResolver cr = mContext.getContentResolver();
+        final long lastActivatedTimeMillis = Secure.getLongForUser(
+                cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mUserId);
+        if (lastActivatedTimeMillis < 0) {
+            return null;
+        }
+
+        final Calendar lastActivatedTime = Calendar.getInstance();
+        lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
+        return lastActivatedTime;
+    }
+
+    /**
      * Returns the current auto mode value controlling when Night display will be automatically
      * activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM}, or
      * {@link #AUTO_MODE_TWILIGHT}.
index 797cf2b..d327180 100644 (file)
@@ -135,7 +135,7 @@ public class SystemNotificationChannels {
         channelsList.add(new NotificationChannel(
                 FOREGROUND_SERVICE,
                 context.getString(R.string.notification_channel_foreground_service),
-                NotificationManager.IMPORTANCE_MIN));
+                NotificationManager.IMPORTANCE_LOW));
 
         nm.createNotificationChannels(channelsList);
     }
index 17ef77c..235ebc8 100644 (file)
@@ -56,6 +56,7 @@ import android.util.LogWriter;
 import android.util.LongSparseArray;
 import android.util.LongSparseLongArray;
 import android.util.MutableInt;
+import android.util.Pools;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.Slog;
@@ -66,6 +67,7 @@ import android.util.TimeUtils;
 import android.util.Xml;
 import android.view.Display;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.util.ArrayUtils;
@@ -116,7 +118,7 @@ public class BatteryStatsImpl extends BatteryStats {
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 158 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 159 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -173,7 +175,6 @@ public class BatteryStatsImpl extends BatteryStats {
 
     private final PlatformIdleStateCallback mPlatformIdleStateCallback;
 
-
     final class MyHandler extends Handler {
         public MyHandler(Looper looper) {
             super(looper, null, true);
@@ -228,11 +229,11 @@ public class BatteryStatsImpl extends BatteryStats {
     }
 
     public interface ExternalStatsSync {
-        public static final int UPDATE_CPU = 0x01;
-        public static final int UPDATE_WIFI = 0x02;
-        public static final int UPDATE_RADIO = 0x04;
-        public static final int UPDATE_BT = 0x08;
-        public static final int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
+        int UPDATE_CPU = 0x01;
+        int UPDATE_WIFI = 0x02;
+        int UPDATE_RADIO = 0x04;
+        int UPDATE_BT = 0x08;
+        int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT;
 
         void scheduleSync(String reason, int flags);
         void scheduleCpuSyncDueToRemovedUid(int uid);
@@ -572,8 +573,6 @@ public class BatteryStatsImpl extends BatteryStats {
     private int mMinLearnedBatteryCapacity = -1;
     private int mMaxLearnedBatteryCapacity = -1;
 
-    private final NetworkStats.Entry mTmpNetworkStatsEntry = new NetworkStats.Entry();
-
     private long[] mCpuFreqs;
 
     private PowerProfile mPowerProfile;
@@ -637,19 +636,9 @@ public class BatteryStatsImpl extends BatteryStats {
 
     private void init(Clocks clocks) {
         mClocks = clocks;
-        mMobileNetworkStats = new NetworkStats[] {
-                new NetworkStats(mClocks.elapsedRealtime(), 50),
-                new NetworkStats(mClocks.elapsedRealtime(), 50),
-                new NetworkStats(mClocks.elapsedRealtime(), 50)
-        };
-        mWifiNetworkStats = new NetworkStats[] {
-                new NetworkStats(mClocks.elapsedRealtime(), 50),
-                new NetworkStats(mClocks.elapsedRealtime(), 50),
-                new NetworkStats(mClocks.elapsedRealtime(), 50)
-            };
     }
 
-    public static interface TimeBaseObs {
+    public interface TimeBaseObs {
         void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime);
         void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime);
     }
@@ -862,21 +851,19 @@ public class BatteryStatsImpl extends BatteryStats {
         final AtomicInteger mCount = new AtomicInteger();
         final TimeBase mTimeBase;
         int mLoadedCount;
-        int mLastCount;
         int mUnpluggedCount;
         int mPluggedCount;
 
-        Counter(TimeBase timeBase, Parcel in) {
+        public Counter(TimeBase timeBase, Parcel in) {
             mTimeBase = timeBase;
             mPluggedCount = in.readInt();
             mCount.set(mPluggedCount);
             mLoadedCount = in.readInt();
-            mLastCount = 0;
             mUnpluggedCount = in.readInt();
             timeBase.add(this);
         }
 
-        Counter(TimeBase timeBase) {
+        public Counter(TimeBase timeBase) {
             mTimeBase = timeBase;
             timeBase.add(this);
         }
@@ -887,11 +874,12 @@ public class BatteryStatsImpl extends BatteryStats {
             out.writeInt(mUnpluggedCount);
         }
 
+        @Override
         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
             mUnpluggedCount = mPluggedCount;
-            mCount.set(mPluggedCount);
         }
 
+        @Override
         public void onTimeStopped(long elapsedRealtime, long baseUptime, long baseRealtime) {
             mPluggedCount = mCount.get();
         }
@@ -926,17 +914,22 @@ public class BatteryStatsImpl extends BatteryStats {
 
         public void logState(Printer pw, String prefix) {
             pw.println(prefix + "mCount=" + mCount.get()
-                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
+                    + " mLoadedCount=" + mLoadedCount
                     + " mUnpluggedCount=" + mUnpluggedCount
                     + " mPluggedCount=" + mPluggedCount);
         }
 
-        void stepAtomic() {
-            mCount.incrementAndGet();
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+        public void stepAtomic() {
+            if (mTimeBase.isRunning()) {
+                mCount.incrementAndGet();
+            }
         }
 
         void addAtomic(int delta) {
-            mCount.addAndGet(delta);
+            if (mTimeBase.isRunning()) {
+                mCount.addAndGet(delta);
+            }
         }
 
         /**
@@ -944,7 +937,7 @@ public class BatteryStatsImpl extends BatteryStats {
          */
         void reset(boolean detachIfReset) {
             mCount.set(0);
-            mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
+            mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
             if (detachIfReset) {
                 detach();
             }
@@ -954,15 +947,16 @@ public class BatteryStatsImpl extends BatteryStats {
             mTimeBase.remove(this);
         }
 
-        void writeSummaryFromParcelLocked(Parcel out) {
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+        public void writeSummaryFromParcelLocked(Parcel out) {
             int count = mCount.get();
             out.writeInt(count);
         }
 
-        void readSummaryFromParcelLocked(Parcel in) {
+        @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
+        public void readSummaryFromParcelLocked(Parcel in) {
             mLoadedCount = in.readInt();
             mCount.set(mLoadedCount);
-            mLastCount = 0;
             mUnpluggedCount = mPluggedCount = mLoadedCount;
         }
     }
@@ -998,7 +992,6 @@ public class BatteryStatsImpl extends BatteryStats {
         @Override
         public void onTimeStarted(long elapsedRealTime, long baseUptime, long baseRealtime) {
             mUnpluggedCounts = copyArray(mPluggedCounts, mUnpluggedCounts);
-            mCounts = copyArray(mPluggedCounts, mCounts);
         }
 
         @Override
@@ -1029,11 +1022,13 @@ public class BatteryStatsImpl extends BatteryStats {
             if (counts == null) {
                 return;
             }
-            if (mCounts == null) {
-                mCounts = new long[counts.length];
-            }
-            for (int i = 0; i < counts.length; ++i) {
-                mCounts[i] += counts[i];
+            if (mTimeBase.isRunning()) {
+                if (mCounts == null) {
+                    mCounts = new long[counts.length];
+                }
+                for (int i = 0; i < counts.length; ++i) {
+                    mCounts[i] += counts[i];
+                }
             }
         }
 
@@ -1104,13 +1099,13 @@ public class BatteryStatsImpl extends BatteryStats {
             }
         }
 
-        private void fillArray(long[] a, long val) {
+        private static void fillArray(long[] a, long val) {
             if (a != null) {
                 Arrays.fill(a, val);
             }
         }
 
-        private void subtract(@NonNull long[] val, long[] toSubtract) {
+        private static void subtract(@NonNull long[] val, long[] toSubtract) {
             if (toSubtract == null) {
                 return;
             }
@@ -1119,7 +1114,7 @@ public class BatteryStatsImpl extends BatteryStats {
             }
         }
 
-        private long[] copyArray(long[] src, long[] dest) {
+        private static long[] copyArray(long[] src, long[] dest) {
             if (src == null) {
                 return null;
             } else {
@@ -1162,7 +1157,6 @@ public class BatteryStatsImpl extends BatteryStats {
         @Override
         public void onTimeStarted(long elapsedRealtime, long baseUptime, long baseRealtime) {
             mUnpluggedCount = mPluggedCount;
-            mCount = mPluggedCount;
         }
 
         @Override
@@ -1189,7 +1183,9 @@ public class BatteryStatsImpl extends BatteryStats {
         }
 
         void addCountLocked(long count) {
-            mCount += count;
+            if (mTimeBase.isRunning()) {
+                mCount += count;
+            }
         }
 
         /**
@@ -3522,6 +3518,7 @@ public class BatteryStatsImpl extends BatteryStats {
     public void removeIsolatedUidLocked(int isolatedUid) {
         mIsolatedUids.delete(isolatedUid);
         mKernelUidCpuTimeReader.removeUid(isolatedUid);
+        mKernelUidCpuFreqTimeReader.removeUid(isolatedUid);
     }
 
     public int mapUid(int uid) {
@@ -4193,7 +4190,10 @@ public class BatteryStatsImpl extends BatteryStats {
         getUidStatsLocked(uid).noteMobileRadioApWakeupLocked();
     }
 
-    public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
+    /**
+     * Updates the radio power state and returns true if an external stats collection should occur.
+     */
+    public boolean noteMobileRadioPowerStateLocked(int powerState, long timestampNs, int uid) {
         final long elapsedRealtime = mClocks.elapsedRealtime();
         final long uptime = mClocks.uptimeMillis();
         if (mMobileRadioPowerState != powerState) {
@@ -4230,13 +4230,15 @@ public class BatteryStatsImpl extends BatteryStats {
                 mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
             } else {
                 mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
-                updateMobileRadioStateLocked(realElapsedRealtimeMs, null);
                 mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
+                // Tell the caller to collect radio network/power stats.
+                return true;
             }
         }
+        return false;
     }
 
-    public void notePowerSaveMode(boolean enabled) {
+    public void notePowerSaveModeLocked(boolean enabled) {
         if (mPowerSaveModeEnabled != enabled) {
             int stepState = enabled ? STEP_LEVEL_MODE_POWER_SAVE : 0;
             mModStepMode |= (mCurStepMode&STEP_LEVEL_MODE_POWER_SAVE) ^ stepState;
@@ -4821,7 +4823,7 @@ public class BatteryStatsImpl extends BatteryStats {
         }
     }
 
-    private void noteBluetoothScanStartedLocked(int uid) {
+    private void noteBluetoothScanStartedLocked(int uid, boolean isUnoptimized) {
         uid = mapUid(uid);
         final long elapsedRealtime = mClocks.elapsedRealtime();
         final long uptime = mClocks.uptimeMillis();
@@ -4833,13 +4835,13 @@ public class BatteryStatsImpl extends BatteryStats {
             mBluetoothScanTimer.startRunningLocked(elapsedRealtime);
         }
         mBluetoothScanNesting++;
-        getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime);
+        getUidStatsLocked(uid).noteBluetoothScanStartedLocked(elapsedRealtime, isUnoptimized);
     }
 
-    public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws) {
+    public void noteBluetoothScanStartedFromSourceLocked(WorkSource ws, boolean isUnoptimized) {
         final int N = ws.size();
         for (int i = 0; i < N; i++) {
-            noteBluetoothScanStartedLocked(ws.get(i));
+            noteBluetoothScanStartedLocked(ws.get(i), isUnoptimized);
         }
     }
 
@@ -5236,28 +5238,26 @@ public class BatteryStatsImpl extends BatteryStats {
 
     public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
         if (TextUtils.isEmpty(iface)) return;
-        if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
-            mMobileIfaces = includeInStringArray(mMobileIfaces, iface);
-            if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mMobileIfaces);
-        } else {
-            mMobileIfaces = excludeFromStringArray(mMobileIfaces, iface);
-            if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mMobileIfaces);
-        }
-        if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
-            mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
-            if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
-        } else {
-            mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
-            if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
+
+        synchronized (mModemNetworkLock) {
+            if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
+                mModemIfaces = includeInStringArray(mModemIfaces, iface);
+                if (DEBUG) Slog.d(TAG, "Note mobile iface " + iface + ": " + mModemIfaces);
+            } else {
+                mModemIfaces = excludeFromStringArray(mModemIfaces, iface);
+                if (DEBUG) Slog.d(TAG, "Note non-mobile iface " + iface + ": " + mModemIfaces);
+            }
         }
-    }
 
-    public void noteNetworkStatsEnabledLocked() {
-        // During device boot, qtaguid isn't enabled until after the inital
-        // loading of battery stats. Now that they're enabled, take our initial
-        // snapshot for future delta calculation.
-        updateMobileRadioStateLocked(mClocks.elapsedRealtime(), null);
-        updateWifiStateLocked(null);
+        synchronized (mWifiNetworkLock) {
+            if (ConnectivityManager.isNetworkTypeWifi(networkType)) {
+                mWifiIfaces = includeInStringArray(mWifiIfaces, iface);
+                if (DEBUG) Slog.d(TAG, "Note wifi iface " + iface + ": " + mWifiIfaces);
+            } else {
+                mWifiIfaces = excludeFromStringArray(mWifiIfaces, iface);
+                if (DEBUG) Slog.d(TAG, "Note non-wifi iface " + iface + ": " + mWifiIfaces);
+            }
+        }
     }
 
     @Override public long getScreenOnTime(long elapsedRealtimeUs, int which) {
@@ -5611,7 +5611,9 @@ public class BatteryStatsImpl extends BatteryStats {
         /** Total time spent by the uid holding any partial wakelocks. */
         DualTimer mAggregatedPartialWakelockTimer;
         DualTimer mBluetoothScanTimer;
+        DualTimer mBluetoothUnoptimizedScanTimer;
         Counter mBluetoothScanResultCounter;
+        Counter mBluetoothScanResultBgCounter;
 
         int mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
         StopwatchTimer[] mProcessStateTimer;
@@ -6096,20 +6098,41 @@ public class BatteryStatsImpl extends BatteryStats {
             return mBluetoothScanTimer;
         }
 
-        public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs) {
+        public DualTimer createBluetoothUnoptimizedScanTimerLocked() {
+            if (mBluetoothUnoptimizedScanTimer == null) {
+                mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
+                        BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
+                        mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase);
+            }
+            return mBluetoothUnoptimizedScanTimer;
+        }
+
+        public void noteBluetoothScanStartedLocked(long elapsedRealtimeMs, boolean isUnoptimized) {
             createBluetoothScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
+            if (isUnoptimized) {
+                createBluetoothUnoptimizedScanTimerLocked().startRunningLocked(elapsedRealtimeMs);
+            }
         }
 
         public void noteBluetoothScanStoppedLocked(long elapsedRealtimeMs) {
             if (mBluetoothScanTimer != null) {
                 mBluetoothScanTimer.stopRunningLocked(elapsedRealtimeMs);
             }
+            // In the ble code, a scan cannot change types and nested starts are not possible.
+            // So if an unoptimizedScan is running, it is now being stopped.
+            if (mBluetoothUnoptimizedScanTimer != null
+                    && mBluetoothUnoptimizedScanTimer.isRunningLocked()) {
+                mBluetoothUnoptimizedScanTimer.stopRunningLocked(elapsedRealtimeMs);
+            }
         }
 
         public void noteResetBluetoothScanLocked(long elapsedRealtimeMs) {
             if (mBluetoothScanTimer != null) {
                 mBluetoothScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
             }
+            if (mBluetoothUnoptimizedScanTimer != null) {
+                mBluetoothUnoptimizedScanTimer.stopAllRunningLocked(elapsedRealtimeMs);
+            }
         }
 
         public Counter createBluetoothScanResultCounterLocked() {
@@ -6119,8 +6142,17 @@ public class BatteryStatsImpl extends BatteryStats {
             return mBluetoothScanResultCounter;
         }
 
+        public Counter createBluetoothScanResultBgCounterLocked() {
+            if (mBluetoothScanResultBgCounter == null) {
+                mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase);
+            }
+            return mBluetoothScanResultBgCounter;
+        }
+
         public void noteBluetoothScanResultsLocked(int numNewResults) {
             createBluetoothScanResultCounterLocked().addAtomic(numNewResults);
+            // Uses background timebase, so the count will only be incremented if uid in background.
+            createBluetoothScanResultBgCounterLocked().addAtomic(numNewResults);
         }
 
         @Override
@@ -6277,10 +6309,28 @@ public class BatteryStatsImpl extends BatteryStats {
         }
 
         @Override
+        public Timer getBluetoothUnoptimizedScanTimer() {
+            return mBluetoothUnoptimizedScanTimer;
+        }
+
+        @Override
+        public Timer getBluetoothUnoptimizedScanBackgroundTimer() {
+            if (mBluetoothUnoptimizedScanTimer == null) {
+                return null;
+            }
+            return mBluetoothUnoptimizedScanTimer.getSubTimer();
+        }
+
+        @Override
         public Counter getBluetoothScanResultCounter() {
             return mBluetoothScanResultCounter;
         }
 
+        @Override
+        public Counter getBluetoothScanResultBgCounter() {
+            return mBluetoothScanResultBgCounter;
+        }
+
         void makeProcessState(int i, Parcel in) {
             if (i < 0 || i >= NUM_PROCESS_STATE) return;
 
@@ -6531,9 +6581,13 @@ public class BatteryStatsImpl extends BatteryStats {
             active |= !resetTimerIfNotNull(mForegroundActivityTimer, false);
             active |= !resetTimerIfNotNull(mAggregatedPartialWakelockTimer, false);
             active |= !resetTimerIfNotNull(mBluetoothScanTimer, false);
+            active |= !resetTimerIfNotNull(mBluetoothUnoptimizedScanTimer, false);
             if (mBluetoothScanResultCounter != null) {
                 mBluetoothScanResultCounter.reset(false);
             }
+            if (mBluetoothScanResultBgCounter != null) {
+                mBluetoothScanResultBgCounter.reset(false);
+            }
 
             if (mProcessStateTimer != null) {
                 for (int i = 0; i < NUM_PROCESS_STATE; i++) {
@@ -6731,10 +6785,18 @@ public class BatteryStatsImpl extends BatteryStats {
                     mBluetoothScanTimer.detach();
                     mBluetoothScanTimer = null;
                 }
+                if (mBluetoothUnoptimizedScanTimer != null) {
+                    mBluetoothUnoptimizedScanTimer.detach();
+                    mBluetoothUnoptimizedScanTimer = null;
+                }
                 if (mBluetoothScanResultCounter != null) {
                     mBluetoothScanResultCounter.detach();
                     mBluetoothScanResultCounter = null;
                 }
+                if (mBluetoothScanResultBgCounter != null) {
+                    mBluetoothScanResultBgCounter.detach();
+                    mBluetoothScanResultBgCounter = null;
+                }
                 if (mUserActivityCounters != null) {
                     for (int i=0; i<NUM_USER_ACTIVITY_TYPES; i++) {
                         mUserActivityCounters[i].detach();
@@ -6919,12 +6981,24 @@ public class BatteryStatsImpl extends BatteryStats {
             } else {
                 out.writeInt(0);
             }
+            if (mBluetoothUnoptimizedScanTimer != null) {
+                out.writeInt(1);
+                mBluetoothUnoptimizedScanTimer.writeToParcel(out, elapsedRealtimeUs);
+            } else {
+                out.writeInt(0);
+            }
             if (mBluetoothScanResultCounter != null) {
                 out.writeInt(1);
                 mBluetoothScanResultCounter.writeToParcel(out);
             } else {
                 out.writeInt(0);
             }
+            if (mBluetoothScanResultBgCounter != null) {
+                out.writeInt(1);
+                mBluetoothScanResultBgCounter.writeToParcel(out);
+            } else {
+                out.writeInt(0);
+            }
             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
                 if (mProcessStateTimer[i] != null) {
                     out.writeInt(1);
@@ -7033,7 +7107,8 @@ public class BatteryStatsImpl extends BatteryStats {
             for (int j = 0; j < numWakelocks; j++) {
                 String wakelockName = in.readString();
                 Uid.Wakelock wakelock = new Wakelock(mBsi, this);
-                wakelock.readFromParcelLocked(timeBase, screenOffTimeBase, in);
+                wakelock.readFromParcelLocked(
+                        timeBase, screenOffTimeBase, mOnBatteryScreenOffBackgroundTimeBase, in);
                 mWakelockStats.add(wakelockName, wakelock);
             }
 
@@ -7168,10 +7243,22 @@ public class BatteryStatsImpl extends BatteryStats {
                 mBluetoothScanTimer = null;
             }
             if (in.readInt() != 0) {
+                mBluetoothUnoptimizedScanTimer = new DualTimer(mBsi.mClocks, Uid.this,
+                        BLUETOOTH_UNOPTIMIZED_SCAN_ON, null,
+                        mBsi.mOnBatteryTimeBase, mOnBatteryBackgroundTimeBase, in);
+            } else {
+                mBluetoothUnoptimizedScanTimer = null;
+            }
+            if (in.readInt() != 0) {
                 mBluetoothScanResultCounter = new Counter(mBsi.mOnBatteryTimeBase, in);
             } else {
                 mBluetoothScanResultCounter = null;
             }
+            if (in.readInt() != 0) {
+                mBluetoothScanResultBgCounter = new Counter(mOnBatteryBackgroundTimeBase, in);
+            } else {
+                mBluetoothScanResultBgCounter = null;
+            }
             mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
             for (int i = 0; i < NUM_PROCESS_STATE; i++) {
                 if (in.readInt() != 0) {
@@ -7298,8 +7385,9 @@ public class BatteryStatsImpl extends BatteryStats {
 
             /**
              * How long (in ms) this uid has been keeping the device partially awake.
+             * Tracks both the total time and the time while the app was in the background.
              */
-            DurationTimer mTimerPartial;
+            DualTimer mTimerPartial;
 
             /**
              * How long (in ms) this uid has been keeping the device fully awake.
@@ -7344,13 +7432,13 @@ public class BatteryStatsImpl extends BatteryStats {
              * @param in the Parcel to be read from.
              * return a new Timer, or null.
              */
-            private DurationTimer readDurationTimerFromParcel(int type,
-                    ArrayList<StopwatchTimer> pool, TimeBase timeBase, Parcel in) {
+            private DualTimer readDualTimerFromParcel(int type, ArrayList<StopwatchTimer> pool,
+                    TimeBase timeBase, TimeBase bgTimeBase, Parcel in) {
                 if (in.readInt() == 0) {
                     return null;
                 }
 
-                return new DurationTimer(mBsi.mClocks, mUid, type, pool, timeBase, in);
+                return new DualTimer(mBsi.mClocks, mUid, type, pool, timeBase, bgTimeBase, in);
             }
 
             boolean reset() {
@@ -7388,9 +7476,10 @@ public class BatteryStatsImpl extends BatteryStats {
                 return !wlactive;
             }
 
-            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase, Parcel in) {
-                mTimerPartial = readDurationTimerFromParcel(WAKE_TYPE_PARTIAL,
-                        mBsi.mPartialTimers, screenOffTimeBase, in);
+            void readFromParcelLocked(TimeBase timeBase, TimeBase screenOffTimeBase,
+                    TimeBase screenOffBgTimeBase, Parcel in) {
+                mTimerPartial = readDualTimerFromParcel(WAKE_TYPE_PARTIAL,
+                        mBsi.mPartialTimers, screenOffTimeBase, screenOffBgTimeBase, in);
                 mTimerFull = readStopwatchTimerFromParcel(WAKE_TYPE_FULL,
                         mBsi.mFullTimers, timeBase, in);
                 mTimerWindow = readStopwatchTimerFromParcel(WAKE_TYPE_WINDOW,
@@ -7416,49 +7505,6 @@ public class BatteryStatsImpl extends BatteryStats {
                 default: throw new IllegalArgumentException("type = " + type);
                 }
             }
-
-            public StopwatchTimer getStopwatchTimer(int type) {
-                switch (type) {
-                    case WAKE_TYPE_PARTIAL: {
-                        DurationTimer t = mTimerPartial;
-                        if (t == null) {
-                            t = new DurationTimer(mBsi.mClocks, mUid, WAKE_TYPE_PARTIAL,
-                                    mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase);
-                            mTimerPartial = t;
-                        }
-                        return t;
-                    }
-                    case WAKE_TYPE_FULL: {
-                        StopwatchTimer t = mTimerFull;
-                        if (t == null) {
-                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_FULL,
-                                    mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
-                            mTimerFull = t;
-                        }
-                        return t;
-                    }
-                    case WAKE_TYPE_WINDOW: {
-                        StopwatchTimer t = mTimerWindow;
-                        if (t == null) {
-                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_WINDOW,
-                                    mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
-                            mTimerWindow = t;
-                        }
-                        return t;
-                    }
-                    case WAKE_TYPE_DRAW: {
-                        StopwatchTimer t = mTimerDraw;
-                        if (t == null) {
-                            t = new StopwatchTimer(mBsi.mClocks, mUid, WAKE_TYPE_DRAW,
-                                    mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
-                            mTimerDraw = t;
-                        }
-                        return t;
-                    }
-                    default:
-                        throw new IllegalArgumentException("type=" + type);
-                }
-            }
         }
 
         public static class Sensor extends BatteryStats.Uid.Sensor {
@@ -8351,16 +8397,16 @@ public class BatteryStatsImpl extends BatteryStats {
             Wakelock wl = new Wakelock(mBsi, this);
             mWakelockStats.add(wlName, wl);
             if (in.readInt() != 0) {
-                wl.getStopwatchTimer(WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
+                getWakelockTimerLocked(wl, WAKE_TYPE_FULL).readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
-                wl.getStopwatchTimer(WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
+                getWakelockTimerLocked(wl, WAKE_TYPE_PARTIAL).readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
-                wl.getStopwatchTimer(WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
+                getWakelockTimerLocked(wl, WAKE_TYPE_WINDOW).readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
-                wl.getStopwatchTimer(WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
+                getWakelockTimerLocked(wl, WAKE_TYPE_DRAW).readSummaryFromParcelLocked(in);
             }
         }
 
@@ -8416,10 +8462,57 @@ public class BatteryStatsImpl extends BatteryStats {
             }
         }
 
+        public StopwatchTimer getWakelockTimerLocked(Wakelock wl, int type) {
+            if (wl == null) {
+                return null;
+            }
+            switch (type) {
+                case WAKE_TYPE_PARTIAL: {
+                    DualTimer t = wl.mTimerPartial;
+                    if (t == null) {
+                        t = new DualTimer(mBsi.mClocks, this, WAKE_TYPE_PARTIAL,
+                                mBsi.mPartialTimers, mBsi.mOnBatteryScreenOffTimeBase,
+                                mOnBatteryScreenOffBackgroundTimeBase);
+                        wl.mTimerPartial = t;
+                    }
+                    return t;
+                }
+                case WAKE_TYPE_FULL: {
+                    StopwatchTimer t = wl.mTimerFull;
+                    if (t == null) {
+                        t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_FULL,
+                                mBsi.mFullTimers, mBsi.mOnBatteryTimeBase);
+                        wl.mTimerFull = t;
+                    }
+                    return t;
+                }
+                case WAKE_TYPE_WINDOW: {
+                    StopwatchTimer t = wl.mTimerWindow;
+                    if (t == null) {
+                        t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_WINDOW,
+                                mBsi.mWindowTimers, mBsi.mOnBatteryTimeBase);
+                        wl.mTimerWindow = t;
+                    }
+                    return t;
+                }
+                case WAKE_TYPE_DRAW: {
+                    StopwatchTimer t = wl.mTimerDraw;
+                    if (t == null) {
+                        t = new StopwatchTimer(mBsi.mClocks, this, WAKE_TYPE_DRAW,
+                                mBsi.mDrawTimers, mBsi.mOnBatteryTimeBase);
+                        wl.mTimerDraw = t;
+                    }
+                    return t;
+                }
+                default:
+                    throw new IllegalArgumentException("type=" + type);
+            }
+        }
+
         public void noteStartWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
             Wakelock wl = mWakelockStats.startObject(name);
             if (wl != null) {
-                wl.getStopwatchTimer(type).startRunningLocked(elapsedRealtimeMs);
+                getWakelockTimerLocked(wl, type).startRunningLocked(elapsedRealtimeMs);
             }
             if (type == WAKE_TYPE_PARTIAL) {
                 createAggregatedPartialWakelockTimerLocked().startRunningLocked(elapsedRealtimeMs);
@@ -8435,7 +8528,7 @@ public class BatteryStatsImpl extends BatteryStats {
         public void noteStopWakeLocked(int pid, String name, int type, long elapsedRealtimeMs) {
             Wakelock wl = mWakelockStats.stopObject(name);
             if (wl != null) {
-                wl.getStopwatchTimer(type).stopRunningLocked(elapsedRealtimeMs);
+                getWakelockTimerLocked(wl, type).stopRunningLocked(elapsedRealtimeMs);
             }
             if (type == WAKE_TYPE_PARTIAL) {
                 if (mAggregatedPartialWakelockTimer != null) {
@@ -8613,27 +8706,25 @@ public class BatteryStatsImpl extends BatteryStats {
         mPlatformIdleStateCallback = null;
     }
 
-    public void setPowerProfile(PowerProfile profile) {
-        synchronized (this) {
-            mPowerProfile = profile;
+    public void setPowerProfileLocked(PowerProfile profile) {
+        mPowerProfile = profile;
 
-            // We need to initialize the KernelCpuSpeedReaders to read from
-            // the first cpu of each core. Once we have the PowerProfile, we have access to this
-            // information.
-            final int numClusters = mPowerProfile.getNumCpuClusters();
-            mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
-            int firstCpuOfCluster = 0;
-            for (int i = 0; i < numClusters; i++) {
-                final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
-                mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
-                        numSpeedSteps);
-                firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
-            }
+        // We need to initialize the KernelCpuSpeedReaders to read from
+        // the first cpu of each core. Once we have the PowerProfile, we have access to this
+        // information.
+        final int numClusters = mPowerProfile.getNumCpuClusters();
+        mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
+        int firstCpuOfCluster = 0;
+        for (int i = 0; i < numClusters; i++) {
+            final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
+            mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
+                    numSpeedSteps);
+            firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
+        }
 
-            if (mEstimatedBatteryCapacity == -1) {
-                // Initialize the estimated battery capacity to a known preset one.
-                mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
-            }
+        if (mEstimatedBatteryCapacity == -1) {
+            // Initialize the estimated battery capacity to a known preset one.
+            mEstimatedBatteryCapacity = (int) mPowerProfile.getBatteryCapacity();
         }
     }
 
@@ -8641,7 +8732,7 @@ public class BatteryStatsImpl extends BatteryStats {
         mCallback = cb;
     }
 
-    public void setRadioScanningTimeout(long timeout) {
+    public void setRadioScanningTimeoutLocked(long timeout) {
         if (mPhoneSignalScanningTimer != null) {
             mPhoneSignalScanningTimer.setTimeout(timeout);
         }
@@ -9333,277 +9424,293 @@ public class BatteryStatsImpl extends BatteryStats {
         }
     }
 
-    private String[] mMobileIfaces = EmptyArray.STRING;
+    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
+    private final Pools.Pool<NetworkStats> mNetworkStatsPool = new Pools.SynchronizedPool<>(6);
+
+    private final Object mWifiNetworkLock = new Object();
+
+    @GuardedBy("mWifiNetworkLock")
     private String[] mWifiIfaces = EmptyArray.STRING;
 
-    private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
+    @GuardedBy("mWifiNetworkLock")
+    private NetworkStats mLastWifiNetworkStats = new NetworkStats(0, -1);
 
-    private static final int NETWORK_STATS_LAST = 0;
-    private static final int NETWORK_STATS_NEXT = 1;
-    private static final int NETWORK_STATS_DELTA = 2;
+    private final Object mModemNetworkLock = new Object();
 
-    private NetworkStats[] mMobileNetworkStats;
-    private NetworkStats[] mWifiNetworkStats;
+    @GuardedBy("mModemNetworkLock")
+    private String[] mModemIfaces = EmptyArray.STRING;
 
-    /**
-     * Retrieves the delta of network stats for the given network ifaces. Uses networkStatsBuffer
-     * as a buffer of NetworkStats objects to cycle through when computing deltas.
-     */
-    private NetworkStats getNetworkStatsDeltaLocked(String[] ifaces,
-                                                    NetworkStats[] networkStatsBuffer)
-            throws IOException {
-        if (!SystemProperties.getBoolean(NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED,
-                false)) {
-            return null;
-        }
+    @GuardedBy("mModemNetworkLock")
+    private NetworkStats mLastModemNetworkStats = new NetworkStats(0, -1);
 
-        final NetworkStats stats = mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL,
-                ifaces, NetworkStats.TAG_NONE, networkStatsBuffer[NETWORK_STATS_NEXT]);
-        networkStatsBuffer[NETWORK_STATS_DELTA] = NetworkStats.subtract(stats,
-                networkStatsBuffer[NETWORK_STATS_LAST], null, null,
-                networkStatsBuffer[NETWORK_STATS_DELTA]);
-        networkStatsBuffer[NETWORK_STATS_NEXT] = networkStatsBuffer[NETWORK_STATS_LAST];
-        networkStatsBuffer[NETWORK_STATS_LAST] = stats;
-        return networkStatsBuffer[NETWORK_STATS_DELTA];
+    private NetworkStats readNetworkStatsLocked(String[] ifaces) {
+        try {
+            if (!ArrayUtils.isEmpty(ifaces)) {
+                return mNetworkStatsFactory.readNetworkStatsDetail(NetworkStats.UID_ALL, ifaces,
+                        NetworkStats.TAG_NONE, mNetworkStatsPool.acquire());
+            }
+        } catch (IOException e) {
+            Slog.e(TAG, "failed to read network stats for ifaces: " + Arrays.toString(ifaces));
+        }
+        return null;
     }
 
     /**
      * Distribute WiFi energy info and network traffic to apps.
      * @param info The energy information from the WiFi controller.
      */
-    public void updateWifiStateLocked(@Nullable final WifiActivityEnergyInfo info) {
+    public void updateWifiState(@Nullable final WifiActivityEnergyInfo info) {
         if (DEBUG_ENERGY) {
-            Slog.d(TAG, "Updating wifi stats");
+            Slog.d(TAG, "Updating wifi stats: " + Arrays.toString(mWifiIfaces));
         }
 
-        final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+        // Grab a separate lock to acquire the network stats, which may do I/O.
         NetworkStats delta = null;
-        try {
-            if (!ArrayUtils.isEmpty(mWifiIfaces)) {
-                delta = getNetworkStatsDeltaLocked(mWifiIfaces, mWifiNetworkStats);
+        synchronized (mWifiNetworkLock) {
+            final NetworkStats latestStats = readNetworkStatsLocked(mWifiIfaces);
+            if (latestStats != null) {
+                delta = NetworkStats.subtract(latestStats, mLastWifiNetworkStats, null, null,
+                        mNetworkStatsPool.acquire());
+                mNetworkStatsPool.release(mLastWifiNetworkStats);
+                mLastWifiNetworkStats = latestStats;
             }
-        } catch (IOException e) {
-            Slog.wtf(TAG, "Failed to get wifi network stats", e);
-            return;
         }
 
-        if (!mOnBatteryInternal) {
-            return;
-        }
-
-        SparseLongArray rxPackets = new SparseLongArray();
-        SparseLongArray txPackets = new SparseLongArray();
-        long totalTxPackets = 0;
-        long totalRxPackets = 0;
-        if (delta != null) {
-            final int size = delta.size();
-            for (int i = 0; i < size; i++) {
-                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
-
-                if (DEBUG_ENERGY) {
-                    Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
-                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
-                            + " txPackets=" + entry.txPackets);
+        synchronized (this) {
+            if (!mOnBatteryInternal) {
+                if (delta != null) {
+                    mNetworkStatsPool.release(delta);
                 }
+                return;
+            }
 
-                if (entry.rxBytes == 0 && entry.txBytes == 0) {
-                    // Skip the lookup below since there is no work to do.
-                    continue;
-                }
+            final long elapsedRealtimeMs = mClocks.elapsedRealtime();
+            SparseLongArray rxPackets = new SparseLongArray();
+            SparseLongArray txPackets = new SparseLongArray();
+            long totalTxPackets = 0;
+            long totalRxPackets = 0;
+            if (delta != null) {
+                NetworkStats.Entry entry = new NetworkStats.Entry();
+                final int size = delta.size();
+                for (int i = 0; i < size; i++) {
+                    entry = delta.getValues(i, entry);
 
-                final Uid u = getUidStatsLocked(mapUid(entry.uid));
-                if (entry.rxBytes != 0) {
-                    u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
-                            entry.rxPackets);
-                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
-                        u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
-                                entry.rxPackets);
+                    if (DEBUG_ENERGY) {
+                        Slog.d(TAG, "Wifi uid " + entry.uid + ": delta rx=" + entry.rxBytes
+                                + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+                                + " txPackets=" + entry.txPackets);
                     }
-                    mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
-                            entry.rxBytes);
-                    mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
-                            entry.rxPackets);
-
-                    rxPackets.put(u.getUid(), entry.rxPackets);
-
-                    // Sum the total number of packets so that the Rx Power can
-                    // be evenly distributed amongst the apps.
-                    totalRxPackets += entry.rxPackets;
-                }
 
-                if (entry.txBytes != 0) {
-                    u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
-                            entry.txPackets);
-                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
-                        u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
-                                entry.txPackets);
+                    if (entry.rxBytes == 0 && entry.txBytes == 0) {
+                        // Skip the lookup below since there is no work to do.
+                        continue;
                     }
-                    mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
-                            entry.txBytes);
-                    mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
-                            entry.txPackets);
 
-                    txPackets.put(u.getUid(), entry.txPackets);
+                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
+                    if (entry.rxBytes != 0) {
+                        u.noteNetworkActivityLocked(NETWORK_WIFI_RX_DATA, entry.rxBytes,
+                                entry.rxPackets);
+                        if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_RX_DATA, entry.rxBytes,
+                                    entry.rxPackets);
+                        }
+                        mNetworkByteActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
+                                entry.rxBytes);
+                        mNetworkPacketActivityCounters[NETWORK_WIFI_RX_DATA].addCountLocked(
+                                entry.rxPackets);
 
-                    // Sum the total number of packets so that the Tx Power can
-                    // be evenly distributed amongst the apps.
-                    totalTxPackets += entry.txPackets;
-                }
-            }
-        }
+                        rxPackets.put(u.getUid(), entry.rxPackets);
 
-        if (info != null) {
-            mHasWifiReporting = true;
+                        // Sum the total number of packets so that the Rx Power can
+                        // be evenly distributed amongst the apps.
+                        totalRxPackets += entry.rxPackets;
+                    }
 
-            // Measured in mAms
-            final long txTimeMs = info.getControllerTxTimeMillis();
-            final long rxTimeMs = info.getControllerRxTimeMillis();
-            final long idleTimeMs = info.getControllerIdleTimeMillis();
-            final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
+                    if (entry.txBytes != 0) {
+                        u.noteNetworkActivityLocked(NETWORK_WIFI_TX_DATA, entry.txBytes,
+                                entry.txPackets);
+                        if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                            u.noteNetworkActivityLocked(NETWORK_WIFI_BG_TX_DATA, entry.txBytes,
+                                    entry.txPackets);
+                        }
+                        mNetworkByteActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
+                                entry.txBytes);
+                        mNetworkPacketActivityCounters[NETWORK_WIFI_TX_DATA].addCountLocked(
+                                entry.txPackets);
 
-            long leftOverRxTimeMs = rxTimeMs;
-            long leftOverTxTimeMs = txTimeMs;
+                        txPackets.put(u.getUid(), entry.txPackets);
 
-            if (DEBUG_ENERGY) {
-                Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
-                Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
-                Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
-                Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
-                Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
+                        // Sum the total number of packets so that the Tx Power can
+                        // be evenly distributed amongst the apps.
+                        totalTxPackets += entry.txPackets;
+                    }
+                }
+                mNetworkStatsPool.release(delta);
+                delta = null;
             }
 
-            long totalWifiLockTimeMs = 0;
-            long totalScanTimeMs = 0;
-
-            // On the first pass, collect some totals so that we can normalize power
-            // calculations if we need to.
-            final int uidStatsSize = mUidStats.size();
-            for (int i = 0; i < uidStatsSize; i++) {
-                final Uid uid = mUidStats.valueAt(i);
-
-                // Sum the total scan power for all apps.
-                totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
-                        elapsedRealtimeMs * 1000) / 1000;
+            if (info != null) {
+                mHasWifiReporting = true;
 
-                // Sum the total time holding wifi lock for all apps.
-                totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
-                        elapsedRealtimeMs * 1000) / 1000;
-            }
-
-            if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
-                Slog.d(TAG, "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
-                        + rxTimeMs + " ms). Normalizing scan time.");
-            }
-            if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
-                Slog.d(TAG, "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
-                        + txTimeMs + " ms). Normalizing scan time.");
-            }
+                // Measured in mAms
+                final long txTimeMs = info.getControllerTxTimeMillis();
+                final long rxTimeMs = info.getControllerRxTimeMillis();
+                final long idleTimeMs = info.getControllerIdleTimeMillis();
+                final long totalTimeMs = txTimeMs + rxTimeMs + idleTimeMs;
 
-            // Actually assign and distribute power usage to apps.
-            for (int i = 0; i < uidStatsSize; i++) {
-                final Uid uid = mUidStats.valueAt(i);
+                long leftOverRxTimeMs = rxTimeMs;
+                long leftOverTxTimeMs = txTimeMs;
 
-                long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
-                        elapsedRealtimeMs * 1000) / 1000;
-                if (scanTimeSinceMarkMs > 0) {
-                    // Set the new mark so that next time we get new data since this point.
-                    uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
+                if (DEBUG_ENERGY) {
+                    Slog.d(TAG, "------ BEGIN WiFi power blaming ------");
+                    Slog.d(TAG, "  Tx Time:    " + txTimeMs + " ms");
+                    Slog.d(TAG, "  Rx Time:    " + rxTimeMs + " ms");
+                    Slog.d(TAG, "  Idle Time:  " + idleTimeMs + " ms");
+                    Slog.d(TAG, "  Total Time: " + totalTimeMs + " ms");
+                }
+
+                long totalWifiLockTimeMs = 0;
+                long totalScanTimeMs = 0;
+
+                // On the first pass, collect some totals so that we can normalize power
+                // calculations if we need to.
+                final int uidStatsSize = mUidStats.size();
+                for (int i = 0; i < uidStatsSize; i++) {
+                    final Uid uid = mUidStats.valueAt(i);
+
+                    // Sum the total scan power for all apps.
+                    totalScanTimeMs += uid.mWifiScanTimer.getTimeSinceMarkLocked(
+                            elapsedRealtimeMs * 1000) / 1000;
+
+                    // Sum the total time holding wifi lock for all apps.
+                    totalWifiLockTimeMs += uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
+                            elapsedRealtimeMs * 1000) / 1000;
+                }
+
+                if (DEBUG_ENERGY && totalScanTimeMs > rxTimeMs) {
+                    Slog.d(TAG,
+                            "  !Estimated scan time > Actual rx time (" + totalScanTimeMs + " ms > "
+                                    + rxTimeMs + " ms). Normalizing scan time.");
+                }
+                if (DEBUG_ENERGY && totalScanTimeMs > txTimeMs) {
+                    Slog.d(TAG,
+                            "  !Estimated scan time > Actual tx time (" + totalScanTimeMs + " ms > "
+                                    + txTimeMs + " ms). Normalizing scan time.");
+                }
+
+                // Actually assign and distribute power usage to apps.
+                for (int i = 0; i < uidStatsSize; i++) {
+                    final Uid uid = mUidStats.valueAt(i);
+
+                    long scanTimeSinceMarkMs = uid.mWifiScanTimer.getTimeSinceMarkLocked(
+                            elapsedRealtimeMs * 1000) / 1000;
+                    if (scanTimeSinceMarkMs > 0) {
+                        // Set the new mark so that next time we get new data since this point.
+                        uid.mWifiScanTimer.setMark(elapsedRealtimeMs);
+
+                        long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
+                        long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
+
+                        // Our total scan time is more than the reported Tx/Rx time.
+                        // This is possible because the cost of a scan is approximate.
+                        // Let's normalize the result so that we evenly blame each app
+                        // scanning.
+                        //
+                        // This means that we may have apps that transmitted/received packets not be
+                        // blamed for this, but this is fine as scans are relatively more expensive.
+                        if (totalScanTimeMs > rxTimeMs) {
+                            scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
+                                    totalScanTimeMs;
+                        }
+                        if (totalScanTimeMs > txTimeMs) {
+                            scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
+                                    totalScanTimeMs;
+                        }
 
-                    long scanRxTimeSinceMarkMs = scanTimeSinceMarkMs;
-                    long scanTxTimeSinceMarkMs = scanTimeSinceMarkMs;
+                        if (DEBUG_ENERGY) {
+                            Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
+                                    + scanRxTimeSinceMarkMs + " ms  Tx:"
+                                    + scanTxTimeSinceMarkMs + " ms)");
+                        }
 
-                    // Our total scan time is more than the reported Tx/Rx time.
-                    // This is possible because the cost of a scan is approximate.
-                    // Let's normalize the result so that we evenly blame each app
-                    // scanning.
-                    //
-                    // This means that we may have apps that transmitted/received packets not be
-                    // blamed for this, but this is fine as scans are relatively more expensive.
-                    if (totalScanTimeMs > rxTimeMs) {
-                        scanRxTimeSinceMarkMs = (rxTimeMs * scanRxTimeSinceMarkMs) /
-                                totalScanTimeMs;
-                    }
-                    if (totalScanTimeMs > txTimeMs) {
-                        scanTxTimeSinceMarkMs = (txTimeMs * scanTxTimeSinceMarkMs) /
-                                totalScanTimeMs;
+                        ControllerActivityCounterImpl activityCounter =
+                                uid.getOrCreateWifiControllerActivityLocked();
+                        activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
+                        activityCounter.getTxTimeCounters()[0].addCountLocked(
+                                scanTxTimeSinceMarkMs);
+                        leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
+                        leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
                     }
 
-                    if (DEBUG_ENERGY) {
-                        Slog.d(TAG, "  ScanTime for UID " + uid.getUid() + ": Rx:"
-                                + scanRxTimeSinceMarkMs + " ms  Tx:"
-                                + scanTxTimeSinceMarkMs + " ms)");
+                    // Distribute evenly the power consumed while Idle to each app holding a WiFi
+                    // lock.
+                    final long wifiLockTimeSinceMarkMs =
+                            uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
+                                    elapsedRealtimeMs * 1000) / 1000;
+                    if (wifiLockTimeSinceMarkMs > 0) {
+                        // Set the new mark so that next time we get new data since this point.
+                        uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
+
+                        final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
+                                / totalWifiLockTimeMs;
+                        if (DEBUG_ENERGY) {
+                            Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
+                                    + myIdleTimeMs + " ms");
+                        }
+                        uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
+                                .addCountLocked(myIdleTimeMs);
                     }
-
-                    ControllerActivityCounterImpl activityCounter =
-                            uid.getOrCreateWifiControllerActivityLocked();
-                    activityCounter.getRxTimeCounter().addCountLocked(scanRxTimeSinceMarkMs);
-                    activityCounter.getTxTimeCounters()[0].addCountLocked(scanTxTimeSinceMarkMs);
-                    leftOverRxTimeMs -= scanRxTimeSinceMarkMs;
-                    leftOverTxTimeMs -= scanTxTimeSinceMarkMs;
                 }
 
-                // Distribute evenly the power consumed while Idle to each app holding a WiFi
-                // lock.
-                final long wifiLockTimeSinceMarkMs = uid.mFullWifiLockTimer.getTimeSinceMarkLocked(
-                        elapsedRealtimeMs * 1000) / 1000;
-                if (wifiLockTimeSinceMarkMs > 0) {
-                    // Set the new mark so that next time we get new data since this point.
-                    uid.mFullWifiLockTimer.setMark(elapsedRealtimeMs);
+                if (DEBUG_ENERGY) {
+                    Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
+                    Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
+                }
 
-                    final long myIdleTimeMs = (wifiLockTimeSinceMarkMs * idleTimeMs)
-                            / totalWifiLockTimeMs;
+                // Distribute the remaining Tx power appropriately between all apps that transmitted
+                // packets.
+                for (int i = 0; i < txPackets.size(); i++) {
+                    final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
+                    final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs)
+                            / totalTxPackets;
                     if (DEBUG_ENERGY) {
-                        Slog.d(TAG, "  IdleTime for UID " + uid.getUid() + ": "
-                                + myIdleTimeMs + " ms");
+                        Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
                     }
-                    uid.getOrCreateWifiControllerActivityLocked().getIdleTimeCounter()
-                            .addCountLocked(myIdleTimeMs);
+                    uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
+                            .addCountLocked(myTxTimeMs);
                 }
-            }
 
-            if (DEBUG_ENERGY) {
-                Slog.d(TAG, "  New RxPower: " + leftOverRxTimeMs + " ms");
-                Slog.d(TAG, "  New TxPower: " + leftOverTxTimeMs + " ms");
-            }
-
-            // Distribute the remaining Tx power appropriately between all apps that transmitted
-            // packets.
-            for (int i = 0; i < txPackets.size(); i++) {
-                final Uid uid = getUidStatsLocked(txPackets.keyAt(i));
-                final long myTxTimeMs = (txPackets.valueAt(i) * leftOverTxTimeMs) / totalTxPackets;
-                if (DEBUG_ENERGY) {
-                    Slog.d(TAG, "  TxTime for UID " + uid.getUid() + ": " + myTxTimeMs + " ms");
+                // Distribute the remaining Rx power appropriately between all apps that received
+                // packets.
+                for (int i = 0; i < rxPackets.size(); i++) {
+                    final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
+                    final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs)
+                            / totalRxPackets;
+                    if (DEBUG_ENERGY) {
+                        Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
+                    }
+                    uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
+                            .addCountLocked(myRxTimeMs);
                 }
-                uid.getOrCreateWifiControllerActivityLocked().getTxTimeCounters()[0]
-                        .addCountLocked(myTxTimeMs);
-            }
 
-            // Distribute the remaining Rx power appropriately between all apps that received
-            // packets.
-            for (int i = 0; i < rxPackets.size(); i++) {
-                final Uid uid = getUidStatsLocked(rxPackets.keyAt(i));
-                final long myRxTimeMs = (rxPackets.valueAt(i) * leftOverRxTimeMs) / totalRxPackets;
-                if (DEBUG_ENERGY) {
-                    Slog.d(TAG, "  RxTime for UID " + uid.getUid() + ": " + myRxTimeMs + " ms");
-                }
-                uid.getOrCreateWifiControllerActivityLocked().getRxTimeCounter()
-                        .addCountLocked(myRxTimeMs);
-            }
+                // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
 
-            // Any left over power use will be picked up by the WiFi category in BatteryStatsHelper.
 
-            // Update WiFi controller stats.
-            mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
-            mWifiActivity.getTxTimeCounters()[0].addCountLocked(info.getControllerTxTimeMillis());
-            mWifiActivity.getIdleTimeCounter().addCountLocked(info.getControllerIdleTimeMillis());
+                // Update WiFi controller stats.
+                mWifiActivity.getRxTimeCounter().addCountLocked(info.getControllerRxTimeMillis());
+                mWifiActivity.getTxTimeCounters()[0].addCountLocked(
+                        info.getControllerTxTimeMillis());
+                mWifiActivity.getIdleTimeCounter().addCountLocked(
+                        info.getControllerIdleTimeMillis());
 
-            // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
-            final double opVolt = mPowerProfile.getAveragePower(
-                    PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
-            if (opVolt != 0) {
-                // We store the power drain as mAms.
-                mWifiActivity.getPowerCounter().addCountLocked(
-                        (long)(info.getControllerEnergyUsed() / opVolt));
+                // POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
+                final double opVolt = mPowerProfile.getAveragePower(
+                        PowerProfile.POWER_WIFI_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+                if (opVolt != 0) {
+                    // We store the power drain as mAms.
+                    mWifiActivity.getPowerCounter().addCountLocked(
+                            (long) (info.getControllerEnergyUsed() / opVolt));
+                }
             }
         }
     }
@@ -9611,133 +9718,148 @@ public class BatteryStatsImpl extends BatteryStats {
     /**
      * Distribute Cell radio energy info and network traffic to apps.
      */
-    public void updateMobileRadioStateLocked(final long elapsedRealtimeMs,
-                                             final ModemActivityInfo activityInfo) {
+    public void updateMobileRadioState(@Nullable final ModemActivityInfo activityInfo) {
         if (DEBUG_ENERGY) {
             Slog.d(TAG, "Updating mobile radio stats with " + activityInfo);
         }
 
+        // Grab a separate lock to acquire the network stats, which may do I/O.
         NetworkStats delta = null;
-        try {
-            if (!ArrayUtils.isEmpty(mMobileIfaces)) {
-                delta = getNetworkStatsDeltaLocked(mMobileIfaces, mMobileNetworkStats);
+        synchronized (mModemNetworkLock) {
+            final NetworkStats latestStats = readNetworkStatsLocked(mModemIfaces);
+            if (latestStats != null) {
+                delta = NetworkStats.subtract(latestStats, mLastModemNetworkStats, null, null,
+                        mNetworkStatsPool.acquire());
+                mNetworkStatsPool.release(mLastModemNetworkStats);
+                mLastModemNetworkStats = latestStats;
             }
-        } catch (IOException e) {
-            Slog.wtf(TAG, "Failed to get mobile network stats", e);
-            return;
-        }
-
-        if (!mOnBatteryInternal) {
-            return;
         }
 
-        long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
-                elapsedRealtimeMs * 1000);
-        mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
-
-        long totalRxPackets = 0;
-        long totalTxPackets = 0;
-        if (delta != null) {
-            final int size = delta.size();
-            for (int i = 0; i < size; i++) {
-                final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
-                if (entry.rxPackets == 0 && entry.txPackets == 0) {
-                    continue;
-                }
-
-                if (DEBUG_ENERGY) {
-                    Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
-                            + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
-                            + " txPackets=" + entry.txPackets);
-                }
-
-                totalRxPackets += entry.rxPackets;
-                totalTxPackets += entry.txPackets;
-
-                final Uid u = getUidStatsLocked(mapUid(entry.uid));
-                u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes, entry.rxPackets);
-                u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes, entry.txPackets);
-                if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
-                            entry.rxBytes, entry.rxPackets);
-                    u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
-                            entry.txBytes, entry.txPackets);
+        synchronized (this) {
+            if (!mOnBatteryInternal) {
+                if (delta != null) {
+                    mNetworkStatsPool.release(delta);
                 }
-
-                mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                        entry.rxBytes);
-                mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                        entry.txBytes);
-                mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
-                        entry.rxPackets);
-                mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
-                        entry.txPackets);
+                return;
             }
 
-            // Now distribute proportional blame to the apps that did networking.
-            long totalPackets = totalRxPackets + totalTxPackets;
-            if (totalPackets > 0) {
+            final long elapsedRealtimeMs = SystemClock.elapsedRealtime();
+            long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked(
+                    elapsedRealtimeMs * 1000);
+            mMobileRadioActivePerAppTimer.setMark(elapsedRealtimeMs);
+
+            long totalRxPackets = 0;
+            long totalTxPackets = 0;
+            if (delta != null) {
+                NetworkStats.Entry entry = new NetworkStats.Entry();
+                final int size = delta.size();
                 for (int i = 0; i < size; i++) {
-                    final NetworkStats.Entry entry = delta.getValues(i, mTmpNetworkStatsEntry);
+                    entry = delta.getValues(i, entry);
                     if (entry.rxPackets == 0 && entry.txPackets == 0) {
                         continue;
                     }
 
-                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
+                    if (DEBUG_ENERGY) {
+                        Slog.d(TAG, "Mobile uid " + entry.uid + ": delta rx=" + entry.rxBytes
+                                + " tx=" + entry.txBytes + " rxPackets=" + entry.rxPackets
+                                + " txPackets=" + entry.txPackets);
+                    }
 
-                    // Distribute total radio active time in to this app.
-                    final long appPackets = entry.rxPackets + entry.txPackets;
-                    final long appRadioTime = (radioTime * appPackets) / totalPackets;
-                    u.noteMobileRadioActiveTimeLocked(appRadioTime);
+                    totalRxPackets += entry.rxPackets;
+                    totalTxPackets += entry.txPackets;
 
-                    // Remove this app from the totals, so that we don't lose any time
-                    // due to rounding.
-                    radioTime -= appRadioTime;
-                    totalPackets -= appPackets;
+                    final Uid u = getUidStatsLocked(mapUid(entry.uid));
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_RX_DATA, entry.rxBytes,
+                            entry.rxPackets);
+                    u.noteNetworkActivityLocked(NETWORK_MOBILE_TX_DATA, entry.txBytes,
+                            entry.txPackets);
+                    if (entry.set == NetworkStats.SET_DEFAULT) { // Background transfers
+                        u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_RX_DATA,
+                                entry.rxBytes, entry.rxPackets);
+                        u.noteNetworkActivityLocked(NETWORK_MOBILE_BG_TX_DATA,
+                                entry.txBytes, entry.txPackets);
+                    }
 
-                    if (activityInfo != null) {
-                        ControllerActivityCounterImpl activityCounter =
-                                u.getOrCreateModemControllerActivityLocked();
-                        if (totalRxPackets > 0 && entry.rxPackets > 0) {
-                            final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
-                                    / totalRxPackets;
-                            activityCounter.getRxTimeCounter().addCountLocked(rxMs);
+                    mNetworkByteActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                            entry.rxBytes);
+                    mNetworkByteActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                            entry.txBytes);
+                    mNetworkPacketActivityCounters[NETWORK_MOBILE_RX_DATA].addCountLocked(
+                            entry.rxPackets);
+                    mNetworkPacketActivityCounters[NETWORK_MOBILE_TX_DATA].addCountLocked(
+                            entry.txPackets);
+                }
+
+                // Now distribute proportional blame to the apps that did networking.
+                long totalPackets = totalRxPackets + totalTxPackets;
+                if (totalPackets > 0) {
+                    for (int i = 0; i < size; i++) {
+                        entry = delta.getValues(i, entry);
+                        if (entry.rxPackets == 0 && entry.txPackets == 0) {
+                            continue;
                         }
 
-                        if (totalTxPackets > 0 && entry.txPackets > 0) {
-                            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
-                                long txMs = entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
-                                txMs /= totalTxPackets;
-                                activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
+                        final Uid u = getUidStatsLocked(mapUid(entry.uid));
+
+                        // Distribute total radio active time in to this app.
+                        final long appPackets = entry.rxPackets + entry.txPackets;
+                        final long appRadioTime = (radioTime * appPackets) / totalPackets;
+                        u.noteMobileRadioActiveTimeLocked(appRadioTime);
+
+                        // Remove this app from the totals, so that we don't lose any time
+                        // due to rounding.
+                        radioTime -= appRadioTime;
+                        totalPackets -= appPackets;
+
+                        if (activityInfo != null) {
+                            ControllerActivityCounterImpl activityCounter =
+                                    u.getOrCreateModemControllerActivityLocked();
+                            if (totalRxPackets > 0 && entry.rxPackets > 0) {
+                                final long rxMs = (entry.rxPackets * activityInfo.getRxTimeMillis())
+                                        / totalRxPackets;
+                                activityCounter.getRxTimeCounter().addCountLocked(rxMs);
+                            }
+
+                            if (totalTxPackets > 0 && entry.txPackets > 0) {
+                                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+                                    long txMs =
+                                            entry.txPackets * activityInfo.getTxTimeMillis()[lvl];
+                                    txMs /= totalTxPackets;
+                                    activityCounter.getTxTimeCounters()[lvl].addCountLocked(txMs);
+                                }
                             }
                         }
                     }
                 }
-            }
 
-            if (radioTime > 0) {
-                // Whoops, there is some radio time we can't blame on an app!
-                mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
-                mMobileRadioActiveUnknownCount.addCountLocked(1);
-            }
-        }
+                if (radioTime > 0) {
+                    // Whoops, there is some radio time we can't blame on an app!
+                    mMobileRadioActiveUnknownTime.addCountLocked(radioTime);
+                    mMobileRadioActiveUnknownCount.addCountLocked(1);
+                }
 
-        if (activityInfo != null) {
-            mHasModemReporting = true;
-            mModemActivity.getIdleTimeCounter().addCountLocked(activityInfo.getIdleTimeMillis());
-            mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
-            for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
-                mModemActivity.getTxTimeCounters()[lvl]
-                        .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
+                mNetworkStatsPool.release(delta);
+                delta = null;
             }
 
-            // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
-            final double opVolt = mPowerProfile.getAveragePower(
-                    PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
-            if (opVolt != 0) {
-                // We store the power drain as mAms.
-                mModemActivity.getPowerCounter().addCountLocked(
-                        (long) (activityInfo.getEnergyUsed() / opVolt));
+            if (activityInfo != null) {
+                mHasModemReporting = true;
+                mModemActivity.getIdleTimeCounter().addCountLocked(
+                        activityInfo.getIdleTimeMillis());
+                mModemActivity.getRxTimeCounter().addCountLocked(activityInfo.getRxTimeMillis());
+                for (int lvl = 0; lvl < ModemActivityInfo.TX_POWER_LEVELS; lvl++) {
+                    mModemActivity.getTxTimeCounters()[lvl]
+                            .addCountLocked(activityInfo.getTxTimeMillis()[lvl]);
+                }
+
+                // POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE is measured in mV, so convert to V.
+                final double opVolt = mPowerProfile.getAveragePower(
+                        PowerProfile.POWER_MODEM_CONTROLLER_OPERATING_VOLTAGE) / 1000.0;
+                if (opVolt != 0) {
+                    // We store the power drain as mAms.
+                    mModemActivity.getPowerCounter().addCountLocked(
+                            (long) (activityInfo.getEnergyUsed() / opVolt));
+                }
             }
         }
     }
@@ -10049,12 +10171,21 @@ public class BatteryStatsImpl extends BatteryStats {
         // Read the CPU data for each UID. This will internally generate a snapshot so next time
         // we read, we get a delta. If we are to distribute the cpu time, then do so. Otherwise
         // we just ignore the data.
-        final long startTimeMs = mClocks.elapsedRealtime();
+        final long startTimeMs = mClocks.uptimeMillis();
         mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
                 new KernelUidCpuTimeReader.Callback() {
                     @Override
                     public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
-                        final Uid u = getUidStatsLocked(mapUid(uid));
+                        uid = mapUid(uid);
+                        if (Process.isIsolated(uid)) {
+                            // This could happen if the isolated uid mapping was removed before
+                            // that process was actually killed.
+                            mKernelUidCpuTimeReader.removeUid(uid);
+                            Slog.d(TAG, "Got readings for an isolated uid with"
+                                    + " no mapping to owning uid: " + uid);
+                            return;
+                        }
+                        final Uid u = getUidStatsLocked(uid);
 
                         // Accumulate the total system and user time.
                         mTempTotalCpuUserTimeUs += userTimeUs;
@@ -10121,7 +10252,7 @@ public class BatteryStatsImpl extends BatteryStats {
             readKernelUidCpuFreqTimesLocked();
         }
 
-        final long elapse = (mClocks.elapsedRealtime() - startTimeMs);
+        final long elapse = (mClocks.uptimeMillis() - startTimeMs);
         if (DEBUG_ENERGY_CPU || (elapse >= 100)) {
             Slog.d(TAG, "Reading cpu stats took " + elapse + " ms");
         }
@@ -10219,7 +10350,14 @@ public class BatteryStatsImpl extends BatteryStats {
 
                     @Override
                     public void onUidCpuFreqTime(int uid, long[] cpuFreqTimeMs) {
-                        final Uid u = getUidStatsLocked(mapUid(uid));
+                        uid = mapUid(uid);
+                        if (Process.isIsolated(uid)) {
+                            mKernelUidCpuFreqTimeReader.removeUid(uid);
+                            Slog.d(TAG, "Got freq readings for an isolated uid with"
+                                    + " no mapping to owning uid: " + uid);
+                            return;
+                        }
+                        final Uid u = getUidStatsLocked(uid);
                         if (u.mCpuFreqTimeMs == null) {
                             u.mCpuFreqTimeMs = new LongSamplingCounterArray(mOnBatteryTimeBase);
                         }
@@ -10885,6 +11023,7 @@ public class BatteryStatsImpl extends BatteryStats {
      */
     public void removeUidStatsLocked(int uid) {
         mKernelUidCpuTimeReader.removeUid(uid);
+        mKernelUidCpuFreqTimeReader.removeUid(uid);
         mUidStats.remove(uid);
     }
 
@@ -11380,8 +11519,14 @@ public class BatteryStatsImpl extends BatteryStats {
                 u.createBluetoothScanTimerLocked().readSummaryFromParcelLocked(in);
             }
             if (in.readInt() != 0) {
+                u.createBluetoothUnoptimizedScanTimerLocked().readSummaryFromParcelLocked(in);
+            }
+            if (in.readInt() != 0) {
                 u.createBluetoothScanResultCounterLocked().readSummaryFromParcelLocked(in);
             }
+            if (in.readInt() != 0) {
+                u.createBluetoothScanResultBgCounterLocked().readSummaryFromParcelLocked(in);
+            }
             u.mProcessState = ActivityManager.PROCESS_STATE_NONEXISTENT;
             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
                 if (in.readInt() != 0) {
@@ -11789,12 +11934,24 @@ public class BatteryStatsImpl extends BatteryStats {
             } else {
                 out.writeInt(0);
             }
+            if (u.mBluetoothUnoptimizedScanTimer != null) {
+                out.writeInt(1);
+                u.mBluetoothUnoptimizedScanTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
+            } else {
+                out.writeInt(0);
+            }
             if (u.mBluetoothScanResultCounter != null) {
                 out.writeInt(1);
                 u.mBluetoothScanResultCounter.writeSummaryFromParcelLocked(out);
             } else {
                 out.writeInt(0);
             }
+            if (u.mBluetoothScanResultBgCounter != null) {
+                out.writeInt(1);
+                u.mBluetoothScanResultBgCounter.writeSummaryFromParcelLocked(out);
+            } else {
+                out.writeInt(0);
+            }
             for (int i = 0; i < Uid.NUM_PROCESS_STATE; i++) {
                 if (u.mProcessStateTimer[i] != null) {
                     out.writeInt(1);
index 568c883..ff521c2 100644 (file)
@@ -53,14 +53,29 @@ public class KernelUidCpuFreqTimeReader {
 
     private SparseArray<long[]> mLastUidCpuFreqTimeMs = new SparseArray<>();
 
+    // We check the existence of proc file a few times (just in case it is not ready yet when we
+    // start reading) and if it is not available, we simply ignore further read requests.
+    private static final int TOTAL_READ_ERROR_COUNT = 5;
+    private int mReadErrorCounter;
+    private boolean mProcFileAvailable;
+
     public void readDelta(@Nullable Callback callback) {
+        if (!mProcFileAvailable && mReadErrorCounter >= TOTAL_READ_ERROR_COUNT) {
+            return;
+        }
         try (BufferedReader reader = new BufferedReader(new FileReader(UID_TIMES_PROC_FILE))) {
             readDelta(reader, callback);
+            mProcFileAvailable = true;
         } catch (IOException e) {
+            mReadErrorCounter++;
             Slog.e(TAG, "Failed to read " + UID_TIMES_PROC_FILE + ": " + e);
         }
     }
 
+    public void removeUid(int uid) {
+        mLastUidCpuFreqTimeMs.delete(uid);
+    }
+
     @VisibleForTesting
     public void readDelta(BufferedReader reader, @Nullable Callback callback) throws IOException {
         String line = reader.readLine();
index ba3aa36..60fbbe9 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.internal.policy;
 
+import android.graphics.Outline;
+import android.view.ViewOutlineProvider;
 import android.view.accessibility.AccessibilityNodeInfo;
 import com.android.internal.R;
 import com.android.internal.policy.PhoneWindow.PanelFeatureState;
@@ -135,6 +137,16 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
                     com.android.internal.R.id.navigationBarBackground,
                     0 /* hideWindowFlag */);
 
+    // This is used to workaround an issue where the PiP shadow can be transparent if the window
+    // background is transparent
+    private static final ViewOutlineProvider PIP_OUTLINE_PROVIDER = new ViewOutlineProvider() {
+        @Override
+        public void getOutline(View view, Outline outline) {
+            outline.setRect(0, 0, view.getWidth(), view.getHeight());
+            outline.setAlpha(1f);
+        }
+    };
+
     // Cludge to address b/22668382: Set the shadow size to the maximum so that the layer
     // size calculation takes the shadow size into account. We set the elevation currently
     // to max until the first layout command has been executed.
@@ -142,6 +154,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
 
     private boolean mElevationAdjustedForStack = false;
 
+    // Keeps track of the picture-in-picture mode for the view shadow
+    private boolean mIsInPictureInPictureMode;
+
+    // Stores the previous outline provider prior to applying PIP_OUTLINE_PROVIDER
+    private ViewOutlineProvider mLastOutlineProvider;
+
     int mDefaultOpacity = PixelFormat.OPAQUE;
 
     /** The feature ID of the panel, or -1 if this is the application's DecorView */
@@ -1404,6 +1422,41 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
         }
     }
 
+    /**
+     * Overrides the view outline when the activity enters picture-in-picture to ensure that it has
+     * an opaque shadow even if the window background is completely transparent. This only applies
+     * to activities that are currently the task root.
+     */
+    public void updatePictureInPictureOutlineProvider(boolean isInPictureInPictureMode) {
+        if (mIsInPictureInPictureMode == isInPictureInPictureMode) {
+            return;
+        }
+
+        if (isInPictureInPictureMode) {
+            final Window.WindowControllerCallback callback =
+                    mWindow.getWindowControllerCallback();
+            if (callback != null && callback.isTaskRoot()) {
+                // Call super implementation directly as we don't want to save the PIP outline
+                // provider to be restored
+                super.setOutlineProvider(PIP_OUTLINE_PROVIDER);
+            }
+        } else {
+            // Restore the previous outline provider
+            if (getOutlineProvider() != mLastOutlineProvider) {
+                setOutlineProvider(mLastOutlineProvider);
+            }
+        }
+        mIsInPictureInPictureMode = isInPictureInPictureMode;
+    }
+
+    @Override
+    public void setOutlineProvider(ViewOutlineProvider provider) {
+        super.setOutlineProvider(provider);
+
+        // Save the outline provider set to ensure that we can restore when the activity leaves PiP
+        mLastOutlineProvider = provider;
+    }
+
     private void drawableChanged() {
         if (mChanging) {
             return;
index a019ea1..3f35c91 100644 (file)
@@ -93,4 +93,10 @@ oneway interface IKeyguardService {
      * @param fadeoutDuration the duration of the exit animation, in milliseconds
      */
     void startKeyguardExitAnimation(long startTime, long fadeoutDuration);
+
+    /**
+     * Notifies the Keyguard that the power key was pressed while locked and launched Home rather
+     * than putting the device to sleep or waking up.
+     */
+    void onShortPowerPressedGoHome();
 }
index 243916b..8fe9100 100644 (file)
@@ -729,6 +729,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
     }
 
     @Override
+    public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+        if (mDecor != null) {
+            mDecor.updatePictureInPictureOutlineProvider(isInPictureInPictureMode);
+        }
+    }
+
+    @Override
     public void reportActivityRelaunched() {
         if (mDecor != null && mDecor.getViewRootImpl() != null) {
             mDecor.getViewRootImpl().reportActivityRelaunched();
index ce89501..66b777e 100644 (file)
@@ -31,7 +31,7 @@ import java.io.StringWriter;
  */
 public final class DumpUtils {
     private static final String TAG = "DumpUtils";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     private DumpUtils() {
     }
index ebbbdbb..d834e63 100644 (file)
@@ -25,6 +25,7 @@ import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.widget.PopupWindow;
 import android.widget.TextView;
 
 public class TooltipPopup {
@@ -32,6 +33,7 @@ public class TooltipPopup {
 
     private final Context mContext;
 
+    private final PopupWindow mPopupWindow;
     private final View mContentView;
     private final TextView mMessageView;
 
@@ -43,6 +45,8 @@ public class TooltipPopup {
     public TooltipPopup(Context context) {
         mContext = context;
 
+        mPopupWindow = new PopupWindow(context);
+        mPopupWindow.setBackgroundDrawable(null);
         mContentView = LayoutInflater.from(mContext).inflate(
                 com.android.internal.R.layout.tooltip, null);
         mMessageView = (TextView) mContentView.findViewById(
@@ -70,17 +74,16 @@ public class TooltipPopup {
 
         computePosition(anchorView, anchorX, anchorY, fromTouch, mLayoutParams);
 
-        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-        wm.addView(mContentView, mLayoutParams);
+        mPopupWindow.setContentView(mContentView);
+        mPopupWindow.showAtLocation(
+            anchorView, mLayoutParams.gravity, mLayoutParams.x, mLayoutParams.y);
     }
 
     public void hide() {
         if (!isShowing()) {
             return;
         }
-
-        WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
-        wm.removeView(mContentView);
+        mPopupWindow.dismiss();
     }
 
     public View getContentView() {
@@ -88,7 +91,7 @@ public class TooltipPopup {
     }
 
     public boolean isShowing() {
-        return mContentView.getParent() != null;
+        return mPopupWindow.isShowing();
     }
 
     public void updateContent(CharSequence tooltipText) {
index 369bb7f..785fd2c 100644 (file)
@@ -16,7 +16,7 @@
 
 #define ATRACE_TAG ATRACE_TAG_DALVIK
 #define LOG_TAG "AndroidRuntime"
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 1
 
 #include <android_runtime/AndroidRuntime.h>
 #include <binder/IBinder.h>
@@ -661,7 +661,7 @@ int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
             checkJni = true;
         }
     }
-    ALOGD("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
+    ALOGV("CheckJNI is %s\n", checkJni ? "ON" : "OFF");
     if (checkJni) {
         /* extended JNI checking */
         addOption("-Xcheck:jni");
index b6b1ac7..18cf8ca 100644 (file)
@@ -15,7 +15,7 @@
 ** limitations under the License.
 */
 
-//#define LOG_NDEBUG 0
+#define LOG_NDEBUG 1
 #define LOG_TAG "Radio-JNI"
 #include <utils/Log.h>
 
@@ -955,7 +955,7 @@ int register_android_hardware_Radio(JNIEnv *env)
 
     int ret = RegisterMethodsOrDie(env, kRadioModuleClassPathName, gModuleMethods, NELEM(gModuleMethods));
 
-    ALOGI("%s DONE", __FUNCTION__);
+    ALOGV("%s DONE", __FUNCTION__);
 
     return ret;
 }
index 192e3bb..438b123 100644 (file)
@@ -208,8 +208,15 @@ public:
 
     void detachAnimators() {
         // Remove animators from the list and post a delayed message in future to end the animator
+        // For infinite animators, remove the listener so we no longer hold a global ref to the AVD
+        // java object, and therefore the AVD objects in both native and Java can be properly
+        // released.
         for (auto& anim : mRunningVDAnimators) {
             detachVectorDrawableAnimator(anim.get());
+            anim->clearOneShotListener();
+        }
+        for (auto& anim : mPausedVDAnimators) {
+            anim->clearOneShotListener();
         }
         mRunningVDAnimators.clear();
         mPausedVDAnimators.clear();
@@ -877,7 +884,8 @@ static jobject android_view_ThreadedRenderer_createHardwareBitmapFromRenderNode(
     sp<IGraphicBufferProducer> producer;
     sp<IGraphicBufferConsumer> rawConsumer;
     BufferQueue::createBufferQueue(&producer, &rawConsumer);
-    rawConsumer->setMaxBufferCount(1);
+    // We only need 1 buffer but some drivers have bugs so workaround it by setting max count to 2
+    rawConsumer->setMaxBufferCount(2);
     sp<BufferItemConsumer> consumer = new BufferItemConsumer(rawConsumer,
             GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_NEVER);
     consumer->setDefaultBufferSize(width, height);
index 8b73daf..e212c43 100644 (file)
@@ -310,7 +310,7 @@ message GlobalSettingsProto {
     SettingProto lte_service_forced = 265;
     SettingProto ephemeral_cookie_max_size_bytes = 266;
     SettingProto enable_ephemeral_feature = 267;
-    SettingProto uninstalled_ephemeral_app_cache_duration_millis = 268;
+    SettingProto installed_instant_app_min_cache_period = 268;
     SettingProto allow_user_switching_when_system_user_locked = 269;
     SettingProto boot_count = 270;
     SettingProto safe_boot_disallowed = 271;
@@ -331,6 +331,10 @@ message GlobalSettingsProto {
     SettingProto network_recommendations_package = 286;
     SettingProto bluetooth_a2dp_supports_optional_codecs_prefix = 287;
     SettingProto bluetooth_a2dp_optional_codecs_enabled_prefix = 288;
+    SettingProto installed_instant_app_max_cache_period = 289;
+    SettingProto uninstalled_instant_app_min_cache_period = 290;
+    SettingProto uninstalled_instant_app_max_cache_period = 291;
+    SettingProto unused_static_shared_lib_min_cache_period = 292;
 }
 
 message SecureSettingsProto {
index 8ed76de..f8044e2 100644 (file)
                 android:description="@string/permdesc_useDataInBackground"
                 android:protectionLevel="normal" />
 
+    <!-- @hide Allows an application to set display offsets for the screen.
+         This permission is not available to third party applications. -->
+    <permission android:name="android.permission.SET_DISPLAY_OFFSET"
+        android:protectionLevel="signature|privileged" />
 
     <!-- ================================== -->
     <!-- Permissions affecting the system wallpaper -->
diff --git a/core/res/res/drawable/stat_sys_vitals.xml b/core/res/res/drawable/stat_sys_vitals.xml
new file mode 100644 (file)
index 0000000..213dd5f
--- /dev/null
@@ -0,0 +1,29 @@
+<!--
+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.
+-->
+<!-- "system vitals", as represented by an EKG trace -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0">
+    <path
+        android:fillColor="#FF000000"
+        android:pathData="M19.5608645,12.0797103 L17.15,5.15 L15.25,5.15 L11.95,15.95 L9.75,11.5 L7.95,11.55 L7.2,13.3
+        L6.65,14.6 L3.25,14.6 L3.25,16.6 L7.35,16.6 L8,16.6 L8.25,16 L8.9,14.3 L11.2,18.85 L13.15,18.85 L16.25,8.8
+        L17.5310733,12.642689 C17.2014325,12.9992627 17,13.4761078 17,14 C17,15.1045695 17.8954305,16 19,16
+        C20.1045695,16 21,15.1045695 21,14 C21,13.0901368 20.3924276,12.3221796 19.5608645,12.0797103 Z M21,3
+        C22,3 23,4 23,5 L23,19 C23,20 22,21 21,21 L3,21 C1.9,21 1,20.1 1,19 L1,5 C1,4 2,3 3,3 L21,3 Z" />
+</vector>
index 9c02402..129d38a 100644 (file)
@@ -1,9 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
-    <background android:drawable="@android:color/white" />
+    <background android:drawable="@drawable/sym_def_app_icon_background" />
     <foreground>
-        <inset android:inset="27.7%">
-            <bitmap android:src="@mipmap/sym_def_app_icon"/>
-        </inset>
+        <bitmap android:src="@mipmap/sym_def_app_icon_foreground"/>
     </foreground>
 </adaptive-icon>
diff --git a/core/res/res/drawable/sym_def_app_icon_background.xml b/core/res/res/drawable/sym_def_app_icon_background.xml
new file mode 100644 (file)
index 0000000..5755210
--- /dev/null
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<vector
+    android:height="108dp"
+    android:width="108dp"
+    android:viewportHeight="108.0"
+    android:viewportWidth="108.0"
+    xmlns:android="http://schemas.android.com/apk/res/android">
+    <path android:fillColor="@android:color/material_deep_teal_500"
+        android:pathData="M0,0h108v108h-108z"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M19,0L19,108"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M9,0L9,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M39,0L39,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M29,0L29,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M59,0L59,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M49,0L49,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M79,0L79,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M69,0L69,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M89,0L89,108"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M99,0L99,108"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,89L108,89"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,99L108,99"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,69L108,69"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,79L108,79"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,49L108,49"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,59L108,59"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,29L108,29"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,39L108,39"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,19L108,19"
+        android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
+    <path android:fillColor="#00000000" android:pathData="M0,9L108,9"
+        android:strokeColor="#66FFFFFF" android:strokeWidth="0.8"/>
+</vector>
+
index 66e400a..4678f76 100644 (file)
@@ -21,7 +21,7 @@
     android:paddingStart="?attr/listPreferredItemPaddingStart"
     android:paddingEnd="?attr/listPreferredItemPaddingEnd"
     android:minWidth="196dip"
-    android:background="?attr/activatedBackgroundIndicator"
+    android:background="?attr/selectableItemBackground"
     android:orientation="vertical" >
 
     <LinearLayout
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png
new file mode 100644 (file)
index 0000000..4e526c9
Binary files /dev/null and b/core/res/res/mipmap-hdpi/sym_def_app_icon_foreground.png differ
diff --git a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png
deleted file mode 100644 (file)
index bf58413..0000000
Binary files a/core/res/res/mipmap-hdpi/sym_def_app_icon_maskable.png and /dev/null differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png
new file mode 100644 (file)
index 0000000..2c38c71
Binary files /dev/null and b/core/res/res/mipmap-mdpi/sym_def_app_icon_foreground.png differ
diff --git a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png
deleted file mode 100644 (file)
index 47f6f81..0000000
Binary files a/core/res/res/mipmap-mdpi/sym_def_app_icon_maskable.png and /dev/null differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png
new file mode 100644 (file)
index 0000000..072467e
Binary files /dev/null and b/core/res/res/mipmap-xhdpi/sym_def_app_icon_foreground.png differ
diff --git a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644 (file)
index f60b896..0000000
Binary files a/core/res/res/mipmap-xhdpi/sym_def_app_icon_maskable.png and /dev/null differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png
new file mode 100644 (file)
index 0000000..78a6b7a
Binary files /dev/null and b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_foreground.png differ
diff --git a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644 (file)
index 6d4f315..0000000
Binary files a/core/res/res/mipmap-xxhdpi/sym_def_app_icon_maskable.png and /dev/null differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png
new file mode 100644 (file)
index 0000000..68ebe33
Binary files /dev/null and b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_foreground.png differ
diff --git a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png b/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png
deleted file mode 100644 (file)
index 08e54d0..0000000
Binary files a/core/res/res/mipmap-xxxhdpi/sym_def_app_icon_maskable.png and /dev/null differ
index d78a980..f77980a 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om taal en uitleg te kies"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> word bo-oor ander programme gewys"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> wys bo-oor ander programme"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"As jy nie wil hê dat <xliff:g id="NAME">%s</xliff:g> hierdie kenmerk gebruik nie, tik om instellings oop te maak en skakel dit af."</string>
index 475167e..bbcc81d 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ቋንቋ እና አቀማመጥን ለመምረጥ መታ ያድርጉ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> በሌሎች መተግበሪያዎች ላይ እያሳየ ነው"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> በሌሎች መተግበሪያዎች ላይ እያሳየ ነው"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ይህን ባህሪ እንዲጠቀም ካልፈለጉ ቅንብሮችን ለመክፈት መታ ያድርጉና ያጥፉት።"</string>
index 3c42334..ae35122 100644 (file)
     <string name="relationTypeFriend" msgid="7313106762483391262">"صديق"</string>
     <string name="relationTypeManager" msgid="6365677861610137895">"مدير"</string>
     <string name="relationTypeMother" msgid="4578571352962758304">"أم"</string>
-    <string name="relationTypeParent" msgid="4755635567562925226">"الأبوان"</string>
+    <string name="relationTypeParent" msgid="4755635567562925226">"الوالدان"</string>
     <string name="relationTypePartner" msgid="7266490285120262781">"شريك"</string>
     <string name="relationTypeReferredBy" msgid="101573059844135524">"جهة الإحالة"</string>
     <string name="relationTypeRelative" msgid="1799819930085610271">"قريب"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"انقر لاختيار لغة وتنسيق"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789 أ ب ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ف ق ك ل م ن ه و ي"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"جارٍ عرض <xliff:g id="NAME">%s</xliff:g> فوق تطبيقات أخرى"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"يتم عرض <xliff:g id="NAME">%s</xliff:g> فوق التطبيقات الأخرى."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"إذا كنت لا تريد أن يستخدم <xliff:g id="NAME">%s</xliff:g> هذه الميزة، فانقر لفتح الإعدادات، ثم اختر تعطيلها."</string>
index f9c699c..b70ad39 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dil və tərtibatı seçmək üçün tıklayın"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCÇDEƏFGĞHXIİJKQLMNOÖPRSŞTUÜVYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCÇDEƏFGĞHİIJKLMNOÖPQRSŞTUÜVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> digər tətbiqlər üzərindən göstərilir"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> tətbiq üzərindən göstərilir"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> adlı şəxsin bu funksiyadan istifadə etməyini istəmirsinizsə, ayarları açmaq və deaktiv etmək üçün klikləyin."</string>
index b7bdb69..06dc7e7 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste izabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplikacija"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se prikazuje preko drugih aplik."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite ovu funkciju za <xliff:g id="NAME">%s</xliff:g>, dodirnite da biste otvorili podešavanja i isključili je."</string>
index 6515803..fbeb50c 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Дакраніцеся, каб выбраць мову і раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГДЕЁЖЗІЙКЛМНОПРСТУЎФХЦЧШ\'ЫЬЭЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> паказваецца паверх іншых праграм"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> паказв. паверх іншых праграм"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Калі вы не хочаце, каб праграма <xliff:g id="NAME">%s</xliff:g> выкарыстоўвала гэту функцыю, дакраніцеся, каб адкрыць налады і адключыць гэта."</string>
index ba640b5..c54379a 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Докоснете, за да изберете език и подредба"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> се показва върху други приложения"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> се показва в/у други прилож."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ако не искате <xliff:g id="NAME">%s</xliff:g> да използва тази функция, докоснете, за да отворите настройките, и я изключете."</string>
index ec7bc7d..c3c8e46 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ভাষা এবং লেআউট নির্বাচন করুন আলতো চাপ দিন"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> অন্যান্য অ্যাপ্লিকেশানের ওপরেও প্রদর্শিত"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> অন্যান্য অ্যাপের ওপর প্রদর্শিত হচ্ছে"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> কে এই বৈশিষ্ট্যটি ব্যবহার করতে দিতে না চাইলে, ট্যাপ করে সেটিংসে যান ও বৈশিষ্ট্যটি বন্ধ করে দিন।"</string>
index 649cadd..3c1dbdb 100644 (file)
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> dana"</string>
-    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> sati"</string>
-    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> dan <xliff:g id="HOURS">%2$d</xliff:g> sat"</string>
+    <string name="durationDayHours" msgid="2713107458736744435">"<xliff:g id="DAYS">%1$d</xliff:g> d i <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
+    <string name="durationDayHour" msgid="7293789639090958917">"<xliff:g id="DAYS">%1$d</xliff:g> d i <xliff:g id="HOURS">%2$d</xliff:g> h"</string>
     <string name="durationHours" msgid="4266858287167358988">"<xliff:g id="HOURS">%1$d</xliff:g> sati"</string>
-    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> sat <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
-    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> sat <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinutes" msgid="9029176248692041549">"<xliff:g id="HOURS">%1$d</xliff:g> h i <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
+    <string name="durationHourMinute" msgid="2741677355177402539">"<xliff:g id="HOURS">%1$d</xliff:g> h i <xliff:g id="MINUTES">%2$d</xliff:g> min"</string>
     <string name="durationMinutes" msgid="3134226679883579347">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
     <string name="durationMinute" msgid="7155301744174623818">"<xliff:g id="MINUTES">%1$d</xliff:g> min"</string>
-    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
-    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min <xliff:g id="SECONDS">%2$d</xliff:g> sek"</string>
+    <string name="durationMinuteSeconds" msgid="1424656185379003751">"<xliff:g id="MINUTES">%1$d</xliff:g> min i <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
+    <string name="durationMinuteSecond" msgid="3989228718067466680">"<xliff:g id="MINUTES">%1$d</xliff:g> min i <xliff:g id="SECONDS">%2$d</xliff:g> s"</string>
     <string name="durationSeconds" msgid="8050088505238241405">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string>
     <string name="durationSecond" msgid="985669622276420331">"<xliff:g id="SECONDS">%1$d</xliff:g> sek"</string>
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez naslova&gt;"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite za odabir jezika i rasporeda"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva ostale aplikacije"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prekriva druge apl."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite da <xliff:g id="NAME">%s</xliff:g> koristi ovu funkciju, dodirnite da otvorite postavke i isključite je."</string>
index c644866..8804d48 100644 (file)
     <string name="wifi_no_internet" msgid="8451173622563841546">"La Wi-Fi no té accés a Internet"</string>
     <string name="wifi_no_internet_detailed" msgid="8083079241212301741">"Toca per veure les opcions"</string>
     <string name="network_switch_metered" msgid="4671730921726992671">"Actualment en ús: <xliff:g id="NETWORK_TYPE">%1$s</xliff:g>"</string>
-    <string name="network_switch_metered_detail" msgid="5325661434777870353">"El dispositiu utilitza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> en cas que <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tingui accés a Internet. És possible que s\'apliquin càrrecs."</string>
+    <string name="network_switch_metered_detail" msgid="5325661434777870353">"El dispositiu utilitza <xliff:g id="NEW_NETWORK">%1$s</xliff:g> en cas que <xliff:g id="PREVIOUS_NETWORK">%2$s</xliff:g> no tingui accés a Internet. És possible que s\'hi apliquin càrrecs."</string>
     <string name="network_switch_metered_toast" msgid="5779283181685974304">"Abans es feia servir la xarxa <xliff:g id="PREVIOUS_NETWORK">%1$s</xliff:g>; ara s\'utilitza <xliff:g id="NEW_NETWORK">%2$s</xliff:g>"</string>
   <string-array name="network_switch_type_name">
     <item msgid="3979506840912951943">"dades mòbils"</item>
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca per seleccionar l\'idioma i el disseny"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"S\'està superposant <xliff:g id="NAME">%s</xliff:g> a altres aplicacions"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> s\'està superposant a altres apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no vols que <xliff:g id="NAME">%s</xliff:g> utilitzi aquesta funció, toca per obrir la configuració i desactiva-la."</string>
index e33b3df..785e32f 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozvržení"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCČDĎEÉĚFGHCHIÍJKLMNŇOÓPQRŘSŠTŤUÚVWXYÝZŽ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikace <xliff:g id="NAME">%s</xliff:g> se zobrazuje přes ostatní aplikace"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se zobrazuje přes ostatní aplikace"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Pokud nechcete, aby aplikace <xliff:g id="NAME">%s</xliff:g> tuto funkci používala, klepnutím otevřete nastavení a funkci vypněte."</string>
index cdb8a2b..f9bfc51 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryk for at vælge sprog og layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> vises over andre apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> vises over andre apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Hvis du ikke ønsker, at <xliff:g id="NAME">%s</xliff:g> skal benytte denne funktion, kan du åbne indstillingerne og deaktivere den."</string>
index 58f3204..d90f6f3 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Zum Auswählen von Sprache und Layout tippen"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> wird über anderen Apps angezeigt"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> wird über anderen Apps angezeigt"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Wenn du nicht möchtest, dass <xliff:g id="NAME">%s</xliff:g> diese Funktion verwendet, tippe, um die Einstellungen zu öffnen und die Funktion zu deaktivieren."</string>
index 780c69d..ff86202 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Πατήστε για να επιλέξετε γλώσσα και διάταξη"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> προβάλλεται πάνω από άλλες εφαρμογές"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"Η εφαρμογή <xliff:g id="NAME">%s</xliff:g> επικαλύπτει άλλες"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Εάν δεν θέλετε να χρησιμοποιείται αυτή η λειτουργία από την εφαρμογή <xliff:g id="NAME">%s</xliff:g>, πατήστε για να ανοίξετε τις ρυθμίσεις και απενεργοποιήστε την."</string>
index 2d823ea..5b03ddb 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> displaying over other apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> is displaying over other apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"If you don’t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
index 2d823ea..5b03ddb 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> displaying over other apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> is displaying over other apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"If you don’t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
index 2d823ea..5b03ddb 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tap to select language and layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> displaying over other apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> is displaying over other apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"If you don’t want <xliff:g id="NAME">%s</xliff:g> to use this feature, tap to open settings and turn it off."</string>
index 45584b5..d85c4b7 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Presiona para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> use esta función, presiona para abrir la configuración y desactivarla."</string>
index 926ee47..a989f59 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar el idioma y el diseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras aplicaciones"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se muestra sobre otras apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Si no quieres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca la notificación para abrir los ajustes y desactivarla."</string>
index 7e690be..7d58cd1 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Puudutage keele ja paigutuse valimiseks"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Rakendus <xliff:g id="NAME">%s</xliff:g> kuvatakse teiste rakenduste peal"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> kuvat. teiste rakenduste peal"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Kui te ei soovi, et rakendus <xliff:g id="NAME">%s</xliff:g> seda funktsiooni kasutaks, puudutage seadete avamiseks ja lülitage see välja."</string>
index 1407479..05f6dde 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Hizkuntza eta diseinua hautatzeko, sakatu hau"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> aplikazioen gainean agertzea"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"Besteen gainean agertzen da <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ez baduzu nahi <xliff:g id="NAME">%s</xliff:g> zerbitzuak eginbide hori erabiltzea, sakatu hau ezarpenak ireki eta aukera desaktibatzeko."</string>
index 8b894ee..0b1f62f 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"برای انتخاب زبان و چیدمان ضربه بزنید"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> روی برنامه‌های دیگر نشان داده می‌شود"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> روی برنامه‌های دیگر نشان داده می‌شود"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"اگر نمی‌خواهید <xliff:g id="NAME">%s</xliff:g> از این قابلیت استفاده کند، با ضربه زدن، تنظیمات را باز کنید و قابلیت را خاموش کنید."</string>
index af1a061..d0270c7 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Valitse kieli ja asettelu koskettamalla."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> näkyy muiden sovellusten päällä"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> näkyy sovellusten päällä"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jos et halua, että <xliff:g id="NAME">%s</xliff:g> voi käyttää tätä ominaisuutta, avaa asetukset napauttamalla ja poista se käytöstä."</string>
index ba2c01e..dcb8f53 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Touchez pour sélectionner la langue et la configuration du clavier"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> affiche du contenu par-dessus d\'autres applications"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> aff. contenu par-dessus applis"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Si vous ne voulez pas que <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalités, touchez l\'écran pour ouvrir les paramètres, puis désactivez-la."</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"Écouteur de réalité virtuelle"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
     <string name="notification_ranker_binding_label" msgid="774540592299064747">"Service de classement des notifications"</string>
-    <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
-    <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
+    <string name="vpn_title" msgid="19615213552042827">"RPV activé"</string>
+    <string name="vpn_title_long" msgid="6400714798049252294">"RPV activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="1610714069627824309">"Appuyez ici pour gérer le réseau."</string>
     <string name="vpn_text_long" msgid="4907843483284977618">"Connecté à <xliff:g id="SESSION">%s</xliff:g>. Appuyez ici pour gérer le réseau."</string>
-    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"VPN permanent en cours de connexion…"</string>
-    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"VPN permanent connecté"</string>
+    <string name="vpn_lockdown_connecting" msgid="6443438964440960745">"RPV permanent en cours de connexion…"</string>
+    <string name="vpn_lockdown_connected" msgid="8202679674819213931">"RPV permanent connecté"</string>
     <string name="vpn_lockdown_disconnected" msgid="4532298952570796327">"RPV permanent déconnecté"</string>
-    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du VPN permanent"</string>
+    <string name="vpn_lockdown_error" msgid="6009249814034708175">"Erreur du RPV permanent"</string>
     <string name="vpn_lockdown_config" msgid="5099330695245008680">"Touchez pour configurer"</string>
     <string name="upload_file" msgid="2897957172366730416">"Choisir un fichier"</string>
     <string name="no_file_chosen" msgid="6363648562170759465">"Aucun fichier sélectionné"</string>
index 12c6866..ccaed18 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Appuyer pour sélectionner la langue et la disposition"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> est affichée sur les autres applications"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> s\'affiche sur autres applis"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Si vous ne voulez pas que l\'application <xliff:g id="NAME">%s</xliff:g> utilise cette fonctionnalité, appuyez ici pour ouvrir les paramètres et la désactiver."</string>
index 68998c3..16c9943 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toca para seleccionar o idioma e o deseño"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNÑOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Mostrando <xliff:g id="NAME">%s</xliff:g> sobre outras aplicacións"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> móstrase sobre outras aplicacións"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non queres que <xliff:g id="NAME">%s</xliff:g> utilice esta función, toca para abrir a configuración e desactívaa."</string>
index 7cae6b6..3fcbc97 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ભાષા અને લેઆઉટ પસંદ કરવા માટે ટૅપ કરો"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનોની ઉપર પ્રદર્શિત થઈ રહ્યું છે"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> અન્ય ઍપ્લિકેશનો પર દેખાઈ છે"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"જો તમે નથી ઇચ્છતા કે <xliff:g id="NAME">%s</xliff:g> આ સુવિધાનો ઉપયોગ કરે, તો સેટિંગ્સ ખોલવા માટે ટૅપ કરો અને તેને બંધ કરો."</string>
index 224710d..d8cab55 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा और लेआउट चुनने के लिए टैप करें"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> अन्य ऐप्लिकेशन के ऊपर दिखाई दे रहा है"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य ऐप पर दिखाई दे रहा है"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"अगर आप नहीं चाहते कि <xliff:g id="NAME">%s</xliff:g> इस सुविधा का उपयोग करे, तो सेटिंग खोलने और उसे बंद करने के लिए टैप करें."</string>
index 61d1862..657456c 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dodirnite da biste odabrali jezik i raspored"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Aplikacija <xliff:g id="NAME">%s</xliff:g> prikazuje se preko drugih aplikacija"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"Apl. <xliff:g id="NAME">%s</xliff:g> zakriva druge aplikacije"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ako ne želite da aplikacija <xliff:g id="NAME">%s</xliff:g> upotrebljava tu značajku, dodirnite da biste otvorili postavke i isključili je."</string>
index e5105b8..0e05296 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Koppintson a nyelv és a billentyűzetkiosztás kiválasztásához"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"A(z) <xliff:g id="NAME">%s</xliff:g> a többi alkalmazás felett jelenik meg"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> – a többi alkalmazás felett"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ha nem szeretné, hogy a(z) <xliff:g id="NAME">%s</xliff:g> használja ezt a funkciót, koppintson a beállítások megnyitásához, és kapcsolja ki."</string>
index 215d83a..22dbe67 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Հպեք՝ լեզուն և դասավորությունն ընտրելու համար"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ԱԲԳԴԵԶԷԸԹԺԻԼԽԾԿՀՁՂՃՄՅՆՇՈՉՊՋՌՍՎՏՐՑՈՒՓՔԵւՕՖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> հավելվածը ցուցադրվում է այլ հավելվածների վերևում"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Եթե չեք ցանկանում, որ <xliff:g id="NAME">%s</xliff:g>-ն օգտագործի այս գործառույթը, հպեք՝ կարգավորումները բացելու և այն անջատելու համար։"</string>
index c9a8942..3c20118 100644 (file)
     <string name="sim_done_button" msgid="827949989369963775">"Selesai"</string>
     <string name="sim_added_title" msgid="3719670512889674693">"Kartu SIM ditambahkan"</string>
     <string name="sim_added_message" msgid="6599945301141050216">"Mulai ulang perangkat Anda untuk mengakses jaringan selular."</string>
-    <string name="sim_restart_button" msgid="4722407842815232347">"Mulai Ulang"</string>
+    <string name="sim_restart_button" msgid="4722407842815232347">"Nyalakan Ulang"</string>
     <string name="carrier_app_dialog_message" msgid="7066156088266319533">"Agar SIM baru bekerja dengan baik, Anda harus memasang dan membuka aplikasi dari operator."</string>
     <string name="carrier_app_dialog_button" msgid="7900235513678617329">"DAPATKAN APLIKASI"</string>
     <string name="carrier_app_dialog_not_now" msgid="6361378684292268027">"LAIN KALI"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketuk untuk memilih bahasa dan tata letak"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ditampilkan di atas aplikasi lain"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jika Anda tidak ingin <xliff:g id="NAME">%s</xliff:g> menggunakan fitur ini, tap untuk membuka setelan dan menonaktifkannya."</string>
index 9e8e022..38bc24b 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ýttu til að velja tungumál og útlit"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AÁBCDÐEÉFGHIÍJKLMNOÓPQRSTUÚVWXYÝZÞÆÖ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> birtist yfir öðrum forritum"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> birtist yfir öðrum forritum"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ef þú vilt ekki að <xliff:g id="NAME">%s</xliff:g> noti þennan eiginleika skaltu ýta til að opna stillingarnar og slökkva á því."</string>
index 975bb57..be2dd22 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tocca per selezionare la lingua e il layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"App <xliff:g id="NAME">%s</xliff:g> visualizzata sopra altre app"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"App <xliff:g id="NAME">%s</xliff:g> mostrata sopra altre app"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se non desideri che l\'app <xliff:g id="NAME">%s</xliff:g> utilizzi questa funzione, tocca per aprire le impostazioni e disattivarla."</string>
index 6eafaaf..93d3df9 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"הקש כדי לבחור שפה ופריסה"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"תצוגה של <xliff:g id="NAME">%s</xliff:g> מעל אפליקציות אחרות"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> מוצגת מעל אפליקציות אחרות"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"אם אינך רוצה ש-<xliff:g id="NAME">%s</xliff:g> תשתמש בתכונה הזו, הקש כדי לפתוח את ההגדרות ולכבות אותה."</string>
index 2a3d9e1..d4745df 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"タップして言語とレイアウトを選択してください"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>を他のアプリの上に重ねて表示"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>が他のアプリの上に表示されています"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g>でこの機能を使用しない場合は、タップして設定を開いて OFF にしてください。"</string>
index 1c3f970..aa92609 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"შეეხეთ ენისა და განლაგების ასარჩევად"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ნაჩვენებია სხვა აპების ინტერფეისის გადაფარვით"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ნაჩვენებია სხვა აპების ინტერფეისის გადაფარვით"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"თუ არ გსურთ <xliff:g id="NAME">%s</xliff:g>-ის მიერ ამ ფუნქციის გამოყენება, შეეხეთ პარამეტრების გასახსნელად და გამორთეთ."</string>
index 4e11c56..50f136f 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тіл мен пернетақта схемасын таңдау үшін түртіңіз"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> басқа қолданбалардың үстінен шықты"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> басқа қолданбалардың үстінен көрсетіледі"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> деген пайдаланушының бұл функцияны пайдалануына жол бермеу үшін параметрлерді түртіп ашыңыз да, оларды өшіріңіз."</string>
index 6994d7f..9022e3d 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ប៉ះដើម្បីជ្រើសភាសា និងប្លង់"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> កំពុង​បង្ហាញពីលើ​កម្មវិធី​ផ្សេង​ទៀត"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> កំពុង​បង្ហាញ​ពីលើ​កម្មវិធី​ផ្សេង​ទៀត"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"ប្រសិនបើ​អ្នក​មិន​ចង់​ឲ្យ <xliff:g id="NAME">%s</xliff:g> ប្រើ​មុខងារ​នេះ​ទេ សូមចុច​ដើម្បី​បើក​ការកំណត់ រួច​បិទ​វា។"</string>
index b3f42d1..6f0ed95 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ಭಾಷೆ ಮತ್ತು ವಿನ್ಯಾಸವನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ಇತರ ಅಪ್ಲಿಕೇಶನ್‌ಗಳ ಮೂಲಕ ಪ್ರದರ್ಶಿಸುತ್ತಿದೆ"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ಇತರವುಗಳ ಮೇಲೆ ಪ್ರದರ್ಶಿಸುತ್ತಿದೆ"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ಈ ವೈಶಿಷ್ಟ್ಯ ಬಳಸುವುದನ್ನು ನೀವು ಬಯಸದಿದ್ದರೆ, ಸೆಟ್ಟಿಂಗ್‌ಗಳನ್ನು ತೆರೆದು, ಅದನ್ನು ಆಫ್ ಮಾಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ."</string>
index e7f9a7f..5cf961b 100644 (file)
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"사진 및 동영상 촬영"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"전화"</string>
     <string name="permgroupdesc_phone" msgid="6234224354060641055">"전화 걸기 및 관리"</string>
-    <string name="permgrouplab_sensors" msgid="416037179223226722">"ì\8b ì²´ 센서"</string>
+    <string name="permgrouplab_sensors" msgid="416037179223226722">"ì\9d¸ì²´ ê°\90ì§\80 센서"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"생체 신호에 관한 센서 데이터에 액세스"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"창 콘텐츠 가져오기"</string>
     <string name="capability_desc_canRetrieveWindowContent" msgid="3772225008605310672">"상호작용 중인 창의 콘텐츠를 검사합니다."</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"앱에서 수신 및 발신 통화 데이터를 포함하여 태블릿의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 지우거나 수정할 수 있습니다."</string>
     <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"앱에서 수신 및 발신 통화 데이터를 포함하여 TV의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 삭제하거나 수정할 수도 있습니다."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"앱에서 수신 및 발신 통화 데이터를 포함하여 휴대전화의 통화 기록을 수정할 수 있도록 허용합니다. 이 경우 악성 앱이 통화 기록을 지우거나 수정할 수 있습니다."</string>
-    <string name="permlab_bodySensors" msgid="4683341291818520277">"ì\8b ì²´ 센서(예: 심박수 모니터)에 액세스"</string>
+    <string name="permlab_bodySensors" msgid="4683341291818520277">"ì\9d¸ì²´ ê°\90ì§\80 센서(예: 심박수 모니터)에 액세스"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"앱이 심박수와 같은 신체 상태를 확인하는 센서의 데이터에 접근하도록 허용합니다."</string>
     <string name="permlab_readCalendar" msgid="6716116972752441641">"캘린더 일정 및 세부정보 읽기"</string>
     <string name="permdesc_readCalendar" product="tablet" msgid="4993979255403945892">"이 앱은 태블릿에 저장된 모든 캘린더 일정을 읽고 캘린더 데이터를 공유하거나 저장할 수 있습니다."</string>
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"탭하여 언어와 레이아웃을 선택하세요."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>이(가) 다른 앱 위에 표시됨"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>이(가) 다른 앱 위에 표시됨"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g>에서 이 기능이 사용되는 것을 원하지 않는 경우 탭하여 설정을 열고 기능을 사용 중지하세요."</string>
index d627e61..460306c 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Тил жана калып тандоо үчүн таптап коюңуз"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> колдонмосун башка терезелердин үстүнөн көрсөтүү"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>: башка колдонмолордун үстүнөн"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Эгер <xliff:g id="NAME">%s</xliff:g> колдонмосу бул функцияны пайдаланбасын десеңиз, жөндөөлөрдү ачып туруп, аны өчүрүп коюңуз."</string>
index 5dc58f6..9bbb0a9 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ແຕະເພື່ອເລືອກພາສາ ແລະ ໂຄງແປ້ນພິມ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ກຳລັງສະແດງຜົນຢູເທິງແອັບອື່ນຢູ່"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ກຳລັງສະແດງຜົນບັງແອັບອື່ນຢູ່"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"ຫາກທ່ານບໍ່ຕ້ອງການ <xliff:g id="NAME">%s</xliff:g> ໃຫ້ໃຊ້ຄຸນສົມບັດນີ້, ໃຫ້ແຕະເພື່ອເປີດການຕັ້ງຄ່າ ແລ້ວປິດມັນໄວ້."</string>
index 14de0a2..8c6175e 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Palieskite, kad pasirinktumėte kalbą ir išdėstymą"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĄBCČDEĘĖFGHIĮYJKLMNOPRSŠTUŲŪVZŽ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> rodomi virš kitų programų"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> rodomi virš kitų programų."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jei nenorite, kad <xliff:g id="NAME">%s</xliff:g> naudotų šią funkciją, palietę atidarykite nustatymus ir išjunkite ją."</string>
index b191747..d090739 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Pieskarieties, lai atlasītu valodu un izkārtojumu"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789AĀBCČDEĒFGĢHIĪJKĶLĻMNŅOPRSŠTUŪVZŽ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Lietotne <xliff:g id="NAME">%s</xliff:g> tiek rādīta pāri citām lietotnēm"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"Lietotne <xliff:g id="NAME">%s</xliff:g> pāri citām lietotnēm"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ja nevēlaties lietotnē <xliff:g id="NAME">%s</xliff:g> izmantot šo funkciju, pieskarieties, lai atvērtu iestatījumus un to izslēgtu."</string>
index 3049488..a328c49 100755 (executable)
@@ -23,6 +23,7 @@
     <string-array translatable="false" name="config_cdma_home_system">
         <item>64</item>
         <item>65</item>
+        <item>66</item>
         <item>76</item>
         <item>77</item>
         <item>78</item>
index 6f85081..04f182e 100755 (executable)
@@ -23,6 +23,7 @@
     <string-array translatable="false" name="config_cdma_home_system">
         <item>64</item>
         <item>65</item>
+        <item>66</item>
         <item>76</item>
         <item>77</item>
         <item>78</item>
index 2e115fc..f48345b 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Допрете за избирање јазик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> се прикажува врз други апликации"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> се прикажува врз апликации"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ако не сакате <xliff:g id="NAME">%s</xliff:g> да ја користи функцијава, допрете за да ги отворите поставките и исклучете ја."</string>
index 8bc3ff8..cd8e8c9 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ഭാഷയും ലേഔട്ടും തിരഞ്ഞെടുക്കുന്നതിന് ടാപ്പുചെയ്യുക"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രദർശിപ്പിക്കുന്നു"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> മറ്റ് ആപ്പുകൾക്ക് മുകളിൽ പ്രദർശിപ്പിക്കുന്നു"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ഈ ഫീച്ചർ ഉപയോഗിക്കുന്നതിൽ നിങ്ങൾക്ക് താൽപ്പര്യമില്ലെങ്കിൽ, ടാപ്പുചെയ്‌ത് ക്രമീകരണം തുറന്ന് അത് ഓഫാക്കുക."</string>
index 8309d77..81f5eaa 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Хэл болон бүдүүвчийг сонгохын тулд дарна уу"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Бусад апп дээгүүр <xliff:g id="NAME">%s</xliff:g>-г харуулж байна"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>-г бусад апп дээр харуулж байна"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Та <xliff:g id="NAME">%s</xliff:g>-д энэ онцлогийг ашиглахыг хүсэхгүй байгаа бол тохиргоог нээгээд, унтраана уу."</string>
index c0bc82c..cbeaacd 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा आणि लेआउट निवडण्यासाठी टॅप करा"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> इतर अॅप्सवर प्रदर्शित करीत आहे"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्‍य अॅप्सवर प्रदर्शित करीत आहे"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ने हे वैशिष्ट्य वापरू नये असे आपण इच्छित असल्यास, सेटिंग्ज उघडण्यासाठी टॅप करा आणि ते बंद करा."</string>
index 8c4bb4c..2a3c046 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Ketik untuk memilih bahasa dan susun atur"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> dipaparkan di atas apl lain"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> dipaparkan di atas apl lain"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jika anda tidak mahu <xliff:g id="NAME">%s</xliff:g> menggunakan ciri ini, ketik untuk membuka tetapan dan matikannya."</string>
index f5a1429..993c5cf 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ဘာသာစကားနှင့် အသွင်အပြင်ရွေးချယ်ရန် တို့ပါ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> သည် အခြားအက်ပ်များအပေါ်တွင် ပြပါသည်"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ကို အခြားအက်ပ်များပေါ်တွင် မြင်နေရပါသည်။"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ကို ဤဝန်ဆောင်မှုအား အသုံးမပြုစေလိုလျှင် ဆက်တင်ကို တို့၍ ဖွင့်ပြီး ၎င်းကို ပိတ်လိုက်ပါ။"</string>
index 5972329..b88ff35 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trykk for å velge språk og layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZÆØÅ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> vises over andre apper"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> vises over andre apper"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Hvis du ikke vil at <xliff:g id="NAME">%s</xliff:g> skal bruke denne funksjonen, kan du trykke for å åpne innstillingene og slå den av."</string>
index 7283936..7734681 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"भाषा र लेआउट चयन गर्न ट्याप गर्नुहोस्"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> अन्य अनुप्रयोगहरूमा देखिँदैछ"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"तपाईं <xliff:g id="NAME">%s</xliff:g> ले यो विशेषता प्रयोग नगरेको चाहनुहुन्न भने सेटिङहरू खोली यसलाई निष्क्रिय पार्न ट्याप गर्नुहोस्।"</string>
index 09cfa70..b174572 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tik om een taal en indeling te selecteren"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven over andere apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> wordt weergegeven over apps"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Als je niet wilt dat <xliff:g id="NAME">%s</xliff:g> deze functie gebruikt, tik je om de instellingen te openen en schakel je de functie uit."</string>
index c89224d..4160344 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"ਭਾਸ਼ਾ ਅਤੇ ਖਾਕਾ ਚੁਣਨ ਲਈ ਟੈਪ ਕਰੋ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ਐਪ ਹੋਰ ਐਪਾਂ ਦੇ ਉੱਤੇ ਹੈ"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ਐਪ ਹੋਰਾਂ ਐਪਾਂ ਦੇ ਉੱਤੇ ਹੈ।"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"ਜੇ ਤੁਸੀਂ ਨਹੀਂ ਚਾਹੁੰਦੇ ਕਿ <xliff:g id="NAME">%s</xliff:g> ਐਪ ਇਸ ਵਿਸ਼ੇਸ਼ਤਾ ਦੀ ਵਰਤੋਂ ਕਰੇ, ਤਾਂ ਸੈਟਿੰਗਾਂ ਖੋਲ੍ਹਣ ਲਈ ਟੈਪ ਕਰੋ ਅਤੇ ਇਸਨੂੰ ਬੰਦ ਕਰੋ।"</string>
index cac8e58..209bd21 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Kliknij, by wybrać język i układ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AĄBCĆDEĘFGHIJKLŁMNŃOÓPQRSŚTUVWXYZŹŻ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Wyświetlanie aplikacji <xliff:g id="NAME">%s</xliff:g> nad innymi"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"Aplikacja <xliff:g id="NAME">%s</xliff:g> jest nad innymi"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Jeśli nie chcesz, by aplikacja <xliff:g id="NAME">%s</xliff:g> korzystała z tej funkcji, otwórz ustawienia i ją wyłącz."</string>
index fe6b766..076e728 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se você não deseja que o <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string>
index 4c04879..15e1e3c 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o esquema"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"A aplicação <xliff:g id="NAME">%s</xliff:g> sobrepõe-se a outras aplicações"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"O <xliff:g id="NAME">%s</xliff:g> sobrepõe-se a outras aplic."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se não pretende que a aplicação <xliff:g id="NAME">%s</xliff:g> utilize esta funcionalidade, toque para abrir as definições e desative-a."</string>
index fe6b766..076e728 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Toque para selecionar o idioma e o layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> exibido sobre outros apps."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Se você não deseja que o <xliff:g id="NAME">%s</xliff:g> use este recurso, toque para abrir as configurações e desativá-lo."</string>
index 835c9ac..cefbccc 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Atingeți pentru a selecta limba și aspectul"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> se afișează peste alte aplicații"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> se afișează peste aplicații"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Dacă nu doriți ca <xliff:g id="NAME">%s</xliff:g> să utilizeze această funcție, atingeți pentru a deschide setările și dezactivați-o."</string>
index 69fe42f..d6dd1ee 100644 (file)
     <string name="reboot_to_update_prepare" msgid="6305853831955310890">"Подготовка обновлений…"</string>
     <string name="reboot_to_update_package" msgid="3871302324500927291">"Обработка обновлений…"</string>
     <string name="reboot_to_update_reboot" msgid="6428441000951565185">"Перезагрузка…"</string>
-    <string name="reboot_to_reset_title" msgid="4142355915340627490">"Сбросить все данные"</string>
+    <string name="reboot_to_reset_title" msgid="4142355915340627490">"Сброс к заводским настройкам"</string>
     <string name="reboot_to_reset_message" msgid="2432077491101416345">"Перезагрузка…"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Выключение..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Планшетный ПК будет отключен."</string>
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Нажмите, чтобы выбрать язык и раскладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>: поверх других приложений"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>: поверх других приложений"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Чтобы отключить эту функцию для приложения <xliff:g id="NAME">%s</xliff:g>, перейдите в настройки."</string>
index 373fe07..adcfad9 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"භාෂාව හා පිරිසැලසුම තේරීමට තට්ටු කරන්න"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> සංදර්ශනය කරමින්"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"අනෙක් යෙදුම්වලට උඩින් <xliff:g id="NAME">%s</xliff:g> දිස් වේ"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"ඔබට <xliff:g id="NAME">%s</xliff:g> මෙම විශේෂාංගය භාවිත කිරීමට අවශ්‍ය නැති නම්, සැකසීම් විවෘත කිරීමට තට්ටු කර එය ක්‍රියාවිරහිත කරන්න."</string>
index 4352a36..c413155 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Klepnutím vyberte jazyk a rozloženie"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" AÁÄBCČDĎDZDŽEÉFGHCHIÍJKLĽMNŇOÓÔPRŔSŠTŤUÚVWXYÝZŽ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> sa zobrazuje cez iné aplikácie"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> sa zobrazuje cez iné aplikácie"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ak nechcete, aby aplikácia <xliff:g id="NAME">%s</xliff:g> používala túto funkciu, klepnutím otvorte nastavenia a vypnite ju."</string>
index c6f4404..fb24d43 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dotaknite se, če želite izbrati jezik in postavitev."</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> prekriva druge aplikacije"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> prekriva druge aplikacije"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Če ne želite, da aplikacija <xliff:g id="NAME">%s</xliff:g> uporablja to funkcijo, se dotaknite, da odprete nastavitve, in funkcijo izklopite."</string>
index 70a3efb..47d1d0c 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Trokit për të zgjedhur gjuhën dhe strukturën"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> afishohet mbi aplikacionet e tjera"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> shfaqet mbi apl. e tjera"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Nëse nuk dëshiron që <xliff:g id="NAME">%s</xliff:g> ta përdorë këtë funksion, trokit për të hapur cilësimet dhe për ta çaktivizuar."</string>
index f46505b..031291d 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Додирните да бисте изабрали језик и распоред"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Апликација <xliff:g id="NAME">%s</xliff:g> се приказује преко других апликација"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> се приказује преко других аплик."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ако не желите ову функцију за <xliff:g id="NAME">%s</xliff:g>, додирните да бисте отворили подешавања и искључили је."</string>
index a3fb085..ffd4f11 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Tryck om du vill välja språk och layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> visas över andra appar"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> visas över andra appar"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Om du inte vill att den här funktionen används för <xliff:g id="NAME">%s</xliff:g> öppnar du inställningarna genom att trycka. Sedan inaktiverar du funktionen."</string>
index ce4a469..910949c 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Gonga ili uchague lugha na muundo"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> inachomoza juu ya programu zingine"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> inachomoza juu ya programu zingine."</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Ikiwa hutaki <xliff:g id="NAME">%s</xliff:g> kutumia kipengele hiki, gonga ili ufungue mipangilio na ukizime."</string>
index f45789b..41cf95b 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"மொழியையும் தளவமைப்பையும் தேர்ந்தெடுக்க, தட்டவும்"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> பிற பயன்பாடுகளின் மீது தோன்றுகிறது"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> பிற ஆப்ஸின் மீது தோன்றுகிறது"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> இந்த அம்சத்தைப் பயன்படுத்த வேண்டாம் என நினைத்தால், அமைப்புகளைத் திறந்து அதை முடக்க, தட்டவும்."</string>
index 68065b9..6d43b2b 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"భాష మరియు లేఅవుట్‌ను ఎంచుకోవడానికి నొక్కండి"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ఇతర అనువర్తనాలలో చూపబడుతోంది"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ఇతర అనువర్తనాలలో చూపబడుతోంది"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ఈ లక్షణాన్ని ఉపయోగించకూడదు అని మీరు అనుకుంటే, సెట్టింగ్‌లను తెరవడానికి నొక్కి, దీన్ని ఆఫ్ చేయండి."</string>
index 51d932d..6b2c4c6 100644 (file)
     <string name="cfTemplateForwardedTime" msgid="9206251736527085256">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: <xliff:g id="DIALING_NUMBER">{1}</xliff:g> หลังผ่านไป <xliff:g id="TIME_DELAY">{2}</xliff:g> วินาที"</string>
     <string name="cfTemplateRegistered" msgid="5073237827620166285">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
     <string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>: ไม่ได้โอนสาย"</string>
-    <string name="fcComplete" msgid="3118848230966886575">"รหัสà¸\84ุà¸\93ลัà¸\81ษà¸\93ะเสร็จสมบูรณ์"</string>
-    <string name="fcError" msgid="3327560126588500777">"à¸\9eà¸\9aà¸\9bัà¸\8dหาà¹\83à¸\99à¸\81ารà¹\80à¸\8aืà¹\88อมà¸\95à¹\88อหรือรหัสà¸\84ุà¸\93ลัà¸\81ษà¸\93ะไม่ถูกต้อง"</string>
+    <string name="fcComplete" msgid="3118848230966886575">"รหัสà¸\9fีà¹\80à¸\88อรà¹\8cเสร็จสมบูรณ์"</string>
+    <string name="fcError" msgid="3327560126588500777">"à¸\9eà¸\9aà¸\9bัà¸\8dหาà¹\83à¸\99à¸\81ารà¹\80à¸\8aืà¹\88อมà¸\95à¹\88อหรือรหัสà¸\9fีà¹\80à¸\88อรà¹\8cไม่ถูกต้อง"</string>
     <string name="httpErrorOk" msgid="1191919378083472204">"ตกลง"</string>
     <string name="httpError" msgid="7956392511146698522">"เกิดข้อผิดพลาดของเครือข่าย"</string>
     <string name="httpErrorLookup" msgid="4711687456111963163">"ไม่พบ URL"</string>
     <string name="permlab_accessImsCallService" msgid="3574943847181793918">"เข้าถึงบริการโทร IMS"</string>
     <string name="permdesc_accessImsCallService" msgid="8992884015198298775">"อนุญาตให้แอปใช้บริการ IMS เพื่อโทรออกโดยคุณไม่ต้องดำเนินการใดๆ เลย"</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"อ่านสถานะและข้อมูลระบุตัวตนของโทรศัพท์"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"อà¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¹\80à¸\82à¹\89าà¸\96ึà¸\87à¸\84ุà¸\93ลัà¸\81ษà¸\93ะโทรศัพท์ของอุปกรณ์ การอนุญาตนี้ทำให้แอปพลิเคชันสามารถตรวจสอบหมายเลขโทรศัพท์และรหัสอุปกรณ์ ตรวจสอบว่ามีการโทรที่ทำงานอยู่หรือไม่ และตรวจสอบหมายเลขระยะไกลที่เชื่อมต่อด้วยการโทร"</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"อà¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¹\80à¸\82à¹\89าà¸\96ึà¸\87à¸\9fีà¹\80à¸\88อรà¹\8cโทรศัพท์ของอุปกรณ์ การอนุญาตนี้ทำให้แอปพลิเคชันสามารถตรวจสอบหมายเลขโทรศัพท์และรหัสอุปกรณ์ ตรวจสอบว่ามีการโทรที่ทำงานอยู่หรือไม่ และตรวจสอบหมายเลขระยะไกลที่เชื่อมต่อด้วยการโทร"</string>
     <string name="permlab_manageOwnCalls" msgid="1503034913274622244">"กำหนดเส้นทางการโทรผ่านระบบ"</string>
     <string name="permdesc_manageOwnCalls" msgid="6552974537554717418">"อนุญาตให้แอปกำหนดเส้นทางการโทรของแอปผ่านระบบเพื่อปรับปรุงประสบการณ์ในการโทร"</string>
     <string name="permlab_readPhoneNumbers" msgid="6108163940932852440">"อ่านหมายเลขโทรศัพท์"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"ข้อมูลของแอปพลิเคชันที่จัดเก็บต้องมีการเข้ารหัส"</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"ปิดใช้งานกล้องถ่ายรูป"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"ป้องกันการใช้กล้องถ่ายรูปของอุปกรณ์ทั้งหมด"</string>
-    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"à¸\9bิà¸\94à¸\84ุà¸\93ลัà¸\81ษà¸\93ะล็อกหน้าจอบางอย่าง"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"à¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¸\81ารà¹\83à¸\8aà¹\89à¸\84ุà¸\93ลัà¸\81ษà¸\93ะบางอย่างของการล็อกหน้าจอ"</string>
+    <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"à¸\9bิà¸\94à¸\9fีà¹\80à¸\88อรà¹\8cล็อกหน้าจอบางอย่าง"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"à¸\9bà¹\89อà¸\87à¸\81ัà¸\99à¸\81ารà¹\83à¸\8aà¹\89à¸\9fีà¹\80à¸\88อรà¹\8cบางอย่างของการล็อกหน้าจอ"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"บ้าน"</item>
     <item msgid="869923650527136615">"มือถือ"</item>
     <string name="lockscreen_pattern_correct" msgid="9039008650362261237">"ถูกต้อง!"</string>
     <string name="lockscreen_pattern_wrong" msgid="4317955014948108794">"ลองอีกครั้ง"</string>
     <string name="lockscreen_password_wrong" msgid="5737815393253165301">"ลองอีกครั้ง"</string>
-    <string name="lockscreen_storage_locked" msgid="9167551160010625200">"à¸\9bลà¸\94ลà¹\87อà¸\81à¸\84ุà¸\93ลัà¸\81ษà¸\93ะและข้อมูลทั้งหมด"</string>
+    <string name="lockscreen_storage_locked" msgid="9167551160010625200">"à¸\9bลà¸\94ลà¹\87อà¸\81à¸\9fีà¹\80à¸\88อรà¹\8cและข้อมูลทั้งหมด"</string>
     <string name="faceunlock_multiple_failures" msgid="754137583022792429">"มีความพยายามที่จะใช้ Face Unlock เกินขีดจำกัด"</string>
     <string name="lockscreen_missing_sim_message_short" msgid="5099439277819215399">"ไม่มีซิมการ์ด"</string>
     <string name="lockscreen_missing_sim_message" product="tablet" msgid="151659196095791474">"ไม่มีซิมการ์ดในแท็บเล็ต"</string>
     <string name="permdesc_writeHistoryBookmarks" product="tv" msgid="7007393823197766548">"อนุญาตให้แอปแก้ไขประวัติของเบราว์เซอร์หรือบุ๊กมาร์กที่เก็บไว้ในทีวี ซึ่งอาจอนุญาตให้แอปลบหรือแก้ไขข้อมูลเบราว์เซอร์ หมายเหตุ: สิทธิ์นี้ไม่สามารถใช้ได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นที่สามารถท่องเว็บได้"</string>
     <string name="permdesc_writeHistoryBookmarks" product="default" msgid="8497389531014185509">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงประวัติหรือบุ๊กมาร์กของเบราว์เซอร์ที่จัดเก็บไว้ในโทรศัพท์ ซึ่งทำให้แอปพลิเคชันสามารถลบหรือเปลี่ยนข้อมูลเบราว์เซอร์ได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับเบราว์เซอร์ของบุคคลที่สามหรือแอปพลิเคชันอื่นๆ ที่มีความสามารถในการเรียกดูบนเว็บ"</string>
     <string name="permlab_setAlarm" msgid="1379294556362091814">"ตั้งปลุก"</string>
-    <string name="permdesc_setAlarm" msgid="316392039157473848">"อà¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¸\95ัà¹\89à¸\87à¹\80วลาà¸\9bลุà¸\81à¹\83à¸\99à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¸\99าฬิà¸\81าà¸\9bลุà¸\81à¸\97ีà¹\88à¸\95ิà¸\94à¸\95ัà¹\89à¸\87 à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¸\99าฬิà¸\81าà¸\9bลุà¸\81à¸\9aาà¸\87รายà¸\81ารอาà¸\88à¹\84มà¹\88à¹\83à¸\8aà¹\89à¸\84ุà¸\93ลัà¸\81ษà¸\93ะนี้"</string>
+    <string name="permdesc_setAlarm" msgid="316392039157473848">"อà¸\99ุà¸\8dาà¸\95à¹\83หà¹\89à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¸\95ัà¹\89à¸\87à¹\80วลาà¸\9bลุà¸\81à¹\83à¸\99à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¸\99าฬิà¸\81าà¸\9bลุà¸\81à¸\97ีà¹\88à¸\95ิà¸\94à¸\95ัà¹\89à¸\87 à¹\81อà¸\9bà¸\9eลิà¹\80à¸\84à¸\8aัà¸\99à¸\99าฬิà¸\81าà¸\9bลุà¸\81à¸\9aาà¸\87รายà¸\81ารอาà¸\88à¹\84มà¹\88à¹\83à¸\8aà¹\89à¸\9fีà¹\80à¸\88อรà¹\8cนี้"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"เพิ่มข้อวามเสียง"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"อนุญาตให้แอปพลิเคชันเพิ่มข้อความลงในกล่องข้อความเสียงของคุณ"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string>
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"แตะเพื่อเลือกภาษาและรูปแบบ"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรลวศษสหฬอฮ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> แสดงทับแอปอื่นๆ"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> กำลังแสดงทับแอปอื่นๆ"</string>
-    <string name="alert_windows_notification_message" msgid="8917232109522912560">"หาà¸\81à¸\84ุà¸\93à¹\84มà¹\88à¸\95à¹\89อà¸\87à¸\81ารà¹\83หà¹\89 <xliff:g id="NAME">%s</xliff:g> à¹\83à¸\8aà¹\89à¸\84ุà¸\93ลัà¸\81ษà¸\93ะà¸\99ีà¹\89 à¹\83หà¹\89à¹\81à¸\95ะà¹\80à¸\9eืà¹\88อà¹\80à¸\9bิà¸\94à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¹\81ลà¹\89วà¸\9bิà¸\94à¸\84ุà¸\93ลัà¸\81ษà¸\93ะ"</string>
+    <string name="alert_windows_notification_message" msgid="8917232109522912560">"หาà¸\81à¸\84ุà¸\93à¹\84มà¹\88à¸\95à¹\89อà¸\87à¸\81ารà¹\83หà¹\89 <xliff:g id="NAME">%s</xliff:g> à¹\83à¸\8aà¹\89à¸\9fีà¹\80à¸\88อรà¹\8cà¸\99ีà¹\89 à¹\83หà¹\89à¹\81à¸\95ะà¹\80à¸\9eืà¹\88อà¹\80à¸\9bิà¸\94à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¹\81ลà¹\89วà¸\9bิà¸\94à¸\9fีà¹\80à¸\88อรà¹\8c"</string>
     <string name="alert_windows_notification_turn_off_action" msgid="3367294525884949878">"ปิด"</string>
     <string name="ext_media_checking_notification_title" msgid="5734005953288045806">"กำลังเตรียม <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="ext_media_checking_notification_message" msgid="4747432538578886744">"กำลังตรวจหาข้อผิดพลาด"</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"ลบ"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"นี่เป็นการเพิ่มระดับเสียงเกินระดับที่แนะนำ\n\nการฟังเสียงดังเป็นเวลานานอาจทำให้การได้ยินของคุณบกพร่องได้"</string>
     <string name="accessibility_shortcut_warning_dialog_title" msgid="8404780875025725199">"ใช้ทางลัดการเข้าถึงพิเศษไหม"</string>
-    <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"à¹\80มืà¹\88อà¸\97าà¸\87ลัà¸\94à¹\80à¸\9bิà¸\94อยูà¹\88 à¸\81ารà¸\81à¸\94à¸\9bุà¹\88มà¸\9bรัà¸\9aระà¸\94ัà¸\9aà¹\80สียà¸\87à¸\97ัà¹\89à¸\87 2 à¸\9bุà¹\88มà¹\80à¸\9bà¹\87à¸\99à¹\80วลา 3 à¸§à¸´à¸\99าà¸\97ีà¸\88ะà¹\80ริà¹\88มà¸\84ุà¸\93ลัà¸\81ษà¸\93ะà¸\81ารà¹\80à¸\82à¹\89าà¸\96ึà¸\87à¸\9eิà¹\80ศษ\n\n à¸\84ุà¸\93ลัà¸\81ษà¸\93ะà¸\81ารà¹\80à¸\82à¹\89าà¸\96ึà¸\87à¸\9eิà¹\80ศษà¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n à¸\84ุà¸\93สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99à¸\84ุà¸\93ลัà¸\81ษà¸\93ะในการตั้งค่า &gt; การเข้าถึงพิเศษ"</string>
+    <string name="accessibility_shortcut_toogle_warning" msgid="7256507885737444807">"à¹\80มืà¹\88อà¸\97าà¸\87ลัà¸\94à¹\80à¸\9bิà¸\94อยูà¹\88 à¸\81ารà¸\81à¸\94à¸\9bุà¹\88มà¸\9bรัà¸\9aระà¸\94ัà¸\9aà¹\80สียà¸\87à¸\97ัà¹\89à¸\87 2 à¸\9bุà¹\88มà¹\80à¸\9bà¹\87à¸\99à¹\80วลา 3 à¸§à¸´à¸\99าà¸\97ีà¸\88ะà¹\80ริà¹\88มà¸\9fีà¹\80à¸\88อรà¹\8cà¸\81ารà¹\80à¸\82à¹\89าà¸\96ึà¸\87à¸\9eิà¹\80ศษ\n\n à¸\9fีà¹\80à¸\88อรà¹\8cà¸\81ารà¹\80à¸\82à¹\89าà¸\96ึà¸\87à¸\9eิà¹\80ศษà¸\9bัà¸\88à¸\88ุà¸\9aัà¸\99:\n <xliff:g id="SERVICE_NAME">%1$s</xliff:g>\n\n à¸\84ุà¸\93สามารà¸\96à¹\80à¸\9bลีà¹\88ยà¸\99à¸\9fีà¹\80à¸\88อรà¹\8cในการตั้งค่า &gt; การเข้าถึงพิเศษ"</string>
     <string name="disable_accessibility_shortcut" msgid="627625354248453445">"ปิดทางลัด"</string>
     <string name="leave_accessibility_shortcut_on" msgid="7653111894438512680">"ใช้ทางลัด"</string>
     <string name="accessibility_shortcut_enabling_service" msgid="7771852911861522636">"ทางลัดการเข้าถึงเปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
     <string name="accessibility_shortcut_disabling_service" msgid="2747243438223109821">"ทางลัดการเข้าถึงปิด <xliff:g id="SERVICE_NAME">%1$s</xliff:g> แล้ว"</string>
-    <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"à¹\80ลือà¸\81à¸\84ุà¸\93ลัà¸\81ษà¸\93ะที่จะใช้เมื่อคุณแตะปุ่ม \"การเข้าถึงพิเศษ\":"</string>
-    <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"หาà¸\81à¸\95à¹\89อà¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¸\84ุà¸\93ลัà¸\81ษà¸\93ะ ให้แตะปุ่ม \"การเข้าถึงพิเศษ\" ค้างไว้"</string>
+    <string name="accessibility_button_prompt_text" msgid="4234556536456854251">"à¹\80ลือà¸\81à¸\9fีà¹\80à¸\88อรà¹\8cที่จะใช้เมื่อคุณแตะปุ่ม \"การเข้าถึงพิเศษ\":"</string>
+    <string name="accessibility_button_instructional_text" msgid="6942300463612999993">"หาà¸\81à¸\95à¹\89อà¸\87à¸\81ารà¹\80à¸\9bลีà¹\88ยà¸\99à¸\9fีà¹\80à¸\88อรà¹\8c ให้แตะปุ่ม \"การเข้าถึงพิเศษ\" ค้างไว้"</string>
     <string name="accessibility_magnification_chooser_text" msgid="1227146738764986237">"การขยาย"</string>
     <string name="user_switched" msgid="3768006783166984410">"ผู้ใช้ปัจจุบัน <xliff:g id="NAME">%1$s</xliff:g>"</string>
     <string name="user_switching_message" msgid="2871009331809089783">"กำลังเปลี่ยนเป็น <xliff:g id="NAME">%1$s</xliff:g>…"</string>
     <string name="region_picker_section_all" msgid="8966316787153001779">"ภูมิภาคทั้งหมด"</string>
     <string name="locale_search_menu" msgid="2560710726687249178">"ค้นหา"</string>
     <string name="work_mode_off_title" msgid="2615362773958585967">"เปิดโหมดงานไหม"</string>
-    <string name="work_mode_off_message" msgid="2961559609199223594">"à¸\81ารà¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\99ีà¹\89à¸\88ะà¹\80à¸\9bิà¸\94à¹\82à¸\9bรà¹\84à¸\9fลà¹\8cà¸\87าà¸\99à¸\82อà¸\87à¸\84ุà¸\93 à¸£à¸§à¸¡à¸\96ึà¸\87à¹\81อà¸\9b à¸\81ารà¸\8bิà¸\87à¸\84à¹\8cà¹\83à¸\99à¸\9eืà¹\89à¸\99หลัà¸\87 à¹\81ละà¸\84ุà¸\93ลัà¸\81ษà¸\93ะที่เกี่ยวข้อง"</string>
+    <string name="work_mode_off_message" msgid="2961559609199223594">"à¸\81ารà¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\99ีà¹\89à¸\88ะà¹\80à¸\9bิà¸\94à¹\82à¸\9bรà¹\84à¸\9fลà¹\8cà¸\87าà¸\99à¸\82อà¸\87à¸\84ุà¸\93 à¸£à¸§à¸¡à¸\96ึà¸\87à¹\81อà¸\9b à¸\81ารà¸\8bิà¸\87à¸\84à¹\8cà¹\83à¸\99à¸\9eืà¹\89à¸\99หลัà¸\87 à¹\81ละà¸\9fีà¹\80à¸\88อรà¹\8cที่เกี่ยวข้อง"</string>
     <string name="work_mode_turn_on" msgid="2062544985670564875">"เปิด"</string>
     <string name="new_sms_notification_title" msgid="8442817549127555977">"คุณมีข้อความใหม่"</string>
     <string name="new_sms_notification_content" msgid="7002938807812083463">"เปิดแอป SMS เพื่อดู"</string>
index ee01ff2..7cc10be 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"I-tap upang pumili ng wika at layout"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Ipinapakita sa itaas ng iba pang app ang <xliff:g id="NAME">%s</xliff:g>."</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"Nasa ibabaw ng ibang app ang <xliff:g id="NAME">%s</xliff:g>"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Kung ayaw mong gamitin ng <xliff:g id="NAME">%s</xliff:g> ang feature na ito, i-tap upang buksan ang mga setting at i-off ito."</string>
index bbae91a..2096a93 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Dili ve düzeni seçmek için dokunun"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>, diğer uygulamaların üzerinde görüntüleniyor"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>, diğer uygulamaların üzerinde gösteriliyor"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> uygulamasının bu özelliği kullanmasını istemiyorsanız dokunarak ayarları açın ve özelliği kapatın."</string>
index f187c03..f635ec4 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Торкніться, щоб вибрати мову та розкладку"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789АБВГҐДЕЄЖЗИІЇЙКЛМНОПРСТУФХЦЧШЩЬЮЯ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"Додаток <xliff:g id="NAME">%s</xliff:g> відображається поверх інших додатків"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> відображається поверх інших додатків"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Щоб у додатку <xliff:g id="NAME">%s</xliff:g> не працювала ця функція, вимкніть її в налаштуваннях."</string>
index 310bddd..7f007be 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"زبان اور لے آؤٹ منتخب کرنے کیلئے تھپتھپائیں"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> کو دیگر ایپس پر دکھایا کیا جا رہا ہے"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> دیگر ایپس پر ڈسپلے ہو رہی ہے"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"اگر آپ نہیں چاہتے ہیں کہ <xliff:g id="NAME">%s</xliff:g> اس خصوصیت کا استعمال کرے تو ترتیبات کھولنے کیلئے تھپتھپائیں اور اسے بند کریں۔"</string>
index bd53da5..4351ab2 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Til va sxemani belgilash uchun bosing"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochilgan"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> boshqa ilovalar ustidan ochilgan"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"<xliff:g id="NAME">%s</xliff:g> ilovasi uchun bu funksiyani sozlamalar orqali o‘chirib qo‘yish mumkin."</string>
index 655bdc7..f134eca 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Nhấn để chọn ngôn ngữ và bố cục"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> hiển thị trên các ứng dụng khác"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> hiển thị trên ứng dụng khác"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Nếu bạn không muốn <xliff:g id="NAME">%s</xliff:g> sử dụng tính năng này, hãy nhấn để mở cài đặt và tắt tính năng này."</string>
index c19e3d2..fda476d 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"点按即可选择语言和布局"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g>正在其他应用的上层显示内容"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g>正在其他应用的上层显示内容"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"如果您不想让<xliff:g id="NAME">%s</xliff:g>使用此功能,请点按以打开设置,然后关闭此功能。"</string>
index 415c1ac..797a195 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕按即可選取語言和鍵盤配置"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"「<xliff:g id="NAME">%s</xliff:g>」目前可顯示在其他應用程式上面"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"「<xliff:g id="NAME">%s</xliff:g>」正在其他應用程式上顯示內容"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"如果您不想「<xliff:g id="NAME">%s</xliff:g>」使用此功能,請輕按以開啟設定,然後停用此功能。"</string>
index 36f9a9e..9008d8e 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"輕觸即可選取語言和版面配置"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"「<xliff:g id="NAME">%s</xliff:g>」在其他應用程式上顯示內容"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"「<xliff:g id="NAME">%s</xliff:g>」正在其他應用程式上顯示內容"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"如果你不想讓「<xliff:g id="NAME">%s</xliff:g>」使用這項功能,請輕觸開啟設定頁面,然後停用此功能。"</string>
index ff35931..c1bff23 100644 (file)
     <string name="select_keyboard_layout_notification_message" msgid="8084622969903004900">"Thepha ukuze ukhethe ulimi nesakhiwo"</string>
     <string name="fast_scroll_alphabet" msgid="5433275485499039199">" ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
     <string name="fast_scroll_numeric_alphabet" msgid="4030170524595123610">" 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"</string>
+    <!-- no translation found for alert_windows_notification_channel_group_name (1463953341148606396) -->
+    <skip />
     <string name="alert_windows_notification_channel_name" msgid="3116610965549449803">"<xliff:g id="NAME">%s</xliff:g> ukubonisa ngaphezu kwezinye izinhlelo zokusebenza"</string>
     <string name="alert_windows_notification_title" msgid="3697657294867638947">"<xliff:g id="NAME">%s</xliff:g> ibonisa ngaphezu kwezinye izinhlelo zokusebenza"</string>
     <string name="alert_windows_notification_message" msgid="8917232109522912560">"Uma ungafuni ukuthi i-<xliff:g id="NAME">%s</xliff:g> isebenzise lesi sici, thepha ukuze uvule izilungiselelo bese usivale."</string>
index 8e6c402..241e565 100644 (file)
          that can be set by the user. -->
     <integer name="config_screenBrightnessDoze">1</integer>
 
+    <!-- Whether or not to skip the initial brightness ramps when the display transitions to
+         STATE_ON. Setting this to true will skip the brightness ramp to the last stored active
+         brightness value and will repeat for the following ramp if autobrightness is enabled. -->
+    <bool name="config_skipScreenOnBrightnessRamp">false</bool>
+
     <!-- Allow automatic adjusting of the screen brightness while dozing in low power state. -->
     <bool name="config_allowAutoBrightnessWhileDozing">false</bool>
 
     <!-- The default vibration strength, must be between 1 and 255 inclusive. -->
     <integer name="config_defaultVibrationAmplitude">255</integer>
 
+    <!-- If the device should still vibrate even in low power mode, for certain priority vibrations
+     (e.g. accessibility, alarms). This is mainly for Wear devices that don't have speakers. -->
+    <bool name="config_allowPriorityVibrationsInLowPowerMode">false</bool>
+
     <!-- Number of retries Cell Data should attempt for a given error code before
          restarting the modem.
          Error codes not listed will not lead to modem restarts.
index f747d3d..3eebe7e 100644 (file)
 
     <!-- Notification title to tell the user that data service is blocked by access control. -->
     <string name="RestrictedOnDataTitle">No data service</string>
-    <!-- Notification title to tell the user that emergency service is blocked by access control. -->
-    <string name="RestrictedOnEmergencyTitle">No emergency service</string>
+    <!-- Notification title to tell the user that emergency calling is blocked by access control. -->
+    <string name="RestrictedOnEmergencyTitle">No emergency calling</string>
     <!-- Notification title to tell the user that normal service is blocked by access control. -->
     <string name="RestrictedOnNormalTitle">No voice service</string>
     <!-- Notification title to tell the user that all emergency and normal voice services are blocked by access control. -->
     <string name="RestrictedOnAllVoiceTitle">No voice/emergency service</string>
 
-    <!-- Notification content to tell the user that data service is blocked by access control. -->
-    <string name="RestrictedOnDataContent">Your carrier has temporarily suspended data service at this location</string>
-    <!-- Notification content to tell the user that emergency service is blocked by access control. -->
-    <string name="RestrictedOnEmergencyContent">Your carrier has temporarily suspended emergency calls at this location</string>
-    <!-- Notification content to tell the user that normal service is blocked by access control. -->
-    <string name="RestrictedOnNormalContent">Your carrier has temporarily suspended voice calls at this location</string>
-    <!-- Notification content to tell the user that all emergency and normal voice services are blocked by access control. -->
-    <string name="RestrictedOnAllVoiceContent">Your carrier has temporarily suspended voice and emergency calls at this location</string>
+    <!-- Notification content to tell the user that voice/data/emergency service is blocked by access control. -->
+    <string name="RestrictedStateContent">Temporarily not offered by the mobile network at your location</string>
 
     <!-- Displayed to tell the user that they should switch their network preference. -->
     <string name="NetworkPreferenceSwitchTitle">Can\u2019t reach network</string>
 
     <!-- Alert windows notification strings -->
     <skip />
+    <!-- Name of notification channel group the system post notification to inform the use about apps
+         that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
+    <string name="alert_windows_notification_channel_group_name">Display over other apps</string>
     <!-- Name of notification channel the system post notification to inform the use about apps
          that are drawing ui on-top of other apps (alert-windows) [CHAR LIMIT=NONE] -->
     <string name="alert_windows_notification_channel_name"><xliff:g id="name" example="Google Maps">%s</xliff:g> displaying over other apps</string>
index 8d2666e..7dd4022 100644 (file)
   <java-symbol type="string" name="RestrictedOnDataTitle" />
   <java-symbol type="string" name="RestrictedOnEmergencyTitle" />
   <java-symbol type="string" name="RestrictedOnNormalTitle" />
-  <java-symbol type="string" name="RestrictedOnAllVoiceContent" />
-  <java-symbol type="string" name="RestrictedOnDataContent" />
-  <java-symbol type="string" name="RestrictedOnEmergencyContent" />
-  <java-symbol type="string" name="RestrictedOnNormalContent" />
+  <java-symbol type="string" name="RestrictedStateContent" />
   <java-symbol type="string" name="notification_channel_network_alert" />
   <java-symbol type="string" name="notification_channel_call_forward" />
   <java-symbol type="string" name="notification_channel_emergency_callback" />
   <java-symbol type="bool" name="config_sf_limitedAlpha" />
   <java-symbol type="bool" name="config_unplugTurnsOnScreen" />
   <java-symbol type="bool" name="config_usbChargingMessage" />
+  <java-symbol type="bool" name="config_skipScreenOnBrightnessRamp" />
   <java-symbol type="bool" name="config_allowAutoBrightnessWhileDozing" />
   <java-symbol type="bool" name="config_allowTheaterModeWakeFromUnplug" />
   <java-symbol type="bool" name="config_allowTheaterModeWakeFromGesture" />
   <java-symbol type="dimen" name="default_minimal_size_pip_resizable_task" />
   <java-symbol type="dimen" name="task_height_of_minimized_mode" />
   <java-symbol type="fraction" name="config_screenAutoBrightnessDozeScaleFactor" />
+  <java-symbol type="bool" name="config_allowPriorityVibrationsInLowPowerMode" />
   <java-symbol type="fraction" name="config_autoBrightnessAdjustmentMaxGamma" />
   <java-symbol type="integer" name="config_autoBrightnessAmbientLightHorizon"/>
   <java-symbol type="integer" name="config_autoBrightnessBrighteningLightDebounce"/>
   <java-symbol type="drawable" name="resolver_icon_placeholder" />
 
   <!-- Alert windows notification -->
+  <java-symbol type="string" name="alert_windows_notification_channel_group_name" />
   <java-symbol type="string" name="alert_windows_notification_channel_name" />
   <java-symbol type="string" name="alert_windows_notification_title" />
   <java-symbol type="string" name="alert_windows_notification_message" />
   <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
 
   <java-symbol type="integer" name="config_inCallNotificationVolumeRelative" />
+  <java-symbol type="drawable" name="stat_sys_vitals" />
 </resources>
index 7517946..8755e37 100644 (file)
@@ -758,6 +758,14 @@ easier.
         <item name="colorControlNormal">?attr/textColorPrimary</item>
     </style>
 
+    <style name="Theme.DeviceDefault.QuickSettings.Dialog" parent="Theme.DeviceDefault.Light.Dialog">
+        <!-- Color palette -->
+        <item name="colorPrimary">@color/primary_device_default_settings_light</item>
+        <item name="colorPrimaryDark">@color/primary_dark_device_default_settings_light</item>
+        <item name="colorSecondary">@color/secondary_device_default_settings_light</item>
+        <item name="colorAccent">@color/accent_device_default_light</item>
+    </style>
+
     <!-- Variant of {@link #Theme_DeviceDefault_Settings_Dark} with no action bar -->
     <style name="Theme.DeviceDefault.Settings.Dark.NoActionBar" parent="Theme.Material.NoActionBar">
         <!-- Color palette -->
index 15dbddf..59aa50a 100644 (file)
@@ -492,7 +492,7 @@ public class AppCacheTest extends AndroidTestCase {
             PackageDataObserver observer = new PackageDataObserver();
             //wait on observer
             synchronized(observer) {
-                getPm().freeStorageAndNotify(null, idealStorageSize, observer);
+                getPm().freeStorageAndNotify(null, idealStorageSize, 0, observer);
                 long waitTime = 0;
                 while(!observer.isDone() || (waitTime > MAX_WAIT_TIME)) {
                     observer.wait(WAIT_TIME_INCR);
@@ -517,7 +517,7 @@ public class AppCacheTest extends AndroidTestCase {
         try {
             // Spin lock waiting for call back
             synchronized(r) {
-                getPm().freeStorage(null, idealStorageSize, pi.getIntentSender());
+                getPm().freeStorage(null, idealStorageSize, 0, pi.getIntentSender());
                 long waitTime = 0;
                 while(!r.isDone() && (waitTime < MAX_WAIT_TIME)) {
                     r.wait(WAIT_TIME_INCR);
index 54d5285..d875ed4 100644 (file)
@@ -334,7 +334,11 @@ public class SettingsBackupTest {
                     Settings.Global.TRUSTED_SOUND,
                     Settings.Global.TZINFO_UPDATE_CONTENT_URL,
                     Settings.Global.TZINFO_UPDATE_METADATA_URL,
-                    Settings.Global.UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS,
+                    Settings.Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                    Settings.Global.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
+                    Settings.Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                    Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
+                    Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
                     Settings.Global.UNLOCK_SOUND,
                     Settings.Global.USE_GOOGLE_MAIL,
                     Settings.Global.VT_IMS_ENABLED,
index dd07a08..3ddeef0 100644 (file)
 
 package android.widget.touchmode;
 
-import android.widget.layout.linear.LLEditTextThenButton;
-import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
 import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterClick;
+import static android.util.TouchModeFlexibleAsserts.assertInTouchModeAfterTap;
 
 import android.test.ActivityInstrumentationTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.MediumTest;
-import android.view.KeyEvent;
 import android.widget.Button;
 import android.widget.EditText;
+import android.widget.layout.linear.LLEditTextThenButton;
 
 /**
  * Some views, like edit texts, can keep and gain focus even when in touch mode.
@@ -64,7 +63,8 @@ public class TouchModeFocusableTest extends ActivityInstrumentationTestCase<LLEd
     @LargeTest
     public void testClickEditTextGivesItFocus() {
         // go down to button
-        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        getActivity().runOnUiThread(() -> mButton.requestFocus());
+        getInstrumentation().waitForIdleSync();
         assertTrue("button should have focus", mButton.isFocused());
 
         assertInTouchModeAfterClick(this, mEditText);
@@ -77,11 +77,12 @@ public class TouchModeFocusableTest extends ActivityInstrumentationTestCase<LLEd
     // isn't focusable in touch mode.
     @LargeTest
     public void testEnterTouchModeGivesFocusBackToFocusableInTouchMode() {
-        sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);
+        getActivity().runOnUiThread(() -> mButton.requestFocus());
+        getInstrumentation().waitForIdleSync();
 
         assertTrue("button should have focus",
                 mButton.isFocused());
-        
+
         assertInTouchModeAfterClick(this, mButton);
         assertTrue("should be in touch mode", mButton.isInTouchMode());
         assertNull("nothing should have focus", getActivity().getCurrentFocus());
index fd57baa..115af5e 100644 (file)
@@ -180,7 +180,9 @@ public class SparseMappingTableTest extends TestCase {
 
         try {
             table.getValue(key);
-            throw new Exception("Exception not thrown after mismatched reset calls.");
+            // Turn off this assertion because the check in SparseMappingTable.assertConsistency
+            // is also turned off.
+            //throw new Exception("Exception not thrown after mismatched reset calls.");
         } catch (RuntimeException ex) {
             // Good
         }
index 9aabdbb..c539f78 100644 (file)
@@ -205,9 +205,9 @@ public class BatteryStatsBackgroundStatsTest extends TestCase {
         // App in foreground
         bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND);
 
-        // Start timer
+        // Start timer (optimized)
         curr = 1000 * (clocks.realtime = clocks.uptime = 202);
-        bi.noteBluetoothScanStartedFromSourceLocked(ws);
+        bi.noteBluetoothScanStartedFromSourceLocked(ws, false);
 
         // Move to background
         curr = 1000 * (clocks.realtime = clocks.uptime = 254);
@@ -221,21 +221,44 @@ public class BatteryStatsBackgroundStatsTest extends TestCase {
         curr = 1000 * (clocks.realtime = clocks.uptime = 409);
         bi.noteBluetoothScanStoppedFromSourceLocked(ws);
 
+        // Start timer (unoptimized)
+        curr = 1000 * (clocks.realtime = clocks.uptime = 1000);
+        bi.noteBluetoothScanStartedFromSourceLocked(ws, true);
+
+        // On battery
+        curr = 1000 * (clocks.realtime = clocks.uptime = 2001);
+        bi.updateTimeBasesLocked(true, false, curr, curr); // on battery
+
+        // Move to foreground
+        curr = 1000 * (clocks.realtime = clocks.uptime = 3004);
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
+
+        // Stop timer
+        curr = 1000 * (clocks.realtime = clocks.uptime = 4008);
+        bi.noteBluetoothScanStoppedFromSourceLocked(ws);
+
         // Test
-        curr = 1000 * (clocks.realtime = clocks.uptime = 657);
+        curr = 1000 * (clocks.realtime = clocks.uptime = 5000);
         BatteryStats.Timer timer = bi.getUidStats().get(UID).getBluetoothScanTimer();
         BatteryStats.Timer bgTimer = bi.getUidStats().get(UID).getBluetoothScanBackgroundTimer();
+        BatteryStats.Timer badTimer = bi.getUidStats().get(UID).getBluetoothUnoptimizedScanTimer();
+        BatteryStats.Timer badBgTimer = bi.getUidStats().get(UID)
+                .getBluetoothUnoptimizedScanBackgroundTimer();
 
         long time = timer.getTotalTimeLocked(curr, STATS_SINCE_CHARGED);
         int count = timer.getCountLocked(STATS_SINCE_CHARGED);
         int bgCount = bgTimer.getCountLocked(STATS_SINCE_CHARGED);
         long actualTime = timer.getTotalDurationMsLocked(clocks.realtime) * 1000;
         long bgTime = bgTimer.getTotalDurationMsLocked(clocks.realtime) * 1000;
-        assertEquals((305 - 202) * 1000, time);
-        assertEquals(1, count);
-        assertEquals(0, bgCount);
-        assertEquals((305 - 202) * 1000, actualTime);
-        assertEquals((305 - 254) * 1000, bgTime);
+        long badTime = badTimer.getTotalDurationMsLocked(clocks.realtime) * 1000;
+        long badBgTime = badBgTimer.getTotalDurationMsLocked(clocks.realtime) * 1000;
+        assertEquals((305 - 202 + 4008 - 2001) * 1000, time);
+        assertEquals(1, count); // second scan starts off-battery
+        assertEquals(0, bgCount); // first scan starts in fg, second starts off-battery
+        assertEquals((305 - 202 + 4008 - 2001) * 1000, actualTime);
+        assertEquals((305 - 254 + 3004 - 2001) * 1000, bgTime);
+        assertEquals((4008 - 2001) * 1000, badTime);
+        assertEquals((3004 - 2001) * 1000, badBgTime);
     }
 
     @SmallTest
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsCounterTest.java
new file mode 100644 (file)
index 0000000..08f8dd1
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.android.internal.os;
+
+import android.os.BatteryStats;
+import android.os.Parcel;
+import android.support.test.filters.SmallTest;
+
+import junit.framework.TestCase;
+
+/**
+ * Test BatteryStatsImpl.Counter.
+ */
+public class BatteryStatsCounterTest extends TestCase {
+
+    @SmallTest
+    public void testCounter() throws Exception {
+        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
+        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+        final BatteryStatsImpl.Counter counter = new BatteryStatsImpl.Counter(timeBase);
+
+        // timeBase off (i.e. plugged in)
+        timeBase.setRunning(false, 1, 1);
+        counter.stepAtomic();
+        counter.stepAtomic();
+        counter.stepAtomic();
+        counter.stepAtomic();
+        counter.stepAtomic();
+        assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(0, counter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(0, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // timeBase on (i.e. unplugged)
+        timeBase.setRunning(true, 2, 2);
+        counter.stepAtomic();
+        counter.stepAtomic();
+        counter.stepAtomic();
+        counter.stepAtomic();
+        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // timeBase off (i.e. plugged in)
+        timeBase.setRunning(false, 3, 3);
+        counter.stepAtomic();
+        counter.stepAtomic();
+        counter.stepAtomic();
+        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(4, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // timeBase on (i.e. unplugged)
+        timeBase.setRunning(true, 4, 4);
+        counter.stepAtomic();
+        counter.stepAtomic();
+        assertEquals(6, counter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(6, counter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(2, counter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+    }
+
+
+    @SmallTest
+    public void testParceling() throws Exception {
+        final MockClocks clocks = new MockClocks(); // holds realtime and uptime in ms
+        final BatteryStatsImpl.TimeBase timeBase = new BatteryStatsImpl.TimeBase();
+        timeBase.init(clocks.uptimeMillis(), clocks.elapsedRealtime());
+
+        final BatteryStatsImpl.Counter origCounter = new BatteryStatsImpl.Counter(timeBase);
+
+        // timeBase on (i.e. unplugged)
+        timeBase.setRunning(true, 1, 1);
+        origCounter.stepAtomic(); origCounter.stepAtomic(); origCounter.stepAtomic(); // three times
+        assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(3, origCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // Test summary parcelling (from origCounter)
+        final Parcel summaryParcel = Parcel.obtain();
+        origCounter.writeSummaryFromParcelLocked(summaryParcel);
+        summaryParcel.setDataPosition(0);
+        final BatteryStatsImpl.Counter summaryCounter = new BatteryStatsImpl.Counter(timeBase);
+        summaryCounter.stepAtomic(); // occurs before reading the summary, so must not count later
+        summaryCounter.readSummaryFromParcelLocked(summaryParcel);
+
+        // timeBase still on (i.e. unplugged)
+        summaryCounter.stepAtomic(); // once
+        assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // timeBase off (i.e. plugged in)
+        timeBase.setRunning(false, 3, 3);
+        summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice
+        assertEquals(4, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(1, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // timeBase on (i.e. unplugged)
+        timeBase.setRunning(true, 4, 4);
+        summaryCounter.stepAtomic(); summaryCounter.stepAtomic(); // twice
+        assertEquals(6, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(3, summaryCounter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(2, summaryCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+
+        // Test full parcelling (from summaryCounter)
+        final Parcel fullParcel = Parcel.obtain();
+        summaryCounter.writeToParcel(fullParcel);
+        fullParcel.setDataPosition(0);
+        final BatteryStatsImpl.Counter fullParcelCounter
+                = new BatteryStatsImpl.Counter(timeBase, fullParcel);
+
+        // timeBase still on (i.e. unplugged)
+        fullParcelCounter.stepAtomic(); // once
+        assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // timeBase off (i.e. plugged in)
+        timeBase.setRunning(false, 5, 5);
+        fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice
+        assertEquals(7, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(4, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(3, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+
+        // timeBase on (i.e. unplugged)
+        timeBase.setRunning(true, 6, 6);
+        fullParcelCounter.stepAtomic(); fullParcelCounter.stepAtomic(); // twice
+        assertEquals(9, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_CHARGED));
+        assertEquals(6, fullParcelCounter.getCountLocked(BatteryStats.STATS_CURRENT));
+        assertEquals(2, fullParcelCounter.getCountLocked(BatteryStats.STATS_SINCE_UNPLUGGED));
+    }
+}
index 06ca18d..4e8ab31 100644 (file)
@@ -37,12 +37,28 @@ public class BatteryStatsNoteTest extends TestCase{
     public void testNoteBluetoothScanResultLocked() throws Exception {
         MockBatteryStatsImpl bi = new MockBatteryStatsImpl(new MockClocks());
         bi.updateTimeBasesLocked(true, true, 0, 0);
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_TOP);
 
         bi.noteBluetoothScanResultsFromSourceLocked(WS, 1);
         bi.noteBluetoothScanResultsFromSourceLocked(WS, 100);
         assertEquals(101,
                 bi.getUidStats().get(UID).getBluetoothScanResultCounter()
                         .getCountLocked(STATS_SINCE_CHARGED));
+        // TODO: remove next line when Counter misreporting values when plugged-in bug is fixed.
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+        BatteryStats.Counter bgCntr = bi.getUidStats().get(UID).getBluetoothScanResultBgCounter();
+        if (bgCntr != null) {
+            assertEquals(0, bgCntr.getCountLocked(STATS_SINCE_CHARGED));
+        }
+
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+        bi.noteBluetoothScanResultsFromSourceLocked(WS, 17);
+        assertEquals(101 + 17,
+                bi.getUidStats().get(UID).getBluetoothScanResultCounter()
+                        .getCountLocked(STATS_SINCE_CHARGED));
+        assertEquals(17,
+                bi.getUidStats().get(UID).getBluetoothScanResultBgCounter()
+                        .getCountLocked(STATS_SINCE_CHARGED));
     }
 
     /** Test BatteryStatsImpl.Uid.noteStartWakeLocked. */
index 3a16fcf..1412d3e 100644 (file)
@@ -5,17 +5,18 @@ import org.junit.runners.Suite;
 
 @RunWith(Suite.class)
 @Suite.SuiteClasses({
+        BatteryStatsBackgroundStatsTest.class,
+        BatteryStatsCounterTest.class,
         BatteryStatsDualTimerTest.class,
         BatteryStatsDurationTimerTest.class,
+        BatteryStatsNoteTest.class,
         BatteryStatsSamplingTimerTest.class,
+        BatteryStatsSensorTest.class,
         BatteryStatsServTest.class,
         BatteryStatsStopwatchTimerTest.class,
         BatteryStatsTimeBaseTest.class,
         BatteryStatsTimerTest.class,
         BatteryStatsUidTest.class,
-        BatteryStatsSensorTest.class,
-        BatteryStatsBackgroundStatsTest.class,
-        BatteryStatsNoteTest.class,
     })
 public class BatteryStatsTests {
 }
index e62df8f..f931d21 100644 (file)
@@ -529,6 +529,7 @@ public class Paint {
         setTextLocales(LocaleList.getAdjustedDefault());
         setElegantTextHeight(false);
         mFontFeatureSettings = null;
+        mFontVariationSettings = null;
     }
 
     /**
@@ -565,6 +566,7 @@ public class Paint {
         mBidiFlags = paint.mBidiFlags;
         mLocales = paint.mLocales;
         mFontFeatureSettings = paint.mFontFeatureSettings;
+        mFontVariationSettings = paint.mFontVariationSettings;
     }
 
     /** @hide */
@@ -1034,6 +1036,8 @@ public class Paint {
         // old shader's pointer may be reused by another shader allocation later
         if (mShader != shader) {
             mNativeShader = -1;
+            // Release any native references to the old shader content
+            nSetShader(mNativePaint, 0);
         }
         // Defer setting the shader natively until getNativeInstance() is called
         mShader = shader;
@@ -1594,10 +1598,13 @@ public class Paint {
             return true;
         }
 
+        // The null typeface is valid and it is equivalent to Typeface.DEFAULT.
+        // To call isSupportedAxes method, use Typeface.DEFAULT instance.
+        Typeface targetTypeface = mTypeface == null ? Typeface.DEFAULT : mTypeface;
         FontVariationAxis[] axes = FontVariationAxis.fromFontVariationSettings(settings);
         final ArrayList<FontVariationAxis> filteredAxes = new ArrayList<FontVariationAxis>();
         for (final FontVariationAxis axis : axes) {
-            if (mTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) {
+            if (targetTypeface.isSupportedAxes(axis.getOpenTypeTagValue())) {
                 filteredAxes.add(axis);
             }
         }
@@ -1605,7 +1612,7 @@ public class Paint {
             return false;
         }
         mFontVariationSettings = settings;
-        setTypeface(Typeface.createFromTypefaceWithVariation(mTypeface, filteredAxes));
+        setTypeface(Typeface.createFromTypefaceWithVariation(targetTypeface, filteredAxes));
         return true;
     }
 
index 5a56f53..c4b56c3 100644 (file)
@@ -725,8 +725,8 @@ public class Typeface {
     }
 
     /** @hide */
-    public static Typeface createFromTypefaceWithVariation(Typeface family,
-            List<FontVariationAxis> axes) {
+    public static Typeface createFromTypefaceWithVariation(@Nullable Typeface family,
+            @NonNull List<FontVariationAxis> axes) {
         final long ni = family == null ? 0 : family.native_instance;
         return new Typeface(nativeCreateFromTypefaceWithVariation(ni, axes));
     }
@@ -1056,7 +1056,7 @@ public class Typeface {
                 }
             }
         }
-        return Arrays.binarySearch(mSupportedAxes, axis) > 0;
+        return Arrays.binarySearch(mSupportedAxes, axis) >= 0;
     }
 
     private static native long nativeCreateFromTypeface(long native_instance, int style);
index 00b5eda..90d6ab8 100644 (file)
@@ -834,6 +834,16 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
             final Animator localAnimator = animator.clone();
             final String targetName = mTargetNameMap.get(animator);
             final Object target = mVectorDrawable.getTargetByName(targetName);
+            if (!mShouldIgnoreInvalidAnim) {
+                if (target == null) {
+                    throw new IllegalStateException("Target with the name \"" + targetName
+                            + "\" cannot be found in the VectorDrawable to be animated.");
+                } else if (!(target instanceof VectorDrawable.VectorDrawableState)
+                        && !(target instanceof VectorDrawable.VObject)) {
+                    throw new UnsupportedOperationException("Target should be either VGroup, VPath,"
+                            + " or ConstantState, " + target.getClass() + " is not supported");
+                }
+            }
             localAnimator.setTarget(target);
             return localAnimator;
         }
@@ -1321,16 +1331,10 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
                         throw new IllegalArgumentException("ClipPath only supports PathData " +
                                 "property");
                     }
-
                 }
             } else if (target instanceof VectorDrawable.VectorDrawableState) {
                 createRTAnimatorForRootGroup(values, animator,
                         (VectorDrawable.VectorDrawableState) target, startTime);
-            } else if (!mDrawable.mAnimatedVectorState.mShouldIgnoreInvalidAnim) {
-                // Should never get here
-                throw new UnsupportedOperationException("Target should be either VGroup, VPath, " +
-                        "or ConstantState, " + target == null ? "Null target" : target.getClass() +
-                        " is not supported");
             }
         }
 
index 39f11b8..4ee47af 100644 (file)
@@ -61,8 +61,17 @@ void RenderNodeDrawable::drawBackwardsProjectedNodes(SkCanvas* canvas, const Ski
 static void clipOutline(const Outline& outline, SkCanvas* canvas, const SkRect* pendingClip) {
     Rect possibleRect;
     float radius;
-    LOG_ALWAYS_FATAL_IF(!outline.getAsRoundRect(&possibleRect, &radius),
-            "clipping outlines should be at most roundedRects");
+
+    /* To match the existing HWUI behavior we only supports rectangles or
+     * rounded rectangles; passing in a more complicated outline fails silently.
+     */
+    if (!outline.getAsRoundRect(&possibleRect, &radius)) {
+        if (pendingClip) {
+            canvas->clipRect(*pendingClip);
+        }
+        return;
+    }
+
     SkRect rect = possibleRect.toSkRect();
     if (radius != 0.0f) {
         if (pendingClip && !pendingClip->contains(rect)) {
index 02a9ffa..9c80ab3 100644 (file)
@@ -436,8 +436,15 @@ void CanvasContext::draw() {
         swap.vsyncTime = mRenderThread.timeLord().latestVsync();
         if (mNativeSurface.get()) {
             int durationUs;
-            mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs);
-            swap.dequeueDuration = us2ns(durationUs);
+            nsecs_t dequeueStart = mNativeSurface->getLastDequeueStartTime();
+            if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::SyncStart)) {
+                // Ignoring dequeue duration as it happened prior to frame render start
+                // and thus is not part of the frame.
+                swap.dequeueDuration = 0;
+            } else {
+                mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs);
+                swap.dequeueDuration = us2ns(durationUs);
+            }
             mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs);
             swap.queueDuration = us2ns(durationUs);
         } else {
index ce3c56f..ec6dfb7 100644 (file)
@@ -18,6 +18,8 @@ package android.location;
 
 import java.util.HashMap;
 
+import android.annotation.SystemService;
+import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.RemoteException;
@@ -40,13 +42,10 @@ import android.util.Log;
  * To be notified of the future country change, use the
  * {@link #addCountryListener}
  * <p>
- * <p>
- * You do not instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.COUNTRY_DETECTOR)}.
  *
  * @hide
  */
+@SystemService(Context.COUNTRY_DETECTOR)
 public class CountryDetector {
 
     /**
index f9385c6..26ac2a2 100644 (file)
@@ -20,7 +20,9 @@ import com.android.internal.location.ProviderProperties;
 
 import android.Manifest;
 import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -47,11 +49,6 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION;
  * {@link Intent} when the device enters the proximity of a given
  * geographical location.
  *
- * <p>You do not
- * instantiate this class directly; instead, retrieve it through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.LOCATION_SERVICE)}.
- *
  * <p class="note">Unless noted, all Location API methods require
  * the {@link android.Manifest.permission#ACCESS_COARSE_LOCATION} or
  * {@link android.Manifest.permission#ACCESS_FINE_LOCATION} permissions.
@@ -60,8 +57,8 @@ import static android.Manifest.permission.ACCESS_FINE_LOCATION;
  * return location results, but the update rate will be throttled and the exact
  * location will be obfuscated to a coarse level of accuracy.
  */
-public class LocationManager
-{
+@SystemService(Context.LOCATION_SERVICE)
+public class LocationManager {
     private static final String TAG = "LocationManager";
 
     private final Context mContext;
@@ -831,6 +828,7 @@ public class LocationManager
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(LocationRequest request, LocationListener listener,
             Looper looper) {
         checkListener(listener);
@@ -859,6 +857,7 @@ public class LocationManager
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION})
     public void requestLocationUpdates(LocationRequest request, PendingIntent intent) {
         checkPendingIntent(intent);
         requestLocationUpdates(request, null, null, intent);
@@ -1820,6 +1819,7 @@ public class LocationManager
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean addGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
         return false;
     }
@@ -1857,6 +1857,7 @@ public class LocationManager
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public void removeGpsMeasurementListener(GpsMeasurementsEvent.Listener listener) {
     }
 
@@ -1877,6 +1878,7 @@ public class LocationManager
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean addGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
         return false;
     }
@@ -1891,6 +1893,7 @@ public class LocationManager
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public void removeGpsNavigationMessageListener(GpsNavigationMessageEvent.Listener listener) {
     }
 
index 0b5dff2..20deeb1 100644 (file)
@@ -19,9 +19,11 @@ package android.media;
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.bluetooth.BluetoothDevice;
@@ -58,10 +60,8 @@ import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * AudioManager provides access to volume and ringer mode control.
- * <p>
- * Use <code>Context.getSystemService(Context.AUDIO_SERVICE)</code> to get
- * an instance of this class.
  */
+@SystemService(Context.AUDIO_SERVICE)
 public class AudioManager {
 
     private Context mOriginalContext;
@@ -2827,6 +2827,7 @@ public class AudioManager {
      *    {@link #SUCCESS} otherwise.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public int registerAudioPolicy(@NonNull AudioPolicy policy) {
         if (policy == null) {
             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
@@ -2852,6 +2853,7 @@ public class AudioManager {
      * @param policy the non-null {@link AudioPolicy} to unregister.
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_AUDIO_ROUTING)
     public void unregisterAudioPolicyAsync(@NonNull AudioPolicy policy) {
         if (policy == null) {
             throw new IllegalArgumentException("Illegal null AudioPolicy argument");
index 6cab56c..2de69e7 100644 (file)
@@ -75,12 +75,12 @@ import java.util.Map;
  <h4>Compressed Buffers</h4>
  <p>
  Input buffers (for decoders) and output buffers (for encoders) contain compressed data according
- to the {@linkplain MediaFormat#KEY_MIME format's type}. For video types this is a single
+ to the {@linkplain MediaFormat#KEY_MIME format's type}. For video types this is normally a single
  compressed video frame. For audio data this is normally a single access unit (an encoded audio
  segment typically containing a few milliseconds of audio as dictated by the format type), but
  this requirement is slightly relaxed in that a buffer may contain multiple encoded access units
  of audio. In either case, buffers do not start or end on arbitrary byte boundaries, but rather on
- frame/access unit boundaries.
+ frame/access unit boundaries unless they are flagged with {@link #BUFFER_FLAG_PARTIAL_FRAME}.
 
  <h4>Raw Audio Buffers</h4>
  <p>
index 228a6de..dd731df 100644 (file)
@@ -136,7 +136,13 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
 
     private void teardownConnection() {
         if (mConnection != null) {
-            mInputStream = null;
+            if (mInputStream != null) {
+                try {
+                    mInputStream.close();
+                } catch (IOException e) {
+                }
+                mInputStream = null;
+            }
 
             mConnection.disconnect();
             mConnection = null;
@@ -298,8 +304,7 @@ public class MediaHTTPConnection extends IMediaHTTPConnection.Stub {
             mCurrentOffset = offset;
         } catch (IOException e) {
             mTotalSize = -1;
-            mInputStream = null;
-            mConnection = null;
+            teardownConnection();
             mCurrentOffset = -1;
 
             throw e;
index 44494a6..91dada7 100644 (file)
@@ -20,6 +20,7 @@ import android.Manifest;
 import android.annotation.DrawableRes;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
+import android.annotation.SystemService;
 import android.app.ActivityThread;
 import android.content.BroadcastReceiver;
 import android.content.Context;
@@ -61,6 +62,7 @@ import java.util.concurrent.CopyOnWriteArrayList;
  * <p>The media router API is not thread-safe; all interactions with it must be
  * done from the main thread of the process.</p>
  */
+@SystemService(Context.MEDIA_ROUTER_SERVICE)
 public class MediaRouter {
     private static final String TAG = "MediaRouter";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
index 5522d36..799f4bf 100644 (file)
@@ -35,7 +35,7 @@ import java.util.LinkedList;
 import java.util.List;
 
 /**
- * MediaSync class can be used to synchronously playback audio and video streams.
+ * MediaSync class can be used to synchronously play audio and video streams.
  * It can be used to play audio-only or video-only stream, too.
  *
  * <p>MediaSync is generally used like this:
index 07c8ae8..a015732 100644 (file)
@@ -16,7 +16,9 @@
 
 package android.media.midi;
 
+import android.annotation.SystemService;
 import android.bluetooth.BluetoothDevice;
+import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
 import android.os.Bundle;
@@ -28,13 +30,8 @@ import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * This class is the public application interface to the MIDI service.
- *
- * <p>You can obtain an instance of this class by calling
- * {@link android.content.Context#getSystemService(java.lang.String) Context.getSystemService()}.
- *
- * {@samplecode
- * MidiManager manager = (MidiManager) getSystemService(Context.MIDI_SERVICE);}
  */
+@SystemService(Context.MIDI_SERVICE)
 public final class MidiManager {
     private static final String TAG = "MidiManager";
 
index f4a548b..9f2c08e 100644 (file)
@@ -18,6 +18,7 @@ package android.media.projection;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.SystemService;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -33,14 +34,8 @@ import java.util.Map;
 
 /**
  * Manages the retrieval of certain types of {@link MediaProjection} tokens.
- *
- * <p>
- * Get an instance of this class by calling {@link
- * android.content.Context#getSystemService(java.lang.String)
- * Context.getSystemService()} with the argument {@link
- * android.content.Context#MEDIA_PROJECTION_SERVICE}.
- * </p>
  */
+@SystemService(Context.MEDIA_PROJECTION_SERVICE)
 public final class MediaProjectionManager {
     private static final String TAG = "MediaProjectionManager";
     /** @hide */
index 83793ae..e02a4dc 100644 (file)
@@ -18,7 +18,9 @@ package android.media.session;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.media.AudioManager;
@@ -42,13 +44,11 @@ import java.util.List;
  * Provides support for interacting with {@link MediaSession media sessions}
  * that applications have published to express their ongoing media playback
  * state.
- * <p>
- * Use <code>Context.getSystemService(Context.MEDIA_SESSION_SERVICE)</code> to
- * get an instance of this class.
  *
  * @see MediaSession
  * @see MediaController
  */
+@SystemService(Context.MEDIA_SESSION_SERVICE)
 public final class MediaSessionManager {
     private static final String TAG = "SessionManager";
 
@@ -357,6 +357,7 @@ public final class MediaSessionManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_VOLUME_KEY_LONG_PRESS_LISTENER)
     public void setOnVolumeKeyLongPressListener(
             OnVolumeKeyLongPressListener listener, @Nullable Handler handler) {
         synchronized (mLock) {
@@ -392,6 +393,7 @@ public final class MediaSessionManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.SET_MEDIA_KEY_LISTENER)
     public void setOnMediaKeyListener(OnMediaKeyListener listener, @Nullable Handler handler) {
         synchronized (mLock) {
             try {
index d5296ae..a48abff 100644 (file)
@@ -20,6 +20,7 @@ import static android.hardware.soundtrigger.SoundTrigger.STATUS_OK;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.hardware.soundtrigger.IRecognitionStatusCallback;
 import android.hardware.soundtrigger.SoundTrigger;
@@ -235,6 +236,7 @@ public final class SoundTriggerDetector {
      * {@link Callback}.
      * @return Indicates whether the call succeeded or not.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public boolean startRecognition(@RecognitionFlags int recognitionFlags) {
         if (DBG) {
             Slog.d(TAG, "startRecognition()");
@@ -258,6 +260,7 @@ public final class SoundTriggerDetector {
     /**
      * Stops recognition for the associated model.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public boolean stopRecognition() {
         int status = STATUS_OK;
         try {
index fdd7fc2..7f8140a 100644 (file)
@@ -18,7 +18,9 @@ package android.media.soundtrigger;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.hardware.soundtrigger.SoundTrigger;
 import android.os.Handler;
@@ -39,6 +41,7 @@ import java.util.UUID;
  * @hide
  */
 @SystemApi
+@SystemService(Context.SOUND_TRIGGER_SERVICE)
 public final class SoundTriggerManager {
     private static final boolean DBG = false;
     private static final String TAG = "SoundTriggerManager";
@@ -65,6 +68,7 @@ public final class SoundTriggerManager {
     /**
      * Updates the given sound trigger model.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public void updateModel(Model model) {
         try {
             mSoundTriggerService.updateSoundModel(model.getGenericSoundModel());
@@ -77,6 +81,7 @@ public final class SoundTriggerManager {
      * Returns the sound trigger model represented by the given UUID. An instance of {@link Model}
      * is returned.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public Model getModel(UUID soundModelId) {
         try {
             return new Model(mSoundTriggerService.getSoundModel(
@@ -89,6 +94,7 @@ public final class SoundTriggerManager {
     /**
      * Deletes the sound model represented by the provided UUID.
      */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public void deleteModel(UUID soundModelId) {
         try {
             mSoundTriggerService.deleteSoundModel(new ParcelUuid(soundModelId));
@@ -110,6 +116,7 @@ public final class SoundTriggerManager {
      * @return Instance of {@link SoundTriggerDetector} or null on error.
      */
     @Nullable
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
     public SoundTriggerDetector createSoundTriggerDetector(UUID soundModelId,
             @NonNull SoundTriggerDetector.Callback callback, @Nullable Handler handler) {
         if (soundModelId == null) {
index 68ee02c..28fd338 100644 (file)
@@ -21,6 +21,8 @@ import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
 import android.media.PlaybackParams;
@@ -57,9 +59,7 @@ import java.util.Map;
 
 /**
  * Central system API to the overall TV input framework (TIF) architecture, which arbitrates
- * interaction between applications and the selected TV inputs. You can retrieve an instance of
- * this interface with {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.TV_INPUT_SERVICE)}.
+ * interaction between applications and the selected TV inputs.
  *
  * <p>There are three primary parties involved in the TV input framework (TIF) architecture:
  *
@@ -78,6 +78,7 @@ import java.util.Map;
  * programs.
  * </ul>
  */
+@SystemService(Context.TV_INPUT_SERVICE)
 public final class TvInputManager {
     private static final String TAG = "TvInputManager";
 
@@ -1516,6 +1517,7 @@ public final class TvInputManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT)
     public List<TvStreamConfig> getAvailableTvStreamConfigList(String inputId) {
         try {
             return mService.getAvailableTvStreamConfigList(inputId, mUserId);
@@ -1534,6 +1536,7 @@ public final class TvInputManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CAPTURE_TV_INPUT)
     public boolean captureFrame(String inputId, Surface surface, TvStreamConfig config) {
         try {
             return mService.captureFrame(inputId, surface, config, mUserId);
index 6678f8b..5680d9f 100644 (file)
@@ -1139,8 +1139,17 @@ public class StaticMetadata {
         }
         List<Integer> modeList = new ArrayList<Integer>();
         for (int mode : modes) {
-            modeList.add(mode);
+            // Skip vendor-added modes
+            if (mode <= CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE) {
+                modeList.add(mode);
+            }
+        }
+        checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
+        modes = new int[modeList.size()];
+        for (int i = 0; i < modeList.size(); i++) {
+            modes[i] = modeList.get(i);
         }
+
         checkTrueForKey(modesKey, "value is empty", !modeList.isEmpty());
 
         // All camera device must support ON
@@ -1227,7 +1236,17 @@ public class StaticMetadata {
             return new int[0];
         }
 
-        List<Integer> modesList = Arrays.asList(CameraTestUtils.toObject(afModes));
+        List<Integer> modesList = new ArrayList<Integer>();
+        for (int afMode : afModes) {
+            // Skip vendor-added AF modes
+            if (afMode > CameraCharacteristics.CONTROL_AF_MODE_EDOF) continue;
+            modesList.add(afMode);
+        }
+        afModes = new int[modesList.size()];
+        for (int i = 0; i < modesList.size(); i++) {
+            afModes[i] = modesList.get(i);
+        }
+
         if (isHardwareLevelLimitedOrBetter()) {
             // Some LEGACY mode devices do not support AF OFF
             checkTrueForKey(key, " All camera devices must support OFF mode",
@@ -1417,6 +1436,16 @@ public class StaticMetadata {
         return fpsRanges;
     }
 
+    public static String getAeModeName(int aeMode) {
+        return (aeMode >= AE_MODE_NAMES.length) ? String.format("VENDOR_AE_MODE_%d", aeMode) :
+            AE_MODE_NAMES[aeMode];
+    }
+
+    public static String getAfModeName(int afMode) {
+        return (afMode >= AF_MODE_NAMES.length) ? String.format("VENDOR_AF_MODE_%d", afMode) :
+            AF_MODE_NAMES[afMode];
+    }
+
     /**
      * Get the highest supported target FPS range.
      * Prioritizes maximizing the min FPS, then the max FPS without lowering min FPS.
index 2f0a411..2324593 100644 (file)
@@ -4,31 +4,35 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     tools:context="com.android.captiveportallogin.CaptivePortalLoginActivity"
-    tools:ignore="MergeRootFrame">
+    tools:ignore="MergeRootFrame" >
+
     <LinearLayout
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >
 
-    <TextView
-        android:id="@+id/url_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:textSize="20sp"
-        android:singleLine="true" />
+      <FrameLayout
+          android:layout_width="match_parent"
+          android:layout_height="4dp" >
 
-    <ProgressBar
-        android:id="@+id/progress_bar"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        style="?android:attr/progressBarStyleHorizontal" />
+        <!-- Eliminates ProgressBar padding by boxing it into a 4dp high container -->
+        <ProgressBar
+            android:id="@+id/progress_bar"
+            style="@android:style/Widget.Material.Light.ProgressBar.Horizontal"
+            android:indeterminate="false"
+            android:max="100"
+            android:progress="0"
+            android:layout_gravity="center"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content" />
+      </FrameLayout>
 
-    <WebView
-        android:id="@+id/webview"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_alignParentBottom="false"
-        android:layout_alignParentRight="false" />
+      <WebView
+          android:id="@+id/webview"
+          android:layout_width="match_parent"
+          android:layout_height="match_parent"
+          android:layout_alignParentBottom="false"
+          android:layout_alignParentRight="false" />
 
-</LinearLayout>
+    </LinearLayout>
 </FrameLayout>
index 4a99638..f6c2339 100644 (file)
@@ -4,7 +4,7 @@
         Base application theme, dependent on API level. This theme is replaced
         by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
     -->
-    <style name="AppBaseTheme" parent="@android:style/Theme.Material.Settings">
+    <style name="AppBaseTheme" parent="@android:style/Theme.DeviceDefault.Settings">
         <!--
             Theme customizations available in newer API levels can go in
             res/values-vXX/styles.xml, while customizations related to
@@ -15,8 +15,5 @@
     <!-- Application theme. -->
     <style name="AppTheme" parent="AppBaseTheme">
         <!-- All customizations that are NOT specific to a particular API-level can go here. -->
-        <!-- Setting's theme's accent color makes ProgressBar useless, reset back. -->
-        <item name="android:colorAccent">@*android:color/material_deep_teal_500</item>
     </style>
-
 </resources>
index c9fba95..582b660 100644 (file)
@@ -37,6 +37,7 @@ import android.util.Log;
 import android.util.TypedValue;
 import android.view.Menu;
 import android.view.MenuItem;
+import android.view.View;
 import android.webkit.SslErrorHandler;
 import android.webkit.WebChromeClient;
 import android.webkit.WebSettings;
@@ -57,6 +58,7 @@ import java.util.Random;
 public class CaptivePortalLoginActivity extends Activity {
     private static final String TAG = CaptivePortalLoginActivity.class.getSimpleName();
     private static final boolean DBG = true;
+    private static final boolean VDBG = false;
 
     private static final int SOCKET_TIMEOUT_MS = 10000;
 
@@ -97,8 +99,6 @@ public class CaptivePortalLoginActivity extends Activity {
         // setContentView initializes the WebView logic which in turn reads the system properties.
         setContentView(R.layout.activity_captive_portal_login);
 
-        getActionBar().setDisplayShowHomeEnabled(false);
-
         // Exit app if Network disappears.
         final NetworkCapabilities networkCapabilities = mCm.getNetworkCapabilities(mNetwork);
         if (networkCapabilities == null) {
@@ -117,9 +117,14 @@ public class CaptivePortalLoginActivity extends Activity {
         }
         mCm.registerNetworkCallback(builder.build(), mNetworkCallback);
 
-        final WebView myWebView = findViewById(R.id.webview);
-        myWebView.clearCache(true);
-        WebSettings webSettings = myWebView.getSettings();
+        getActionBar().setDisplayShowHomeEnabled(false);
+        getActionBar().setElevation(0); // remove shadow
+        getActionBar().setTitle(getHeaderTitle());
+        getActionBar().setSubtitle("");
+
+        final WebView webview = getWebview();
+        webview.clearCache(true);
+        WebSettings webSettings = webview.getSettings();
         webSettings.setJavaScriptEnabled(true);
         webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_COMPATIBILITY_MODE);
         webSettings.setUseWideViewPort(true);
@@ -128,11 +133,11 @@ public class CaptivePortalLoginActivity extends Activity {
         webSettings.setBuiltInZoomControls(true);
         webSettings.setDisplayZoomControls(false);
         mWebViewClient = new MyWebViewClient();
-        myWebView.setWebViewClient(mWebViewClient);
-        myWebView.setWebChromeClient(new MyWebChromeClient());
+        webview.setWebViewClient(mWebViewClient);
+        webview.setWebChromeClient(new MyWebChromeClient());
         // Start initial page load so WebView finishes loading proxy settings.
         // Actual load of mUrl is initiated by MyWebViewClient.
-        myWebView.loadData("", "text/html", null);
+        webview.loadData("", "text/html", null);
     }
 
     // Find WebView's proxy BroadcastReceiver and prompt it to read proxy system properties.
@@ -251,10 +256,14 @@ public class CaptivePortalLoginActivity extends Activity {
         if (url == null) {
             url = mCm.getCaptivePortalServerUrl();
         }
+        return makeURL(url);
+    }
+
+    private static URL makeURL(String url) {
         try {
             return new URL(url);
         } catch (MalformedURLException e) {
-            Log.e(TAG, "Invalid captive portal URL " + url);
+            Log.e(TAG, "Invalid URL " + url);
         }
         return null;
     }
@@ -303,6 +312,7 @@ public class CaptivePortalLoginActivity extends Activity {
 
     private class MyWebViewClient extends WebViewClient {
         private static final String INTERNAL_ASSETS = "file:///android_asset/";
+
         private final String mBrowserBailOutToken = Long.toString(new Random().nextLong());
         // How many Android device-independent-pixels per scaled-pixel
         // dp/sp = (px/sp) / (px/dp) = (1/sp) / (1/dp)
@@ -331,15 +341,16 @@ public class CaptivePortalLoginActivity extends Activity {
             // For internally generated pages, leave URL bar listing prior URL as this is the URL
             // the page refers to.
             if (!url.startsWith(INTERNAL_ASSETS)) {
-                final TextView myUrlBar = findViewById(R.id.url_bar);
-                myUrlBar.setText(url);
+                getActionBar().setSubtitle(getHeaderSubtitle(url));
             }
+            getProgressBar().setVisibility(View.VISIBLE);
             testForCaptivePortal();
         }
 
         @Override
         public void onPageFinished(WebView view, String url) {
             mPagesLoaded++;
+            getProgressBar().setVisibility(View.INVISIBLE);
             if (mPagesLoaded == 1) {
                 // Now that WebView has loaded at least one page we know it has read in the proxy
                 // settings.  Now prompt the WebView read the Network-specific proxy settings.
@@ -354,12 +365,6 @@ public class CaptivePortalLoginActivity extends Activity {
             testForCaptivePortal();
         }
 
-        // Convert Android device-independent-pixels (dp) to HTML size.
-        private String dp(int dp) {
-            // HTML px's are scaled just like dp's, so just add "px" suffix.
-            return Integer.toString(dp) + "px";
-        }
-
         // Convert Android scaled-pixels (sp) to HTML size.
         private String sp(int sp) {
             // Convert sp to dp's.
@@ -367,25 +372,11 @@ public class CaptivePortalLoginActivity extends Activity {
             // Apply a scale factor to make things look right.
             dp *= 1.3;
             // Convert dp's to HTML size.
-            return dp((int)dp);
+            // HTML px's are scaled just like dp's, so just add "px" suffix.
+            return Integer.toString((int)dp) + "px";
         }
 
         // A web page consisting of a large broken lock icon to indicate SSL failure.
-        private final String SSL_ERROR_HTML = "<html><head><style>" +
-                "body { margin-left:" + dp(48) + "; margin-right:" + dp(48) + "; " +
-                        "margin-top:" + dp(96) + "; background-color:#fafafa; }" +
-                "img { width:" + dp(48) + "; height:" + dp(48) + "; }" +
-                "div.warn { font-size:" + sp(16) + "; margin-top:" + dp(16) + "; " +
-                "           opacity:0.87; line-height:1.28; }" +
-                "div.example { font-size:" + sp(14) + "; margin-top:" + dp(16) + "; " +
-                "              opacity:0.54; line-height:1.21905; }" +
-                "a { font-size:" + sp(14) + "; text-decoration:none; text-transform:uppercase; " +
-                "    margin-top:" + dp(24) + "; display:inline-block; color:#4285F4; " +
-                "    height:" + dp(48) + "; font-weight:bold; }" +
-                "</style></head><body><p><img src=quantum_ic_warning_amber_96.png><br>" +
-                "<div class=warn>%s</div>" +
-                "<div class=example>%s</div>" +
-                "<a href=%s>%s</a></body></html>";
 
         @Override
         public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
@@ -393,10 +384,63 @@ public class CaptivePortalLoginActivity extends Activity {
                     // Only show host to avoid leaking private info.
                     Uri.parse(error.getUrl()).getHost() + " certificate: " +
                     error.getCertificate() + "); displaying SSL warning.");
-            final String html = String.format(SSL_ERROR_HTML, getString(R.string.ssl_error_warning),
-                    getString(R.string.ssl_error_example), mBrowserBailOutToken,
-                    getString(R.string.ssl_error_continue));
-            view.loadDataWithBaseURL(INTERNAL_ASSETS, html, "text/HTML", "UTF-8", null);
+            final String sslErrorPage = makeSslErrorPage();
+            if (VDBG) {
+                Log.d(TAG, sslErrorPage);
+            }
+            view.loadDataWithBaseURL(INTERNAL_ASSETS, sslErrorPage, "text/HTML", "UTF-8", null);
+        }
+
+        private String makeSslErrorPage() {
+            final String warningMsg = getString(R.string.ssl_error_warning);
+            final String exampleMsg = getString(R.string.ssl_error_example);
+            final String continueMsg = getString(R.string.ssl_error_continue);
+            return String.join("\n",
+                    "<html>",
+                    "<head>",
+                    "  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">",
+                    "  <style>",
+                    "    body {",
+                    "      background-color:#fafafa;",
+                    "      margin:auto;",
+                    "      width:80%;",
+                    "      margin-top: 96px",
+                    "    }",
+                    "    img {",
+                    "      height:48px;",
+                    "      width:48px;",
+                    "    }",
+                    "    div.warn {",
+                    "      font-size:" + sp(16) + ";",
+                    "      line-height:1.28;",
+                    "      margin-top:16px;",
+                    "      opacity:0.87;",
+                    "    }",
+                    "    div.example {",
+                    "      font-size:" + sp(14) + ";",
+                    "      line-height:1.21905;",
+                    "      margin-top:16px;",
+                    "      opacity:0.54;",
+                    "    }",
+                    "    a {",
+                    "      color:#4285F4;",
+                    "      display:inline-block;",
+                    "      font-size:" + sp(14) + ";",
+                    "      font-weight:bold;",
+                    "      height:48px;",
+                    "      margin-top:24px;",
+                    "      text-decoration:none;",
+                    "      text-transform:uppercase;",
+                    "    }",
+                    "  </style>",
+                    "</head>",
+                    "<body>",
+                    "  <p><img src=quantum_ic_warning_amber_96.png><br>",
+                    "  <div class=warn>" + warningMsg + "</div>",
+                    "  <div class=example>" + exampleMsg + "</div>",
+                    "  <a href=" + mBrowserBailOutToken + ">" + continueMsg + "</a>",
+                    "</body>",
+                    "</html>");
         }
 
         @Override
@@ -412,8 +456,31 @@ public class CaptivePortalLoginActivity extends Activity {
     private class MyWebChromeClient extends WebChromeClient {
         @Override
         public void onProgressChanged(WebView view, int newProgress) {
-            final ProgressBar myProgressBar = findViewById(R.id.progress_bar);
-            myProgressBar.setProgress(newProgress);
+            getProgressBar().setProgress(newProgress);
+        }
+    }
+
+    private ProgressBar getProgressBar() {
+        return findViewById(R.id.progress_bar);
+    }
+
+    private WebView getWebview() {
+        return findViewById(R.id.webview);
+    }
+
+    private String getHeaderTitle() {
+        return getString(R.string.action_bar_label);
+    }
+
+    private String getHeaderSubtitle(String urlString) {
+        URL url = makeURL(urlString);
+        if (url == null) {
+            return urlString;
+        }
+        final String https = "https";
+        if (https.equals(url.getProtocol())) {
+            return https + "://" + url.getHost();
         }
+        return url.getHost();
     }
 }
index 151d1ee..da66814 100644 (file)
@@ -76,7 +76,7 @@
             android:id="@+id/bottom_label_space"
             android:layout_width="@dimen/usage_graph_labels_width"
             android:layout_height="wrap_content"/>
-        <LinearLayout
+        <com.android.settingslib.graph.BottomLabelLayout
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
                      layout="@layout/usage_side_label" />
 
             <Space
-                android:layout_width="0dp"
+                android:id="@+id/spacer"
+                android:layout_width="40dp"
                 android:layout_height="wrap_content"
                 android:layout_weight="1" />
 
             <include android:id="@+id/label_end"
                      layout="@layout/usage_side_label" />
-        </LinearLayout>
+        </com.android.settingslib.graph.BottomLabelLayout>
     </LinearLayout>
 
 </LinearLayout>
index 4f52812..337a8eb 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Agtergrondproses-limiet"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Wys alle ANRe"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Wys Program reageer nie-dialoog vir agtergrond programme"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Wys kennisgewingkanaalwaarskuwings"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Wys waarskuwing op skerm wanneer \'n program \'n kennisgewing sonder \'n geldige kanaal plaas"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Programme verplig ekstern toegelaat"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Maak dat enige program in eksterne berging geskryf kan word, ongeag manifeswaardes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Verplig verstelbare groottes vir aktiwiteite"</string>
index 465e253..645aa49 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"የዳራ አሂድ ወሰን"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ሁሉንም ANRs አሳይ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ለዳራ መተግበሪያዎች ምላሽ የማይሰጥ መገናኛ ትግበራ አሳይ"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"የማሳወቂያ ሰርጥ ማስጠንቀቂያዎችን አሳይ"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"አንድ መተግበሪያ የሚሰራ ሰርጥ ሳይኖረው ማሳወቂያ ሲለጥፍ በማያ ገጽ-ላይ ማስጠንቀቂያን ያሳያል"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"በውጫዊ ላይ ሃይል ይፈቀዳል"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"የዝርዝር ሰነዶች እሴቶች ግምት ውስጥ ሳያስገባ ማንኛውም መተግበሪያ ወደ ውጫዊ ማከማቻው ለመጻፍ ብቁ ያደርጋል"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"እንቅስቃሴዎች ዳግመኛ እንዲመጣጠኑ አስገድድ"</string>
index a4ee8fd..897d473 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"حد العمليات بالخلفية"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏عرض جميع رسائل ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"عرض مربع الحوار \"التطبيق لا يستجيب\" مع تطبيقات الخلفية"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"عرض تحذيرات قناة الإشعار"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"لعرض تحذير على الشاشة عند نشر تطبيق ما لإشعار بدون قناة صالحة"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"فرض السماح للتطبيقات على الخارجي"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"تأهيل أي تطبيق بحيث تتم كتابته على وحدة تخزين خارجية، بغض النظر عن قيم البيان"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"فرض إمكانية تغيير على الأنشطة"</string>
index 690e589..4144593 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fon prosesi limiti"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Bütün ANRları göstər"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Arxa tətbiqlər dialoquna cavab verməyən tətbiqi göstər"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Xəbərdarlıqları göstərin"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Bildiriş paylaşıldıqda xəbərdarlıq göstərir"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tətbiqlərə xaricdən məcburi icazə"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Seçilmiş hər hansı tətbiqi bəyannamə dəyərlərindən aslı olmayaraq xarici yaddaşa yazılabilən edir."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Ölçü dəyişdirmək üçün məcburi fəaliyyətlər"</string>
index e59dac6..73f0de0 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje pozadinskih procesa"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaži dijalog Aplikacija ne reaguje za aplikacije u pozadini"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Prikazuj upozorenja zbog kanala za obaveštenja"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Prikazuje upozorenje na ekranu kada aplikacija postavi obaveštenje bez važećeg kanala"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Prinudno dozvoli aplikacije u spoljnoj"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava upisivanje svih aplikacija u spoljnu memoriju, bez obzira na vrednosti manifesta"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Prinudno omogući promenu veličine aktivnosti"</string>
index b1ec867..2e8aa9f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ліміт фонавага працэсу"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Паказаць усе ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Паказаць дыялогавае акно \"Праграма не адказвае\" для фонавых прыкладанняў"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Паказваць папярэджанні канала апавяшчэннаў"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Паказвае папярэджанне на экране, калі праграма публікуе апавяшчэнне без сапраўднага канала"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Прымусова дазволіць праграмы на вонкавым сховішчы"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Робіць любую праграму даступнай для запісу на вонкавае сховішча, незалежна ад значэнняў маніфеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Зрабіць вокны дзеянняў даступнымі для змены памеру"</string>
index a8039eb..4e24cec 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Лимит за фонови процеси"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Всички нереагиращи прил."</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Диалог. прозорец „НП“ за приложения на заден план"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Предупрежд. за канала за известия"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Показва се предупреждение, когато приложение публикува известие без валиден канал"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Външно хран.: Принуд. разрешаване на приложенията"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Прави всички приложения да отговарят на условията да бъдат записвани във външното хранилище независимо от стойностите в манифеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Възможност за преоразмеряване на активностите"</string>
index 3f0de25..6fb79cb 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"পশ্চাদপট প্রক্রিয়ার সীমা"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"সব ANR দেখান"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"পশ্চাদপটের অ্যাপ্লিকেশানগুলির জন্য অ্যাপ্লিকেশান কোনো প্রতিক্রিয়া দিচ্ছে না এমন কথোপকথন দেখান"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"বিজ্ঞপ্তির সতর্কতা দেখুন"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"অ্যাপ সঠিক চ্যানেল ছাড়া বিজ্ঞপ্তি দেখালে সতর্ক করে"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"বহিরাগততে বলপূর্বক মঞ্জুরি"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ম্যানিফেস্ট মানগুলি নির্বিশেষে যেকোনো অ্যাপ্লিকেশানকে বাহ্যিক সঞ্চয়স্থানে লেখার উপযুক্ত বানায়"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"আকার পরিবর্তনযোগ্য করার জন্য ক্রিয়াকলাপগুলিকে জোর করুন"</string>
index f91a8a8..be03695 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje procesa u pozadini"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prik. dijalog Aplikacija ne reagira za apl. u poz."</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Prikaz upozorenja na obavještenju o kanalu"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Prikaz upozorenja ekranu kada aplikacija pošalje obavještenje bez važećeg kanala."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Nametni aplikacije na vanjskoj pohrani"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Omogućava da svaka aplikacija bude pogodna za upisivanje na vanjsku pohranu, bez obzira na prikazane vrijednosti"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni aktivnostima mijenjanje veličina"</string>
index 99c5d37..a56d994 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límita processos en segon pla"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tots els errors sense resposta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que una aplicació en segon pla no respon"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Avisos del canal de notificacions"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Mostra un avís a la pantalla quan una app publica una notificació sense canal vàlid"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Força permís d\'aplicacions a l\'emmagatzem. extern"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permet que qualsevol aplicació es pugui escriure en un dispositiu d’emmagatzematge extern, independentment dels valors definits"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Força l\'ajust de la mida de les activitats"</string>
index 7b3fb86..36b3720 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Omezení procesů na pozadí"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Zobrazit všechny ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovat dialog „Aplikace neodpovídá“ pro aplikace na pozadí"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Zobrazovat upozornění ohledně kanálu oznámení"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Když aplikace odešle oznámení bez platného kanálu, na obrazovce se zobrazí upozornění"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vynutit povolení aplikací na externím úložišti"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Každou aplikaci bude možné zapsat do externího úložiště, bez ohledu na hodnoty manifestu"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vynutit možnost změny velikosti aktivit"</string>
index 6ccf45b..a549082 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Grænse for baggrundsprocesser"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Vis alle \"Appen svarer ikke\""</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis \"Appen svarer ikke\" for baggrundsapps"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Vis advarsler om underretningskanal"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Viser en advarsel, når en app sender en underretning uden en gyldig kanal"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Gennemtving tilladelse til eksternt lager"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gør det muligt at overføre enhver app til et eksternt lager uafhængigt af manifestværdier"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til at kunne tilpasses"</string>
index db58ab2..af31792 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Hintergrundprozesslimit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Alle ANRS anzeigen"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Dialogfeld \"App antwortet nicht\" für Hintergrund-Apps anzeigen"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Warnungen für Benachrichtigungskanäle einblenden"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Blendet Warnungen auf dem Display ein, wenn eine App eine Benachrichtigung ohne gültigen Kanal sendet"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Externe Speichernutzung von Apps erlauben"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ermöglicht es jeder qualifizierten App, Daten auf externen Speicher zu schreiben, unabhängig von den Manifestwerten"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Anpassen der Größe von Aktivitäten erzwingen"</string>
index cde2066..43f0f2c 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Όριο διεργασ. παρασκηνίου"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Εμφάνιση όλων των ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Εμφ.του παραθ. \"Η εφαρμ.δεν αποκρ.\" για εφ.παρασκ."</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Εμφάνιση προειδοπ. καναλιού ειδοπ."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Εμφανίζει προειδοποίηση όταν μια εφαρμογή δημοσιεύει ειδοποίηση χωρίς έγκυρο κανάλι"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Να επιτρέπονται υποχρεωτικά εφαρμογές σε εξωτ.συσ."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Κάνει κάθε εφαρμογή κατάλληλη για εγγραφή σε εξωτερικό αποθηκευτικό χώρο, ανεξάρτητα από τις τιμές του μανιφέστου"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Αναγκαστική δυνατότητα αλλαγής μεγέθους δραστηριοτήτων"</string>
index b252545..93e1aa8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Show notification channel warnings"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Displays on-screen warning when an app posts a notification without a valid channel"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
index b252545..93e1aa8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Show notification channel warnings"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Displays on-screen warning when an app posts a notification without a valid channel"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
index b252545..93e1aa8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Background process limit"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Show all ANRs"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Show App Not Responding dialogue for background apps"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Show notification channel warnings"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Displays on-screen warning when an app posts a notification without a valid channel"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Force allow apps on external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Makes any app eligible to be written to external storage, regardless of manifest values"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Force activities to be re-sizable"</string>
index 03d8cea..16d34a2 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límite de procesos en segundo plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar diálogo cuando las aplic. en 2do plano no responden"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Alertas de notificaciones"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"App que publica notificación sin canal válido"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permisos en almacenamiento externo"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Cualquier app puede escribirse en un almacenamiento externo, sin importar los valores del manifiesto"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar actividades para que cambien de tamaño"</string>
index 00dbf9c..c51854d 100644 (file)
     <string name="choose_profile" msgid="6921016979430278661">"Seleccionar perfil"</string>
     <string name="category_personal" msgid="1299663247844969448">"Personal"</string>
     <string name="category_work" msgid="8699184680584175622">"Trabajo"</string>
-    <string name="development_settings_title" msgid="215179176067683667">"Opciones de desarrollo"</string>
+    <string name="development_settings_title" msgid="215179176067683667">"Opciones para desarrolladores"</string>
     <string name="development_settings_enable" msgid="542530994778109538">"Habilitar opciones para desarrolladores"</string>
     <string name="development_settings_summary" msgid="1815795401632854041">"Establecer opciones de desarrollo de aplicaciones"</string>
     <string name="development_settings_not_available" msgid="4308569041701535607">"Las opciones de desarrollador no están disponibles para este usuario"</string>
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límitar procesos en segundo plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Errores sin respuesta"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informar de que una aplicación en segundo plano no responde"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Ver advertencias canal notificaciones"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Muestra advertencia en pantalla cuando app publica notificación sin canal válido"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicaciones de forma externa"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hace que cualquier aplicación se pueda escribir en un dispositivo de almacenamiento externo, independientemente de los valores definidos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar el ajuste de tamaño de las actividades"</string>
index 4d0f5f6..b1a40a8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Taustaprotsesside piir"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Näita kõiki ANR-e"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Kuva taustarakendustele dial. Rakendus ei reageeri"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Kuva märguandekan. hoiat."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Esitab ekraanil hoiatuse, kui rakendus postitab kehtiva kanalita märguande"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Luba rakendused välises salvestusruumis"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lubab mis tahes rakendusi kirjutada välisesse salvestusruumi manifesti väärtustest olenemata"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Muuda tegevuste suurused muudetavaks"</string>
index 6ed2d75..2b6d964 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Atzeko planoko prozesuen muga"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Erakutsi ANR guztiak"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"\"Erantzunik ez\" mezua atz. planoko aplikazioetarako"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Erakutsi jakinarazpenen kanaleko abisuak"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Bistaratu abisuak aplikazioek baliozko kanalik gabeko jakinarazpenak argitaratzean"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Behartu aplikazioak onartzea kanpoko biltegian"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikazioek kanpoko memorian idatz dezakete, manifestuaren balioak kontuan izan gabe"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Behartu jardueren tamaina doitu ahal izatea"</string>
index bb10b38..ff76b60 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"محدودیت پردازش در پس‌زمینه"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏نمایش تمام ANRها"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"نمایش گفتگوی \"برنامه پاسخ نمی‌دهد\" برای برنامه‌های پس‌زمینه"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"نمایش هشدارهای کانال اعلان"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"هنگامی که برنامه‌ای بدون وجود کانالی معتبر، اعلانی پست می‌کند، هشدار روی صفحه‌ای نمایش می‌دهد"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"اجازه اجباری به برنامه‌های دستگاه ذخیره خارجی"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"بدون توجه به مقادیر مانیفست، هر برنامه‌ای را برای نوشتن در حافظه خارجی واجد شرایط می‌کند"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"اجبار فعالیت‌ها به قابل تغییر اندازه بودن"</string>
index 7dd2e58..b675992 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Taustaprosessi"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Näytä kaikki ANR:t"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Näytä Sovellus ei vastaa -ikkuna taustasovell."</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Näytä ilmoituskanavan varoitukset"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Näyttää varoituksen, kun sovellus julkaisee ilmoituksen ilman kelvollista kanavaa."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Salli aina ulkoinen tallennus"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Mahdollistaa sovelluksen tietojen tallentamisen ulkoiseen tallennustilaan luetteloarvoista riippumatta."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Pakota kaikki toiminnot hyväksymään koon muutos"</string>
index 5641d7c..7488df7 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite processus arr.-plan"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages «L\'application ne répond pas»"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher « L\'application ne répond plus » pour applis en arrière-plan"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Affich. avertiss. canal notification"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Afficher avertiss. à l\'écran quand une app présente une notific. sans canal valide"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer l\'autor. d\'applis sur stockage externe"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Rend possible l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer les activités à être redimensionnables"</string>
index b0b532f..c6562e2 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite processus arr.-plan"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Afficher tous les messages ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Afficher \"L\'application ne répond plus\" pour applis en arrière-plan"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Voir avertissements liés aux canaux notification"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Affiche avertissement lorsqu\'une application publie notification sans canal valide"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forcer disponibilité stockage externe pour applis"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Rend possible l\'enregistrement de toute application sur un espace de stockage externe, indépendamment des valeurs du fichier manifeste."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forcer possibilité de redimensionner les activités"</string>
index 81a1ca9..2fc72cb 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Límite proceso 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Informa que aplicación segundo plano non responde"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos de notificacións"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Mostra avisos cando unha aplicación publica notificacións sen unha canle válida"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forzar permiso de aplicacións de forma externa"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Permite que calquera aplicación apta se poida escribir nun almacenamento externo, independentemente dos valores expresados"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forzar o axuste do tamaño das actividades"</string>
index e4e1507..ed1a382 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"પૃષ્ઠભૂમિ પ્રક્રિયા સીમા"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"બધા ANR બતાવો"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"પૃષ્ઠભૂમિ ઍપ્લિકેશનો માટે ઍપ્લિકેશન પ્રતિસાદ આપતી નથી સંવાદ બતાવો"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"સૂચના ચૅનલની ચેતવણી બતાવો"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ઍપ્લિકેશન માન્ય ચૅનલ વિના સૂચના પોસ્ટ કરે તો સ્ક્રીન પર ચેતવણી દેખાય છે"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"બાહ્ય પર એપ્લિકેશનોને મંજૂરી આપવાની ફરજ પાડો"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"મેનિફેસ્ટ મૂલ્યોને ધ્યાનમાં લીધા સિવાય, કોઈપણ ઍપ્લિકેશનને બાહ્ય સ્ટોરેજ પર લખાવા માટે લાયક બનાવે છે"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"પ્રવૃત્તિઓને ફરીથી કદ યોગ્ય થવા માટે ફરજ પાડો"</string>
index 936e775..a4a75c5 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"पृष्ठभूमि प्रक्रिया सीमा"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"सभी ANR दिखाएं"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि ऐप्स के लिए ऐप्स प्रतिसाद नहीं दे रहा डॉयलॉग दिखाएं"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"नोटिफ़िकेशन चैनल चेतावनी दिखाएं"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ऐप्लिकेशन मान्य चैनल के बिना नोटिफ़िकेशन पोस्ट करे तो स्क्रीन पर चेतावनी दिखाएं"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ऐप्स को बाहरी मेमोरी पर बाध्‍य करें"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"इससे कोई भी ऐप्लिकेशन, मेनिफेस्ट मानों को अनदेखा करके, बाहरी मेमोरी पर लिखने योग्य बन जाता है"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"आकार बदले जाने के लिए गतिविधियों को बाध्य करें"</string>
index be4ac19..f4a7497 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ograničenje pozadinskog procesa"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Prikaži sve ANR-ove"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz dijaloga o pozad. aplik. koja ne odgovara"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Prikaži upozorenja kanala obavijesti"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Prikazuje upozorenje na zaslonu kada aplikacija objavi obavijest bez važećeg kanala"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Prisilno dopusti aplikacije u vanjskoj pohrani"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Aplikacije se mogu zapisivati u vanjsku pohranu neovisno o vrijednostima manifesta"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Nametni mogućnost promjene veličine za aktivnosti"</string>
index b791178..f800782 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Háttérfolyamat-korlátozás"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Összes ANR mutatása"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Az Alkalmazás nem válaszol ablak megjelenítése"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Értesítő csatorna figyelmeztetései"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Figyelmeztet, ha egy alkalmazás érvényes csatorna nélkül küld értesítést"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Külső tárhely alkalmazásainak engedélyezése"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Lehetővé teszi bármely alkalmazás külső tárhelyre való írását a jegyzékértékektől függetlenül"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tevékenységek átméretezésének kényszerítése"</string>
index da34ccc..7643240 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Հետնաշերտի գործընթացի սահմանաչափ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Ցույց տալ բոլոր ANR-երը"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Ցուցադրել այն ծրագիրը, որը չի արձագանքում երկխոսությունը հետնաշերտի ծրագրերի համար"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Ցուցադրել ծանուցումների ալիքի զգուշացումները"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Էկրանին ցուցադրվում է զգուշացում, երբ որևէ հավելված փակցնում է ծանուցում առանց վավեր ալիքի"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Միշտ թույլատրել ծրագրեր արտաքին պահեստում"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Թույլ է տալիս ցանկացած հավելված պահել արտաքին սարքում՝ մանիֆեստի արժեքներից անկախ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Ստիպել, որ ակտիվությունների չափերը լինեն փոփոխելի"</string>
index 13407fe..3aea66b 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Batas proses latar blkg"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tampilkan semua ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Tmplkn dialog Apl Tidak Merespons utk apl ltr blkg"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Menampilkan peringatan channel notifikasi"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Menampilkan peringatan di layar saat aplikasi memposting notifikasi tanpa channel yang valid"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Paksa izinkan aplikasi di eksternal"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Membuat semua aplikasi dapat ditulis ke penyimpanan eksternal, terlepas dari nilai manifes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktivitas agar ukurannya dapat diubah"</string>
index 6457e71..9e3eb22 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Takmörkun á bakgrunnsvinnslum"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Öll forrit sem svara ekki"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Sýna „Forrit svarar ekki“ fyrir bakgrunnsforrit"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Sýna viðvaranir tilkynningarásar"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Birtir viðvörun á skjánum þegar forrit birtir tilkynningu án gildrar rásar"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Þvinga fram leyfi forrita í ytri geymslu"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Gerir öll forrit skrifanleg í ytra geymslurými, óháð gildum í upplýsingaskrá"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Þvinga breytanlega stærð virkni"</string>
index 5182730..5681b76 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite processi background"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostra tutti errori ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostra finestra ANR per applicazioni in background"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostra avvisi canale di notifica"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Viene mostrato un avviso sullo schermo quando un\'app pubblica una notifica senza un canale valido"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forza autorizzazione app su memoria esterna"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Consente l\'installazione di qualsiasi app su memoria esterna, indipendentemente dai valori manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Imponi formato modificabile alle attività"</string>
index 249fac4..d0a8d58 100644 (file)
     <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">"×\92×\93×\9c×\99 ×\9e×\90×\92ר ×©×\9c ×\99×\95צר ×\99×\95×\9e×\9f"</string>
+    <string name="select_logd_size_title" msgid="7433137108348553508">"×\92×\93×\9c×\99 ×\9e×\90×\92ר ×©×\9c ×\99×\95×\9e×\9f ×¨×\99ש×\95×\9d"</string>
     <string name="select_logd_size_dialog_title" msgid="1206769310236476760">"בחר גדלים של יוצר יומן לכל מאגר יומן"</string>
     <string name="dev_logpersist_clear_warning_title" msgid="684806692440237967">"האם למחוק את אחסון המתעד המתמיד?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="2256582531342994562">"כשאנחנו כבר לא מבצעים מעקב באמצעות המתעד המתמיד, אנחנו נדרשים למחוק את נתוני המתעד המקומי במכשיר."</string>
-    <string name="select_logpersist_title" msgid="7530031344550073166">"×\90×\97ס×\95×\9f × ×ª×\95× ×\99 ×\9eתע×\93 ×\9eת×\9e×\99ד במכשיר"</string>
+    <string name="select_logpersist_title" msgid="7530031344550073166">"×\90×\97ס×\95×\9f ×\9eת×\9e×\99×\93 ×©×\9c × ×ª×\95× ×\99 ×ª×\99×¢×\95ד במכשיר"</string>
     <string name="select_logpersist_dialog_title" msgid="4003400579973269060">"בחר מאגר נתונים זמני ליומן לשם אחסון מתמיד במכשיר"</string>
     <string name="select_usb_configuration_title" msgid="2649938511506971843">"‏בחר תצורת USB"</string>
     <string name="select_usb_configuration_dialog_title" msgid="6385564442851599963">"‏בחר תצורת USB"</string>
     <string name="app_process_limit_title" msgid="4280600650253107163">"מגבלה של תהליכים ברקע"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏הצג את כל פריטי ה-ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"הצג תיבת דו-שיח של \'אפליקציה לא מגיבה\' עבור אפליקציות שפועלות ברקע"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"אזהרות לגבי ערוץ הודעות"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"הצגת אזהרה כשאפליקציה שולחת הודעה ללא ערוץ חוקי"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"אילוץ הרשאת אפליקציות באחסון חיצוני"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"מאפשר כתיבה של כל אפליקציה באחסון חיצוני, ללא התחשבות בערכי המניפסט"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"אלץ יכולת קביעת גודל של הפעילויות"</string>
index 8837e97..403677f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"バックグラウンドプロセスの上限"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"すべてのANRを表示"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"バックグラウンドアプリが応答しない場合に通知する"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"通知チャネルの警告を表示"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"アプリから有効なチャネルのない通知が投稿されたときに画面上に警告を表示します"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"外部ストレージへのアプリの書き込みを許可"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"マニフェストの値に関係なく、すべてのアプリを外部ストレージに書き込めるようになります"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"アクティビティをサイズ変更可能にする"</string>
index 81416a0..30492ce 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"ფონური პროცესების ლიმიტი"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ყველა ANR-ის ჩვენება"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"შეტყობინების ჩვენება, როცა ფონური აპლიკაცია არ პასუხობს"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"შეტყობინებათა არხის გაფრთხილებების ჩვენება"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ეკრანზე აჩვენებს გაფრთხილებას, როცა აპი შეტყობინებას სწორი არხის გარეშე განათავსებს"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"აპების დაშვება გარე მეხსიერებაში"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"აპები ჩაიწერება გარე მეხსიერებაზე აღწერის ფაილების მნიშვნელობების მიუხედავად"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ზომაცვლადი აქტივობების იძულება"</string>
index 66b4a0e..e624348 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Фондық үрдіс шектеуі"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Барлық ANR (қолданба жауап бермеді) хабарларын көрсетіңіз"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондық қолданбалардың жауап бермегенін көрсету"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Хабарландыру арнасының ескертулерін көрсету"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Қолданба жарамсыз арна арқылы хабарландыру жариялағанда, экрандық ескертуді көрсетеді"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Сыртқыда қолданбаларға мәжбүрлеп рұқсат ету"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест мәндеріне қарамастан кез келген қолданбаны сыртқы жадқа жазуға жарамды етеді"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Әрекеттерді өлшемін өзгертуге болатын етуге мәжбүрлеу"</string>
index 1adc432..5498ef3 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"ដែន​កំណត់​ដំណើរការ​ក្នុង​ផ្ទៃ​ខាង​ក្រោយ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"បង្ហាញ ANRs ទាំងអស់"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"បង្ហាញ​ប្រអប់​កម្មវិធី​មិន​ឆ្លើយតប​សម្រាប់​កម្មវិធី​ផ្ទៃ​ខាង​ក្រោយ"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"បង្ហាញការព្រមានអំពីបណ្តាញជូនដំណឹង"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"បង្ហាញការព្រមាននៅលើអេក្រង់ នៅពេលកម្មវិធីបង្ហោះការជូនដំណឹងដោយមិនមានបណ្តាញត្រឹមត្រូវ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"បង្ខំឲ្យអនុញ្ញាតកម្មវិធីលើឧបករណ៍ផ្ទុកខាងក្រៅ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ធ្វើឲ្យកម្មវិធីទាំងឡាយមានសិទ្ធិសរសេរទៅកាន់ឧបករណ៍ផ្ទុកខាងក្រៅ ដោយមិនគិតពីតម្លៃជាក់លាក់"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"បង្ខំឲ្យសកម្មភាពអាចប្តូរទំហំបាន"</string>
index c545da7..ab2235a 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"ಹಿನ್ನೆಲೆ ಪ್ರಕ್ರಿಯೆ ಮಿತಿ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ಎಲ್ಲ ANR ಗಳನ್ನು ತೋರಿಸು"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ಹಿನ್ನೆಲೆ ಅಪ್ಲಿಕೇಶನ್‌ಗಳಿಗಾಗಿ ಅಪ್ಲಿಕೇಶನ್ ಪ್ರತಿಕ್ರಿಯಿಸುತ್ತಿಲ್ಲ ಎಂಬ ಸಂಭಾಷಣೆ ತೋರಿಸು"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ಅಧಿಸೂಚನೆ ಎಚ್ಚರಿಕೆ ತೋರಿಸಿ"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ಅಮಾನ್ಯ ಚಾನಲ್ ಅಧಿಸೂಚನೆಗಾಗಿ ಪರದೆಯಲ್ಲಿ ಎಚ್ಚರಿಕೆ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ಬಾಹ್ಯವಾಗಿ ಅಪ್ಲಿಕೇಶನ್‌ಗಳನ್ನು ಒತ್ತಾಯವಾಗಿ ಅನುಮತಿಸಿ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ಮ್ಯಾನಿಫೆಸ್ಟ್ ಮೌಲ್ಯಗಳು ಯಾವುದೇ ಆಗಿದ್ದರೂ, ಬಾಹ್ಯ ಸಂಗ್ರಹಣೆಗೆ ಬರೆಯಲು ಯಾವುದೇ ಅಪ್ಲಿಕೇಶನ್‌ ಅನ್ನು ಅರ್ಹಗೊಳಿಸುತ್ತದೆ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ಚಟುವಟಿಕೆಗಳನ್ನು ಮರುಗಾತ್ರಗೊಳಿಸುವಂತೆ ಒತ್ತಾಯ ಮಾಡಿ"</string>
index bbaeed7..3369a26 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"백그라운드 프로세스 수 제한"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"모든 ANR 보기"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"백그라운드 앱에 대해 앱 응답 없음 대화상자 표시"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"알림 채널 경고 표시"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"앱에서 유효한 채널 없이 알림을 게시하면 화면에 경고가 표시됩니다."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"외부에서 앱 강제 허용"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"매니페스트 값과 관계없이 모든 앱이 외부 저장소에 작성되도록 허용"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"활동의 크기가 조정 가능하도록 설정"</string>
index 66f3769..9b0a4d8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Фондогу процесстер чеги"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Бардык ANR\'лерди көрсөтүү"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Фондогу колдонмолорго Колдонмо Жооп Бербейт деп көрсөтүү"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Эскертме каналынын эскертүүлөрүн көрсөтүү"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Колдонмодон жарактуу каналсыз эскертме жайгаштырылганда, экрандан эскертүү көрсөтүлөт"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Тышкы сактагычка сактоого уруксат берүү"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест маанилерине карабастан бардык колдонмолорду тышкы сактагычка сактоого уруксат берет"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Аракеттердин өлчөмүн өзгөртүүнү мажбурлоо"</string>
index c909cbb..aacee8b 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"ການຈຳກັດໂປຣເຊສໃນພື້ນຫຼັງ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ສະ​ແດງ ANRs ທັງ​ຫມົດ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ສະແດງໜ້າຈໍແອັບຯທີ່ບໍ່ຕອບສະໜອງສຳລັບແອັບຯພື້ນຫຼັງ"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ສະແດງຄຳເຕືອນຊ່ອງການແຈ້ງເຕືອນ"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ສະແດງຄຳເຕືອນໃນໜ້າຈໍເມື່ອແອັບໂພສການແຈ້ງເຕືອນໂດຍບໍ່ມີຊ່ອງທີ່ຖືກຕ້ອງ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ບັງຄັບອະນຸຍາດແອັບ​ຢູ່​ພາຍນອກ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ເຮັດໃຫ້ທຸກແອັບມີສິດໄດ້ຮັບການຂຽນໃສ່ພື້ນທີ່ຈັດເກັບຂໍ້ມູນພາຍນອກ, ໂດຍບໍ່ຄຳນຶງເຖິງຄ່າ manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ບັງ​ຄັງ​ໃຫ້​ກິດ​ຈະ​ກຳ​ປ່ຽນ​ຂະ​ໜາດ​ໄດ້"</string>
index 274ce9a..97de7d5 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fono procesų apribojimas"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Rodyti visus ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Fon. programose rodyti dialogo langą „Neatsako“"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Rodyti pran. kan. įspėj."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Ekr. rod. įsp., kai progr. pask. pr. be tink. kan."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Priverstinai leisti programas išorinėje atmintin."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Nustatoma, kad visas programas būtų galima įrašyti į išorinę saugyklą, nepaisant aprašo verčių"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Priv. nust., kad veiksm. b. g. atl. kelių d. lang."</string>
index e760d78..98c8156 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fona procesu ierobežojums"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Rādīt visus ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Rādīt fona lietotņu dialoglodz. Lietotne nereaģē"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Paziņojumu kanāla brīdinājumi"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Brīdinājums ekrānā, kad lietotne publicē paziņojumu, nenorādot derīgu kanālu"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Lietotņu piespiedu atļaušana ārējā krātuvē"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ļauj jebkuru lietotni ierakstīt ārējā krātuvē neatkarīgi no manifesta vērtības."</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Pielāgot darbības"</string>
index 1979451..2bafd1f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Граница на процес во зад."</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Прикажи ги сите ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи „Апл. не реагира“ за. апл. во заднина"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Прикажи ги предупредувањата на каналот за известувањe"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Предупредува кога апликација дава известување без важечки канал"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Принуд. дозволете апликации на надворешна меморија"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Прави секоја апликација да биде подобна за запишување на надворешна меморија, независно од вредностите на манифестот"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Принуди ги активностите да ја менуваат големината"</string>
index 06a9dc1..2471879 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"പശ്ചാത്തല പ്രോസ‌സ്സ് പരിധി"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"എല്ലാ ANR-കളും ദൃശ്യമാക്കുക"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"പ‌ശ്ചാത്തല അപ്ലിക്കേഷനുകൾക്ക് അപ്ലിക്കേഷൻ പ്രതികരിക്കുന്നില്ല എന്ന ഡയലോഗ് കാണിക്കുക"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ചാനൽ മുന്നറിയിപ്പ് കാണിക്കൂ"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"സാധുതയുള്ള ചാനലില്ലാതെ ഒരു ആപ്പ്, അറിയിപ്പ് പോസ്റ്റുചെയ്യുമ്പോൾ ഓൺ-സ്‌ക്രീൻ മുന്നറിയിപ്പ് ‌പ്രദർശിപ്പിക്കുന്നു"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ബാഹ്യമായതിൽ നിർബന്ധിച്ച് അനുവദിക്കുക"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"മാനിഫെസ്റ്റ് മൂല്യങ്ങൾ പരിഗണിക്കാതെ, ബാഹ്യ സ്റ്റോറേജിലേക്ക് എഴുതപ്പെടുന്നതിന് ഏതൊരു ആപ്പിനെയും യോഗ്യമാക്കുന്നു"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"വലിപ്പം മാറ്റാൻ പ്രവർത്തനങ്ങളെ നിർബന്ധിക്കുക"</string>
index f400f5a..769ef5c 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Далд процессын хязгаар"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Бүх ANRs харуулах"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Далд апп-уудад Апп Хариу Өгөхгүй байна гэснийг харуулах"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Мэдэгдлийн сувгийн анхааруулгыг харуулах"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Апп хүчинтэй суваггүйгээр мэдэгдэл гаргах үед дэлгэцэд сануулга харуулна"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Аппыг гадаад санах ойд хадгалахыг зөвшөөрөх"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Манифест утгыг нь үл хамааран дурын апп-г гадаад санах ойд бичих боломжтой болгодог"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Үйл ажиллагааны хэмжээг өөрчилж болохуйц болгох"</string>
index 10632e0..0e1499b 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"पार्श्वभूमी प्रक्रिया मर्यादा"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"सर्व ANR दर्शवा"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पार्श्वभूमी अॅप्ससाठी अॅप प्रतिसाद देत नाही संवाद दर्शवा"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"सूचना चॅनेल चेतावण्या दाखवा"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"एखादे अ‍ॅप वैध चॅनेलशिवाय सूचना पोस्ट करते तेव्हा स्क्रीनवर चेतावणी देते"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यवर अॅप्सना अनुमती देण्याची सक्ती करा"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"मॅनिफेस्ट मूल्यांकडे दुर्लक्ष करून, कोणत्याही अॅपला बाह्य संचयनावर लेखन केले जाण्यासाठी पात्र बनविते"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"क्र‍ियाकलापाचा आकार बदलण्यायोग्य होण्याची सक्ती करा"</string>
index cc6a935..6667585 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Had proses latar belakang"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tunjukkan semua ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Tunjukkan dialog Aplikasi Tidak Memberi Maklum Balas untuk aplikasi latar belakang"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Papar amaran saluran pemberitahuan"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Memaparkan amaran pada skrin apabila apl menyiarkan pemberitahuan tanpa saluran sah"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Benarkan apl secara paksa pada storan luaran"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Menjadikan sebarang apl layak ditulis ke storan luaran, tanpa mengambil kira nilai manifes"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Paksa aktiviti supaya boleh diubah saiz"</string>
index 3e71800..2572d60 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"နောက်ခံလုပ်ငန်းစဉ်ကန့်သတ်ခြင်း"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ANRsအားလုံးအား ပြသရန်"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"နောက်ခံအပ်ပလီကေးရှင်းအတွက်တုံ့ပြန်မှုမရှိပြရန်"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ချန်နယ်သတိပေးချက်များပြပါ"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ချန်နယ်မရှိဘဲ အကြောင်းကြားလျှင် စကရင်တွင်သတိပေးသည်"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"အပြင်မှာ အတင်း ခွင့်ပြုရန်"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"တိကျစွာ သတ်မှတ်ထားသည့်တန်ဖိုးများရှိသော်လည်း၊ ပြင်ပသိုလှောင်ခန်းများသို့ မည်သည့်အက်ပ်ကိုမဆို ဝင်ရောက်ခွင့်ပြုပါ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"လုပ်ဆောင်ချက်များ ဆိုက်ညှိရနိုင်ရန် လုပ်ခိုင်းပါ"</string>
index 61ce9cb..a59b89c 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Bakgrunnsprosessgrense"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Vis alle ANR-er"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Vis Appen svarer ikke-dialog for bakgrunnsapper"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Vis varselskanaladvarsler"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Viser advarsler på skjermen når apper publiserer varsler uten en gyldig kanal"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tving frem tillatelse for ekstern lagring av apper"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Dette gjør at alle apper kan lagres på eksterne lagringsmedier – uavhengig av manifestverdier"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Tving aktiviteter til å kunne endre størrelse"</string>
index e87cf2f..87873ca 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"पृष्ठभूमि प्रक्रिया सीमा"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"सबै ANRs देखाउनुहोस्"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"पृष्ठभूमि अनुप्रयोगका लागि जवाफ नदिइरहेका अनुप्रयोगहरू देखाउनुहोस्"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"सूचना च्यानलका चेतावनी देखाउनुहोस्"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"अनुप्रयोगले कुनै मान्य च्यानल बिना सूचना पोस्ट गर्दा स्क्रिनमा चेतावनी देखाउँछ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"बाह्यमा बल प्रयोगको अनुमति प्राप्त अनुप्रयोगहरू"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"म्यानिफेेस्टका मानहरूको ख्याल नगरी कुनै पनि अनुप्रयोगलाई बाह्य भण्डारणमा लेख्न सकिने खाले बनाउँछ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"गतिविधिहरू रिसाइज गर्नको लागि बाध्य गर्नुहोस्"</string>
index b98ea2b..34487f7 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Achtergrondproceslimiet"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Alle ANR\'s weergeven"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"\'App reageert niet\' weerg. voor apps op achtergr."</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Kanaalwaarschuwingen voor meldingen weergeven"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Geeft een waarschuwing op het scherm weer wanneer een app een melding post zonder geldig kanaal"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Toestaan van apps op externe opslag afdwingen"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Hiermee komt elke app in aanmerking voor schrijven naar externe opslag, ongeacht de manifestwaarden"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Formaat activiteiten geforceerd aanpasbaar maken"</string>
index 08dd09d..d48a92b 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"ਪਿਛੋਕੜ ਪ੍ਰਕਿਰਿਆ ਸੀਮਾ"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"ਸਾਰੇ ANR ਦਿਖਾਓ"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"ਪਿਛੋਕੜ ਐਪਸ ਲਈ ਐਪਸ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਹੇ ਡਾਇਲੌਗ ਦਿਖਾਓ"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ਸੂਚਨਾ ਚੈਨਲ ਚੇਤਾਵਨੀਆਂ ਦਿਖਾਓ"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"ਐਪ ਵੱਲੋਂ ਵੈਧ ਚੈਨਲ ਤੋਂ ਬਿਨਾਂ ਸੂਚਨਾ ਪੋਸਟ ਕਰਨ \'ਤੇ ਸਕ੍ਰੀਨ \'ਤੇ ਚੇਤਾਵਨੀ ਦਿਖਾਉਂਦੀ ਹੈ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"ਐਪਸ ਨੂੰ ਬਾਹਰਲੇ ਤੇ ਜ਼ਬਰਦਸਤੀ ਆਗਿਆ ਦਿਓ"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ਮੈਨੀਫੈਸਟ ਮੁੱਲਾਂ ਦੀ ਪਰਵਾਹ ਕੀਤੇ ਬਿਨਾਂ, ਕਿਸੇ ਵੀ ਐਪ ਨੂੰ ਬਾਹਰੀ ਸਟੋਰੇਜ \'ਤੇ ਲਿਖਣ ਦੇ ਯੋਗ ਬਣਾਉਂਦੀ ਹੈ"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ਮੁੜ-ਆਕਾਰ ਬਦਲਣ ਲਈ ਸਰਗਰਮੀਆਂ \'ਤੇ ਜ਼ੋਰ ਦਿਓ"</string>
index e559c69..823e9c8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limit procesów w tle"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Pokaż wszystkie ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Pokaż okno Aplikacja Nie Reaguje dla aplikacji w tle"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Pokaż ostrzeżenia kanału powiadomień"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Wyświetla ostrzeżenie, gdy aplikacja publikuje powiadomienie bez prawidłowego kanału"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Wymuś zezwalanie na aplikacje w pamięci zewn."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Pozwala na zapis aplikacji w pamięci zewnętrznej niezależnie od wartości w pliku manifestu"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Wymuś zmianę rozmiaru okien aktywności"</string>
index cce80ed..c37d2f4 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do proc. 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos do canal de notif."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Exibe aviso na tela quando um app posta notificação sem canal válido"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
index 8124c4b..3a803a8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite proc. em 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Mostrar erro \"Aplic. não Resp.\" p/ aplic. 2º plano"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos do canal de notif."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Mostra um aviso no ecrã quando uma aplic. publica uma notific. sem um canal válido"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar perm. de aplicações no armazenamento ext."</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Torna qualquer aplicação elegível para ser gravada no armazenamento externo, independentemente dos valores do manifesto"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar as atividades a serem redimensionáveis"</string>
index cce80ed..c37d2f4 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limite do proc. 2º plano"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Mostrar todos os ANRS"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Exibir \"App não responde\" para app em 2º plano"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Mostrar avisos do canal de notif."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Exibe aviso na tela quando um app posta notificação sem canal válido"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forçar permissão de apps em armazenamento externo"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Qualifica apps para gravação em armazenamento externo, independentemente de valores de manifestos"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forçar atividades a serem redimensionáveis"</string>
index 3a174de..a861533 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limită procese fundal"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Afișați toate elem. ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Aplicații din fundal: afișați Aplicația nu răspunde"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Afișați avertismentele de pe canalul de notificări"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Afișează avertisment pe ecran când o aplicație postează o notificare fără canal valid"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Forțați accesul aplicațiilor la stocarea externă"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Face orice aplicație eligibilă să fie scrisă în stocarea externă, indiferent de valorile manifestului"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Forțați redimensionarea activităților"</string>
index cd8d956..9eb75ae 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Лимит фоновых процессов"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Все ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Уведомлять о том, что приложение не отвечает"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Показывать предупреждения канала передачи оповещения"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Показывать предупреждение о новых уведомлениях приложения вне допустимого канала"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Разрешить сохранение на внешние накопители"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Разрешить сохранение приложений на внешних накопителях (независимо от значений в манифесте)"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Изменение размера в многооконном режиме"</string>
index 592c2f9..8774baa 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"පසුබිම් ක්‍රියාවලි සීමාව"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"සියලුම ANR පෙන්වන්න"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"පසුබිම් යෙදුම් වලට යෙදුම ප්‍රතිචාර නොදක්වයි කවුළුව පෙන්වන්න"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"දැනුම්දීම් නාලිකා අනතුරු ඇඟවීම් පෙන්."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"යෙදුමක් වලංගු නාලිකාවකින් තොරව දැනුම්දීමක් පළ කරන විට තිරය-මත අනතුරු ඇඟවීමක් සංදර්ශනය කරයි."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"බාහිර මත යෙදුම් ඉඩ දීම බල කරන්න"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"මැනිෆෙස්ට් අගයන් නොසලකා, ඕනෑම යෙදුමක් බාහිර ගබඩාවට ලිවීමට සුදුසුකම් ලබා දෙයි"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"ක්‍රියාකාරකම් ප්‍රතිප්‍රමාණ කළ හැකි බවට බල කරන්න"</string>
index d5c4061..925e2c8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limit procesov na pozadí"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Zobrazovať všetky ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Zobrazovať dialóg „Aplikácia neodpovedá“ aj pre aplikácie na pozadí"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Zobraziť hlásenia kanála upozornení"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Zobrazuje varovné hlásenie na obrazovke, keď aplikácia zverejní upozornenie bez platného kanála"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vynútiť povolenie aplikácií na externom úložisku"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Umožňuje zapísať akúkoľvek aplikáciu do externého úložiska bez ohľadu na hodnoty v manifeste"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vynútiť možnosť zmeny veľkosti aktivít"</string>
index 4e0085c..6c2c355 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Omejitev postopkov v ozadju"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Pokaži okna neodzivanj"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Prikaz pogovornega okna za neodzivanje aplikacije v ozadju"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Pokaži opoz. kan. za obv."</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Na zaslonu se pokaže opozorilo, ko aplikacija objavi obvestilo brez veljavnega kanala"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Vsili omogočanje aplikacij v zunanji shrambi"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Poskrbi, da je ne glede na vrednosti v manifestu mogoče vsako aplikacijo zapisati v zunanjo shrambo"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Vsili povečanje velikosti za aktivnosti"</string>
index e8340bf..9c178d7 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Kufizimi i proceseve në sfond"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Shfaq raportet ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Shfaq raportet ANR (Aplikacioni nuk përgjigjet) për aplikacionet në sfond"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Shfaq paralajmërimet e kanalit të njoftimeve"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Shfaq paralajmërimin në ekran kur një aplikacion poston një njoftim pa një kanal të vlefshëm"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Detyro lejimin në hapësirën e jashtme"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Bën që çdo aplikacion të jetë i përshtatshëm për t\'u shkruar në hapësirën ruajtëse të jashtme, pavarësisht nga vlerat e manifestit"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Detyro madhësinë e ndryshueshme për aktivitetet"</string>
index 63ceb73..44fe06f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Ограничење позадинских процеса"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Прикажи све ANR-ове"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Прикажи дијалог Апликација не реагује за апликације у позадини"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Приказуј упозорења због канала за обавештења"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Приказује упозорење на екрану када апликација постави обавештење без важећег канала"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Принудно дозволи апликације у спољној"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Омогућава уписивање свих апликација у спољну меморију, без обзира на вредности манифеста"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Принудно омогући промену величине активности"</string>
index 1f2ca23..d8cc76f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Begränsa bakgrundsprocess"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Visa alla som inte svarar"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Visa dialogrutan om att appen inte svarar för bakgrundsappar"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Visa varningar om aviseringskanal"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Visa varningar på skärmen när en app lägger upp en avisering utan en giltig kanal"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tillåt appar i externt lagringsutrymme"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Allar appar kan skrivas till extern lagring, oavsett manifestvärden"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Framtvinga storleksanpassning för aktiviteter"</string>
index 4d75fbc..d48cded 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Kiwango cha mchakato wa mandari nyuma"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Onyesha ANR zote"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Onyesha kisanduku kidadisi cha Programu Haiitikii kwa programu za usuli"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Onyesha arifa za maonyo ya kituo"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Huonyesha onyo kwenye skrini programu inapochapisha arifa bila kituo sahihi."</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Lazima uruhusu programu kwenye hifadhi ya nje"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Huruhusu programu yoyote iwekwe kwenye hifadhi ya nje, bila kujali thamani za faili ya maelezo"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Lazimisha shughuli ziweze kubadilishwa ukubwa"</string>
index 47f7586..44b13ec 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"பின்புலச் செயல்முறை வரம்பு"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"எல்லா ANRகளையும் காட்டு"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"பின்புலப் பயன்பாடுகளுக்குப் பயன்பாடு பதிலளிக்கவில்லை என்ற உரையாடலைக் காட்டு"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"அறிவிப்புச் சேனல் எச்சரிக்கைகளைக் காட்டு"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"பயன்பாடானது சரியான சேனல் இல்லாமல் அறிவிப்பை இடுகையிடும் போது, திரையில் எச்சரிக்கையைக் காட்டும்"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"பயன்பாடுகளை வெளிப்புறச் சேமிப்பிடத்தில் அனுமதி"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"மேனிஃபெஸ்ட் மதிப்புகளைப் பொருட்படுத்தாமல், எல்லா பயன்பாட்டையும் வெளிப்புறச் சேமிப்பிடத்தில் எழுத அனுமதிக்கும்"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"செயல்பாடுகளை அளவுமாறக்கூடியதாக அமை"</string>
index 1a7ad4d..66f31d8 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"నేపథ్య ప్రాసెస్ పరిమితి"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"అన్ని ANRలను చూపు"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"నేపథ్య అనువర్తనాల కోసం అనువర్తనం ప్రతిస్పందించడం లేదు డైలాగ్‌ను చూపు"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"ఛానెల్ హెచ్చరికల నోటిఫికేషన్‌‌ను చూపు"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"చెల్లుబాటు అయ్యే ఛానెల్ లేకుండా అనువర్తనం నోటిఫికేషన్‌ను పోస్ట్ చేస్తున్నప్పుడు స్క్రీన్‌పై హెచ్చరికను చూపిస్తుంది"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"అనువర్తనాలను బాహ్య నిల్వలో నిర్బంధంగా అనుమతించు"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ఏ అనువర్తనాన్ని అయినా మానిఫెస్ట్ విలువలతో సంబంధం లేకుండా బాహ్య నిల్వలో వ్రాయడానికి అనుమతిస్తుంది"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"కార్యాచరణలను పరిమాణం మార్చగలిగేలా నిర్బంధించు"</string>
index aa0296c..0cc93a9 100644 (file)
     <string name="oem_unlock_enable" msgid="6040763321967327691">"การปลดล็อก OEM"</string>
     <string name="oem_unlock_enable_summary" msgid="4720281828891618376">"อนุญาตให้ปลดล็อกตัวโหลดการเปิดเครื่อง"</string>
     <string name="confirm_enable_oem_unlock_title" msgid="4802157344812385674">"อนุญาตการปลดล็อก OEM ไหม"</string>
-    <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"à¸\84ำà¹\80à¸\95ือà¸\99: à¸\84ุà¸\93ลัà¸\81ษà¸\93ะการปกป้องอุปกรณ์จะไม่ทำงานบนอุปกรณ์นี้ขณะที่การตั้งค่านี้เปิดอยู่"</string>
+    <string name="confirm_enable_oem_unlock_text" msgid="5517144575601647022">"à¸\84ำà¹\80à¸\95ือà¸\99: à¸\9fีà¹\80à¸\88อรà¹\8cการปกป้องอุปกรณ์จะไม่ทำงานบนอุปกรณ์นี้ขณะที่การตั้งค่านี้เปิดอยู่"</string>
     <string name="mock_location_app" msgid="7966220972812881854">"เลือกแอปจำลองตำแหน่ง"</string>
     <string name="mock_location_app_not_set" msgid="809543285495344223">"ไม่ได้ตั้งค่าแอปจำลองตำแหน่ง"</string>
     <string name="mock_location_app_set" msgid="8966420655295102685">"แอปจำลองตำแหน่ง: <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"การตั้งค่านี้มีไว้เพื่อการพัฒนาเท่านั้น จึงอาจทำให้อุปกรณ์และแอปพลิเคชันที่มีอยู่เสียหายหรือทำงานผิดพลาดได้"</string>
     <string name="verify_apps_over_usb_title" msgid="4177086489869041953">"ยืนยันแอปพลิเคชันผ่าน USB"</string>
     <string name="verify_apps_over_usb_summary" msgid="9164096969924529200">"ตรวจสอบแอปพลิเคชันที่ติดตั้งผ่าน ADB/ADT เพื่อตรวจดูพฤติกรรมที่เป็นอันตราย"</string>
-    <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\84ุà¸\93ลัà¸\81ษà¸\93ะการควบคุมระดับเสียงของอุปกรณ์อื่นผ่านบลูทูธในกรณีที่มีปัญหาเกี่ยวกับระดับเสียงของอุปกรณ์ระยะไกล เช่น ระดับเสียงที่ดังเกินไปหรือระดับเสียงที่ไม่มีการควบคุม"</string>
+    <string name="bluetooth_disable_absolute_volume_summary" msgid="6031284410786545957">"à¸\9bิà¸\94à¹\83à¸\8aà¹\89à¸\9fีà¹\80à¸\88อรà¹\8cการควบคุมระดับเสียงของอุปกรณ์อื่นผ่านบลูทูธในกรณีที่มีปัญหาเกี่ยวกับระดับเสียงของอุปกรณ์ระยะไกล เช่น ระดับเสียงที่ดังเกินไปหรือระดับเสียงที่ไม่มีการควบคุม"</string>
     <string name="bluetooth_enable_inband_ringing_summary" msgid="2787866074741784975">"ให้เสียงเรียกเข้าในโทรศัพท์เล่นในชุดหูฟังบลูทูธ"</string>
     <string name="enable_terminal_title" msgid="95572094356054120">"เทอร์มินัลในตัวเครื่อง"</string>
     <string name="enable_terminal_summary" msgid="67667852659359206">"เปิดใช้งานแอปเทอร์มินัลที่ให้การเข้าถึงเชลล์ในตัวเครื่อง"</string>
     <string name="app_process_limit_title" msgid="4280600650253107163">"ขีดจำกัดกระบวนการพื้นหลัง"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"แสดง ANR ทั้งหมด"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"แสดงหน้าต่างแอปไม่ตอบสนอง สำหรับแอปพื้นหลัง"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"แสดงคำเตือนจากช่องทางการแจ้งเตือน"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"แสดงคำเตือนบนหน้าจอเมื่อแอปโพสต์การแจ้งเตือนโดยไม่มีช่องทางที่ถูกต้อง"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"บังคับให้แอปสามารถใช้ที่เก็บภายนอก"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"ทำให้สามารถเขียนแอปใดๆ ก็ตามไปยังพื้นที่เก็บข้อมูลภายนอกได้ โดยไม่คำนึงถึงค่าในไฟล์ Manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"บังคับให้กิจกรรมปรับขนาดได้"</string>
     <string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"แปลง…"</string>
     <string name="convert_to_file_encryption_done" msgid="7859766358000523953">"เข้ารหัสไฟล์แล้ว"</string>
     <string name="title_convert_fbe" msgid="1263622876196444453">"การแปลงเป็นการเข้ารหัสตามไฟล์"</string>
-    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"à¹\81à¸\9bลà¸\87à¸\9eารà¹\8cà¸\97ิà¸\8aัà¸\99à¸\82à¹\89อมูลà¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\80à¸\82à¹\89ารหัสà¹\81à¸\9aà¸\9aà¹\84à¸\9fลà¹\8c\n !!à¸\84ำà¹\80à¸\95ือà¸\99!! à¸\81ารà¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\99ีà¹\89à¸\88ะลà¸\9aà¸\82à¹\89อมูลà¸\97ัà¹\89à¸\87หมà¸\94à¸\82อà¸\87à¸\84ุà¸\93\n à¸\84ุà¸\93ลัà¸\81ษà¸\93ะนี้เป็นแบบอัลฟา และอาจทำงานไม่เป็นปกติ\n กด \"ลบและแปลง...\" เพื่อดำเนินการต่อ"</string>
+    <string name="convert_to_fbe_warning" msgid="6139067817148865527">"à¹\81à¸\9bลà¸\87à¸\9eารà¹\8cà¸\97ิà¸\8aัà¸\99à¸\82à¹\89อมูลà¹\80à¸\9bà¹\87à¸\99à¸\81ารà¹\80à¸\82à¹\89ารหัสà¹\81à¸\9aà¸\9aà¹\84à¸\9fลà¹\8c\n !!à¸\84ำà¹\80à¸\95ือà¸\99!! à¸\81ารà¸\94ำà¹\80à¸\99ิà¸\99à¸\81ารà¸\99ีà¹\89à¸\88ะลà¸\9aà¸\82à¹\89อมูลà¸\97ัà¹\89à¸\87หมà¸\94à¸\82อà¸\87à¸\84ุà¸\93\n à¸\9fีà¹\80à¸\88อรà¹\8cนี้เป็นแบบอัลฟา และอาจทำงานไม่เป็นปกติ\n กด \"ลบและแปลง...\" เพื่อดำเนินการต่อ"</string>
     <string name="button_convert_fbe" msgid="5152671181309826405">"ลบและแปลง…"</string>
     <string name="picture_color_mode" msgid="4560755008730283695">"โหมดสีของรูปภาพ"</string>
     <string name="picture_color_mode_desc" msgid="1141891467675548590">"ใช้ sRGB"</string>
     <string name="daltonizer_mode_protanomaly" msgid="8424148009038666065">"ตาบอดจางสีแดง (สีแดง/เขียว)"</string>
     <string name="daltonizer_mode_tritanomaly" msgid="481725854987912389">"ตาบอดจางสีน้ำเงิน (สีน้ำเงิน/เหลือง)"</string>
     <string name="accessibility_display_daltonizer_preference_title" msgid="5800761362678707872">"การแก้สี"</string>
-    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"à¸\84ุà¸\93ลัà¸\81ษà¸\93ะนี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string>
+    <string name="accessibility_display_daltonizer_preference_subtitle" msgid="3484969015295282911">"à¸\9fีà¹\80à¸\88อรà¹\8cนี้เป็นแบบทดลองและอาจส่งผลต่อประสิทธิภาพการทำงาน"</string>
     <string name="daltonizer_type_overridden" msgid="3116947244410245916">"แทนที่โดย <xliff:g id="TITLE">%1$s</xliff:g>"</string>
     <string name="power_remaining_duration_only" msgid="845431008899029842">"อีกประมาณ <xliff:g id="TIME">%1$s</xliff:g>"</string>
     <string name="power_remaining_charging_duration_only" msgid="1421102457410268886">"อีก <xliff:g id="TIME">%1$s</xliff:g> จึงจะชาร์จเต็ม"</string>
index 988a88b..f00440f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Limitasyon ng proseso sa background"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Ipakita ang lahat ng ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"App Not Responding dialog para sa background apps"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Ipakita ang mga babala sa notification channel"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Nagpapakita ng babala sa screen kapag nag-post ang app ng notification nang walang wastong channel"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Pwersahang payagan ang mga app sa external"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Ginagawang kwalipikado ang anumang app na mailagay sa external na storage, anuman ang mga value ng manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Sapilitang gawing resizable ang mga aktibidad"</string>
index 5eff6c3..80f5dc4 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Arka plan işlem sınırı"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Tüm ANR\'leri göster"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Arka plan uygulamalar için Uygulama Yanıt Vermiyor mesajını göster"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Bildirim kanalı uyarılarını göster"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Bir uygulama geçerli kanal olmadan bildirim yayınladığında ekranda uyarı gösterir"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Harici birimdeki uygulamalara izin vermeye zorla"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Manifest değerlerinden bağımsız olarak uygulamaları harici depolamaya yazmak için uygun hale getirir"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Etkinlikleri yeniden boyutlandırılabilmeye zorla"</string>
index 419a8c0..96f0c59 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Обмеження фон. процесів"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Показувати всі ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Сповіщати, коли додаток не відповідає"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Показувати застереження про канал"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"З’являється застереження, коли додаток надсилає сповіщення через недійсний канал"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Примусово записувати додатки в зовнішню пам’ять"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Можна записувати додатки в зовнішню пам’ять, незалежно від значень у маніфесті"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Примусово масштабувати активність"</string>
index 55f7132..aed65fa 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"پس منظر پروسیس کی حد"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"‏سبھی ANRs کو دکھائیں"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"پس منظر کی ایپس کیلئے ایپ جواب نہیں دے رہی ہے ڈائلاگ دکھائیں"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"چینل کی اطلاعی تنبیہات دکھائیں"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"کسی ایپ کی طرف سے درست چینل کے بغیر اطلاع پوسٹ ہونے پر آن اسکرین تنبیہ ڈسپلے کرتا ہے"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"بیرونی پر ایپس کو زبردستی اجازت دیں"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"‏manifest اقدار سے قطع نظر، کسی بھی ایپ کو بیرونی اسٹوریج پر لکھے جانے کا اہل بناتا ہے"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"سرگرمیوں کو ری سائز ایبل بنائیں"</string>
index 4b53da5..ae6ba0f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Fondagi jarayonlarni cheklash"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Hamma ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Ilova javob bermayotgani haqida xabar qilish"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Xabarlar kanali ogohlantirishlarini ko‘rsatish"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Yaroqli kanalsiz yuborilgan yangi ilova xabarnomalari haqida ogohlantirishlarni ko‘rsatish"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Tashqi xotira qurilmasidagi ilova dasturlariga majburiy ruxsat berish"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Manifest qiymatidan qat’i nazar istalgan ilovani tashqi xotiraga saqlash imkonini beradi"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Harakatlarni moslashuvchan o‘lchamga keltirish"</string>
index a6a54d0..87ba837 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Giới hạn quá trình nền"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Hiển thị tất cả ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Hiện hộp thoại Ứng dụng ko đáp ứng cho ứng dụng nền"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Hiện cảnh báo kênh th.báo"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Hiện cảnh báo trên m.hình khi ƯD đăng th.báo ko có kênh hợp lệ"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Buộc cho phép các ứng dụng trên bộ nhớ ngoài"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Giúp mọi ứng dụng đủ điều kiện để được ghi vào bộ nhớ ngoài, bất kể giá trị tệp kê khai là gì"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Buộc các hoạt động có thể thay đổi kích thước"</string>
index 41c5f60..ae98f2f 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"后台进程限制"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"显示所有“应用无响应”(ANR)"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"为后台应用显示“应用无响应”对话框"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"显示通知渠道警告"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"当应用未经有效渠道发布通知时,在屏幕上显示警告"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"强制允许将应用写入外部存储设备"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"允许将任何应用写入外部存储设备(无论清单值是什么)"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"强制将活动设为可调整大小"</string>
index 00748b0..e1ad0c4 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"背景處理程序限制"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"顯示所有 ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"顯示背景應用程式的「應用程式無回應」對話框"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"顯示通知渠道警告"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效渠道發佈通知時,在螢幕上顯示警告"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許應用程式寫入到外部儲存空間"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"在任何資訊清單值下,允許將所有符合資格的應用程式寫入到外部儲存完間"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"強制可變更活動尺寸"</string>
index 3988edd..9ed1a26 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"背景處理程序限制"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"顯示所有無回應程式"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"為背景應用程式顯示「應用程式無回應」對話方塊"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"顯示通知管道警告"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"當應用程式未經有效管道發佈通知時,在畫面上顯示警告"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"強制允許將應用程式寫入外部儲存空間"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"允許將任何應用程式寫入外部儲存空間 (無論資訊清單值為何)"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"將活動強制設為可調整大小"</string>
index 11dfdcc..630a9da 100644 (file)
     <string name="app_process_limit_title" msgid="4280600650253107163">"Isilinganiso senqubo yesithombe sanemuva"</string>
     <string name="show_all_anrs" msgid="28462979638729082">"Bonisa wonke ama-ANR"</string>
     <string name="show_all_anrs_summary" msgid="641908614413544127">"Boniso idayalogi Yohlelo Lokusebenza Olungasabeli kwizinhlelo zokusebenza zasemuva"</string>
-    <!-- no translation found for show_notification_channel_warnings (1399948193466922683) -->
-    <skip />
-    <!-- no translation found for show_notification_channel_warnings_summary (5536803251863694895) -->
-    <skip />
+    <string name="show_notification_channel_warnings" msgid="1399948193466922683">"Bonisa izexwayiso zesiteshi sesaziso"</string>
+    <string name="show_notification_channel_warnings_summary" msgid="5536803251863694895">"Ibonisa isexwayiso esikusikrini uma uhlelo lokusebenza luthumela isaziso ngaphandle kwesiteshi esivumelekile"</string>
     <string name="force_allow_on_external" msgid="3215759785081916381">"Phoqelela ukuvumela izinhlelo zokusebenza ngaphandle"</string>
     <string name="force_allow_on_external_summary" msgid="3640752408258034689">"Yenza noma uluphi uhlelo lokusebenza lifaneleke ukuthi libhalwe kusitoreji sangaphandle, ngaphandle kwamavelu we-manifest"</string>
     <string name="force_resizable_activities" msgid="8615764378147824985">"Imisebenzi yamandla izonikezwa usayizi omusha"</string>
index 4921be1..8f7a3dd 100644 (file)
     <!-- Summary for switch preference to denote it is switched off [CHAR LIMIT=50] -->
     <string name="disabled_by_admin">Disabled by admin</string>
 
+    <!-- [CHAR LIMIT=25] Manage applications, text telling using an application is disabled. -->
+    <string name="disabled">Disabled</string>
+    <!-- Summary of app trusted to install apps [CHAR LIMIT=45] -->
+    <string name="external_source_trusted">Allowed</string>
+    <!-- Summary of app not trusted to install apps [CHAR LIMIT=45] -->
+    <string name="external_source_untrusted">Not allowed</string>
+
+    <!-- Title for settings screen for controlling apps that can install other apps on device [CHAR LIMIT=50] -->
+    <string name="install_other_apps">Install unknown apps</string>
+
     <!-- Option in navigation drawer that leads to Settings main screen [CHAR LIMIT=30] -->
     <string name="home">Settings Home</string>
 
index 82da9a3..e4e0f7f 100644 (file)
@@ -26,13 +26,13 @@ public class InterestingConfigChanges {
     private int mLastDensity;
 
     public InterestingConfigChanges() {
-        this(0);
+        this(ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT
+                | ActivityInfo.CONFIG_ASSETS_PATHS);
     }
 
-    public InterestingConfigChanges(int extraFlags) {
-        mFlags = extraFlags | ActivityInfo.CONFIG_LOCALE
-                | ActivityInfo.CONFIG_UI_MODE | ActivityInfo.CONFIG_SCREEN_LAYOUT
-                | ActivityInfo.CONFIG_ASSETS_PATHS;
+    public InterestingConfigChanges(int flags) {
+        mFlags = flags;
     }
 
     public boolean applyNewConfig(Resources res) {
index 34fdc9d..a8f6f02 100644 (file)
@@ -63,15 +63,17 @@ public class StorageStatsSource {
         public long audioBytes;
         public long videoBytes;
         public long imageBytes;
+        public long appBytes;
 
         /** Convenience method for testing. */
         @VisibleForTesting
         public ExternalStorageStats(
-                long totalBytes, long audioBytes, long videoBytes, long imageBytes) {
+                long totalBytes, long audioBytes, long videoBytes, long imageBytes, long appBytes) {
             this.totalBytes = totalBytes;
             this.audioBytes = audioBytes;
             this.videoBytes = videoBytes;
             this.imageBytes = imageBytes;
+            this.appBytes = appBytes;
         }
 
         /**
@@ -84,6 +86,7 @@ public class StorageStatsSource {
             audioBytes = stats.getAudioBytes();
             videoBytes = stats.getVideoBytes();
             imageBytes = stats.getImageBytes();
+            appBytes = stats.getAppBytes();
         }
     }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java b/packages/SettingsLib/src/com/android/settingslib/graph/BottomLabelLayout.java
new file mode 100644 (file)
index 0000000..8161dd4
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+
+package com.android.settingslib.graph;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.support.annotation.VisibleForTesting;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import com.android.settingslib.R;
+
+/**
+ * An extension of LinearLayout that automatically switches to vertical
+ * orientation when it can't fit its child views horizontally.
+ *
+ * Main logic in this class comes from {@link android.support.v7.widget.ButtonBarLayout}.
+ * Compared with {@link android.support.v7.widget.ButtonBarLayout}, this layout won't reverse
+ * children's order and won't update the minimum height
+ */
+public class BottomLabelLayout extends LinearLayout {
+    private static final String TAG = "BottomLabelLayout";
+
+    public BottomLabelLayout(Context context,
+            @Nullable AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
+        final boolean isStacked = isStacked();
+        boolean needsRemeasure = false;
+
+        // If we're not stacked, make sure the measure spec is AT_MOST rather
+        // than EXACTLY. This ensures that we'll still get TOO_SMALL so that we
+        // know to stack the buttons.
+        final int initialWidthMeasureSpec;
+        if (!isStacked && MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) {
+            initialWidthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
+
+            // We'll need to remeasure again to fill excess space.
+            needsRemeasure = true;
+        } else {
+            initialWidthMeasureSpec = widthMeasureSpec;
+        }
+
+        super.onMeasure(initialWidthMeasureSpec, heightMeasureSpec);
+        if (!isStacked) {
+            final int measuredWidth = getMeasuredWidthAndState();
+            final int measuredWidthState = measuredWidth & View.MEASURED_STATE_MASK;
+
+            if (measuredWidthState == View.MEASURED_STATE_TOO_SMALL) {
+                setStacked(true);
+                // Measure again in the new orientation.
+                needsRemeasure = true;
+            }
+        }
+
+        if (needsRemeasure) {
+            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        }
+
+    }
+
+    @VisibleForTesting
+    void setStacked(boolean stacked) {
+        setOrientation(stacked ? LinearLayout.VERTICAL : LinearLayout.HORIZONTAL);
+        setGravity(stacked ? Gravity.START : Gravity.BOTTOM);
+
+        final View spacer = findViewById(R.id.spacer);
+        if (spacer != null) {
+            spacer.setVisibility(stacked ? View.GONE : View.VISIBLE);
+        }
+    }
+
+    private boolean isStacked() {
+        return getOrientation() == LinearLayout.VERTICAL;
+    }
+}
index b3565ea..623d1a6 100644 (file)
@@ -335,6 +335,7 @@ public class AccessPoint implements Comparable<AccessPoint> {
         if (security != SECURITY_NONE) {
             builder.append(',').append(securityToString(security, pskType));
         }
+        builder.append(",mRssi=").append(mRssi);
         builder.append(",level=").append(getLevel());
         if (mRankingScore != Integer.MIN_VALUE) {
             builder.append(",rankingScore=").append(mRankingScore);
@@ -745,8 +746,12 @@ public class AccessPoint implements Comparable<AccessPoint> {
             visibility.append(" rssi=").append(mInfo.getRssi());
             visibility.append(" ");
             visibility.append(" score=").append(mInfo.score);
-            visibility.append(" rankingScore=").append(getRankingScore());
-            visibility.append(" badge=").append(getBadge());
+            if (mRankingScore != Integer.MIN_VALUE) {
+              visibility.append(" rankingScore=").append(getRankingScore());
+            }
+            if (mBadge != NetworkBadging.BADGING_NONE) {
+              visibility.append(" badge=").append(getBadge());
+            }
             visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate));
             visibility.append(String.format("%.1f,", mInfo.txRetriesRate));
             visibility.append(String.format("%.1f ", mInfo.txBadRate));
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiSavedConfigUtils.java
new file mode 100644 (file)
index 0000000..159b2a1
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+package com.android.settingslib.wifi;
+
+import android.content.Context;
+import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import android.net.wifi.hotspot2.PasspointConfiguration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Provide utility functions for retrieving saved Wi-Fi configurations.
+ */
+public class WifiSavedConfigUtils {
+    /**
+     * Returns all the saved configurations on the device, including both Wi-Fi networks and
+     * Passpoint profiles, represented by {@link AccessPoint}.
+     *
+     * @param context The application context
+     * @param wifiManager An instance of {@link WifiManager}
+     * @return List of {@link AccessPoint}
+     */
+    public static List<AccessPoint> getAllConfigs(Context context, WifiManager wifiManager) {
+        List<AccessPoint> savedConfigs = new ArrayList<>();
+        List<WifiConfiguration> savedNetworks = wifiManager.getConfiguredNetworks();
+        for (WifiConfiguration network : savedNetworks) {
+            // Configuration for Passpoint network is configured temporary by WifiService for
+            // connection attempt only.  The underlying configuration is saved as Passpoint
+            // configuration, which will be retrieved with WifiManager#getPasspointConfiguration
+            // call below.
+            if (network.isPasspoint()) {
+                continue;
+            }
+            // Ephemeral networks are not saved to the persistent storage, ignore them.
+            if (network.isEphemeral()) {
+                continue;
+            }
+            savedConfigs.add(new AccessPoint(context, network));
+        }
+        try {
+            List<PasspointConfiguration> savedPasspointConfigs =
+                    wifiManager.getPasspointConfigurations();
+            for (PasspointConfiguration config : savedPasspointConfigs) {
+                savedConfigs.add(new AccessPoint(context, config));
+            }
+        } catch (UnsupportedOperationException e) {
+            // Passpoint not supported.
+        }
+        return savedConfigs;
+    }
+}
+
index 7a63b8a..40a59cf 100644 (file)
@@ -95,8 +95,6 @@ public class WifiTracker {
 
     private WifiTrackerNetworkCallback mNetworkCallback;
 
-    private int mNumSavedNetworks;
-
     @GuardedBy("mLock")
     private boolean mRegistered;
 
@@ -138,8 +136,6 @@ public class WifiTracker {
 
     private final NetworkScoreManager mNetworkScoreManager;
     private final WifiNetworkScoreCache mScoreCache;
-    private boolean mNetworkScoringUiEnabled;
-    private final ContentObserver mObserver;
 
     @GuardedBy("mLock")
     private final Set<NetworkKey> mRequestedScores = new ArraySet<>();
@@ -227,16 +223,6 @@ public class WifiTracker {
                 updateNetworkScores();
             }
         });
-
-        mObserver = new ContentObserver(mWorkHandler) {
-            @Override
-            public void onChange(boolean selfChange) {
-                mNetworkScoringUiEnabled =
-                        Settings.Global.getInt(
-                                mContext.getContentResolver(),
-                                Settings.Global.NETWORK_SCORING_UI_ENABLED, 0) == 1;
-            }
-        };
     }
 
     /**
@@ -310,12 +296,6 @@ public class WifiTracker {
         synchronized (mLock) {
             registerScoreCache();
 
-            mContext.getContentResolver().registerContentObserver(
-                    Settings.Global.getUriFor(Settings.Global.NETWORK_SCORING_UI_ENABLED),
-                    false /* notifyForDescendants */,
-                    mObserver);
-            mObserver.onChange(false /* selfChange */); // Set mScoringUiEnabled
-
             resumeScanning();
             if (!mRegistered) {
                 mContext.registerReceiver(mReceiver, mFilter);
@@ -362,7 +342,6 @@ public class WifiTracker {
             }
             unregisterAndClearScoreCache();
             pauseScanning();
-            mContext.getContentResolver().unregisterContentObserver(mObserver);
 
             mWorkHandler.removePendingMessages();
             mMainHandler.removePendingMessages();
@@ -399,9 +378,11 @@ public class WifiTracker {
     /**
      * Returns the number of saved networks on the device, regardless of whether the WifiTracker
      * is tracking saved networks.
+     * TODO(b/62292448): remove this function and update callsites to use WifiSavedConfigUtils
+     * directly.
      */
     public int getNumSavedNetworks() {
-        return mNumSavedNetworks;
+        return WifiSavedConfigUtils.getAllConfigs(mContext, mWifiManager).size();
     }
 
     public boolean isConnected() {
@@ -499,12 +480,10 @@ public class WifiTracker {
 
         final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
         if (configs != null) {
-            mNumSavedNetworks = 0;
             for (WifiConfiguration config : configs) {
                 if (config.selfAdded && config.numAssociation == 0) {
                     continue;
                 }
-                mNumSavedNetworks++;
                 AccessPoint accessPoint = getCachedOrCreate(config, cachedAccessPoints);
                 if (mLastInfo != null && mLastNetworkInfo != null) {
                     accessPoint.update(connectionConfig, mLastInfo, mLastNetworkInfo);
@@ -582,7 +561,7 @@ public class WifiTracker {
 
         requestScoresForNetworkKeys(scoresToRequest);
         for (AccessPoint ap : accessPoints) {
-            ap.update(mScoreCache, mNetworkScoringUiEnabled);
+            ap.update(mScoreCache, false /* mNetworkScoringUiEnabled */);
         }
 
         // Pre-sort accessPoints to speed preference insertion
@@ -680,7 +659,7 @@ public class WifiTracker {
                     updated = true;
                     if (previouslyConnected != ap.isActive()) reorder = true;
                 }
-                if (ap.update(mScoreCache, mNetworkScoringUiEnabled)) {
+                if (ap.update(mScoreCache, false /* mNetworkScoringUiEnabled */)) {
                     reorder = true;
                     updated = true;
                 }
@@ -703,7 +682,8 @@ public class WifiTracker {
         synchronized (mLock) {
             boolean updated = false;
             for (int i = 0; i < mInternalAccessPoints.size(); i++) {
-                if (mInternalAccessPoints.get(i).update(mScoreCache, mNetworkScoringUiEnabled)) {
+                if (mInternalAccessPoints.get(i).update(
+                        mScoreCache, false /* mNetworkScoringUiEnabled */)) {
                     updated = true;
                 }
             }
index d4ce40c..c526432 100644 (file)
@@ -410,6 +410,7 @@ public class WifiTrackerTest {
         validConfig.BSSID = BSSID_1;
 
         WifiConfiguration selfAddedNoAssociation = new WifiConfiguration();
+        selfAddedNoAssociation.ephemeral = true;
         selfAddedNoAssociation.selfAdded = true;
         selfAddedNoAssociation.numAssociation = 0;
         selfAddedNoAssociation.SSID = SSID_2;
@@ -472,7 +473,7 @@ public class WifiTrackerTest {
     }
 
     @Test
-    public void scoreCacheUpdateScoresShouldChangeSortOrder() throws InterruptedException {
+    public void scoreCacheUpdateScoresShouldNotChangeSortOrder() throws InterruptedException {
         WifiTracker tracker =  createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         List<AccessPoint> aps = tracker.getAccessPoints();
         assertTrue(aps.size() == 2);
@@ -483,8 +484,8 @@ public class WifiTrackerTest {
 
         aps = tracker.getAccessPoints();
         assertTrue(aps.size() == 2);
-        assertEquals(aps.get(0).getSsidStr(), SSID_2);
-        assertEquals(aps.get(1).getSsidStr(), SSID_1);
+        assertEquals(aps.get(0).getSsidStr(), SSID_1);
+        assertEquals(aps.get(1).getSsidStr(), SSID_2);
     }
 
     @Test
@@ -510,7 +511,8 @@ public class WifiTrackerTest {
     }
 
     @Test
-    public void scoreCacheUpdateScoresShouldInsertBadgeIntoAccessPoint() throws InterruptedException {
+    public void scoreCacheUpdateScoresShouldNotInsertBadgeIntoAccessPoint()
+            throws InterruptedException {
         WifiTracker tracker = createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
         updateScoresAndWaitForAccessPointsChangedCallback();
 
@@ -518,9 +520,9 @@ public class WifiTrackerTest {
 
         for (AccessPoint ap : aps) {
             if (ap.getSsidStr().equals(SSID_1)) {
-                assertEquals(BADGE_1, ap.getBadge());
+                assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
             } else if (ap.getSsidStr().equals(SSID_2)) {
-                assertEquals(BADGE_2, ap.getBadge());
+                assertEquals(NetworkBadging.BADGING_NONE, ap.getBadge());
             }
         }
     }
@@ -746,4 +748,4 @@ public class WifiTrackerTest {
 
         verifyNoMoreInteractions(mockWifiListener);
     }
-}
\ No newline at end of file
+}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/graph/BottomLabelLayoutTest.java
new file mode 100644 (file)
index 0000000..ec21723
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ *
+ */
+
+package com.android.settingslib.graph;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.view.View;
+import android.widget.LinearLayout;
+import android.widget.Space;
+
+import com.android.settingslib.R;
+import com.android.settingslib.TestConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
+public class BottomLabelLayoutTest {
+    private BottomLabelLayout mBottomLabelLayout;
+    private Context mContext;
+    private Space mSpace;
+
+    @Before
+    public void setUp() {
+        mContext = RuntimeEnvironment.application;
+        mBottomLabelLayout = new BottomLabelLayout(mContext, null);
+        mBottomLabelLayout.setOrientation(LinearLayout.HORIZONTAL);
+
+        mSpace = new Space(mContext);
+        mSpace.setId(R.id.spacer);
+        mBottomLabelLayout.addView(mSpace);
+    }
+
+    @Test
+    public void testSetStacked_stackedTrue_layoutVertical() {
+        mBottomLabelLayout.setStacked(true);
+
+        assertThat(mBottomLabelLayout.getOrientation()).isEqualTo(LinearLayout.VERTICAL);
+        assertThat(mSpace.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void testSetStacked_stackedFalse_layoutHorizontal() {
+        mBottomLabelLayout.setStacked(false);
+
+        assertThat(mBottomLabelLayout.getOrientation()).isEqualTo(LinearLayout.HORIZONTAL);
+        assertThat(mSpace.getVisibility()).isEqualTo(View.VISIBLE);
+    }
+}
index 9309359..b328933 100644 (file)
@@ -888,8 +888,20 @@ class SettingsProtoDumpUtil {
                 Settings.Global.ENABLE_EPHEMERAL_FEATURE,
                 GlobalSettingsProto.ENABLE_EPHEMERAL_FEATURE);
         dumpSetting(s, p,
-                Settings.Global.UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS,
-                GlobalSettingsProto.UNINSTALLED_EPHEMERAL_APP_CACHE_DURATION_MILLIS);
+                Settings.Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                GlobalSettingsProto.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD);
+        dumpSetting(s, p,
+                Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
+                GlobalSettingsProto.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD);
+        dumpSetting(s, p,
+                Settings.Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                GlobalSettingsProto.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD);
+        dumpSetting(s, p,
+                Settings.Global.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
+                GlobalSettingsProto.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD);
+        dumpSetting(s, p,
+                Settings.Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
+                GlobalSettingsProto.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD);
         dumpSetting(s, p,
                 Settings.Global.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED,
                 GlobalSettingsProto.ALLOW_USER_SWITCHING_WHEN_SYSTEM_USER_LOCKED);
index 455d9cb..f5d7dd8 100644 (file)
@@ -2212,11 +2212,7 @@ public class SettingsProvider extends ContentProvider {
                 throw new IllegalStateException("Key is corrupted", e);
             }
 
-            // Mac the package name and each of the signatures.
-            final String packageName = callingPkg.packageName;
-            byte[] packageNameBytes = packageName.getBytes(StandardCharsets.UTF_8);
-            m.update(getLengthPrefix(packageNameBytes), 0, 4);
-            m.update(packageNameBytes);
+            // Mac each of the developer signatures.
             for (int i = 0; i < callingPkg.signatures.length; i++) {
                 byte[] sig = callingPkg.signatures[i].toByteArray();
                 m.update(getLengthPrefix(sig), 0, 4);
@@ -2231,7 +2227,7 @@ public class SettingsProvider extends ContentProvider {
             final String uid = Integer.toString(callingPkg.applicationInfo.uid);
             final SettingsState ssaidSettings = getSettingsLocked(SETTINGS_TYPE_SSAID, userId);
             final boolean success = ssaidSettings.insertSettingLocked(uid, ssaid, null, true,
-                    packageName);
+                callingPkg.packageName);
 
             if (!success) {
                 throw new IllegalStateException("Ssaid settings not accessible");
index 1ddbcad..348b02a 100644 (file)
@@ -966,17 +966,24 @@ public class BugreportProgressService extends Service {
         }
 
         final Intent notifIntent;
+        boolean useChooser = true;
 
         // Send through warning dialog by default
         if (getWarningState(mContext, STATE_UNKNOWN) != STATE_HIDE) {
             notifIntent = buildWarningIntent(mContext, sendIntent);
+            // No need to show a chooser in this case.
+            useChooser = false;
         } else {
             notifIntent = sendIntent;
         }
         notifIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
 
         // Send the share intent...
-        sendShareIntent(mContext, notifIntent);
+        if (useChooser) {
+            sendShareIntent(mContext, notifIntent);
+        } else {
+            mContext.startActivity(notifIntent);
+        }
 
         // ... and stop watching this process.
         stopProgress(id);
index 79b02a5..c4e134b 100644 (file)
         <activity
             android:name=".settings.BrightnessDialog"
             android:label="@string/quick_settings_brightness_dialog_title"
-            android:theme="@android:style/Theme.DeviceDefault.Light.Dialog"
+            android:theme="@*android:style/Theme.DeviceDefault.QuickSettings.Dialog"
             android:finishOnCloseSystemDialogs="true"
             android:launchMode="singleInstance"
             android:excludeFromRecents="true"
index ed415b8..7e664d0 100644 (file)
@@ -25,7 +25,8 @@
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:gravity="center">
-    <TextClock android:id="@+id/date_view"
+    <com.android.systemui.statusbar.policy.DateView
+        android:id="@+id/date_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:textColor="@color/clock_white"
index 3fb86d0..1b6fa4c 100644 (file)
@@ -16,5 +16,5 @@
   -->
 
 <resources>
-    <dimen name="widget_big_font_size">64dp</dimen>
+    <dimen name="widget_big_font_size">72dp</dimen>
 </resources>
\ No newline at end of file
index 3fb86d0..1b6fa4c 100644 (file)
@@ -16,5 +16,5 @@
   -->
 
 <resources>
-    <dimen name="widget_big_font_size">64dp</dimen>
+    <dimen name="widget_big_font_size">72dp</dimen>
 </resources>
\ No newline at end of file
index 3ca6e69..41c723e 100644 (file)
@@ -41,7 +41,7 @@
     <!-- Default clock parameters -->
     <dimen name="bottom_text_spacing_digital">-1dp</dimen>
     <dimen name="widget_label_font_size">14sp</dimen>
-    <dimen name="widget_big_font_size">64dp</dimen>
+    <dimen name="widget_big_font_size">72dp</dimen>
 
     <!-- The y translation to apply at the start in appear animations. -->
     <dimen name="appear_y_translation_start">32dp</dimen>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml b/packages/SystemUI/res/drawable/ic_qs_signal_1x.xml
deleted file mode 100644 (file)
index 195849a..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 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="32.0dp"
-        android:height="32dp"
-        android:viewportWidth="12.0"
-        android:viewportHeight="12.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M3.500000,11.000000L1.800000,11.000000L1.800000,4.400000L0.200000,5.100000L0.200000,3.700000l3.100000,-1.300000l0.200000,0.000000L3.500000,11.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M8.600000,5.500000l1.200000,-3.000000l1.900000,0.000000L9.700000,6.700000l2.200000,4.300000L9.900000,11.000000L8.700000,7.900000L7.400000,11.000000L5.500000,11.000000l2.100000,-4.300000L5.600000,2.500000l1.900000,0.000000L8.600000,5.500000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_3g.xml
deleted file mode 100644 (file)
index 68c4307..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 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="32dp"
-        android:height="32dp"
-        android:viewportWidth="13.0"
-        android:viewportHeight="13.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M2.000000,6.000000l0.800000,0.000000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000s0.200000,-0.500000 0.200000,-0.900000c0.000000,-0.300000 -0.100000,-0.600000 -0.200000,-0.800000S3.200000,3.700000 2.900000,3.700000C2.700000,3.700000 2.500000,3.800000 2.300000,4.000000S2.100000,4.400000 2.100000,4.700000L0.500000,4.700000C0.500000,4.000000 0.700000,3.400000 1.100000,3.000000s1.000000,-0.600000 1.700000,-0.600000c0.800000,0.000000 1.400000,0.200000 1.900000,0.600000s0.700000,1.000000 0.700000,1.800000c0.000000,0.400000 -0.100000,0.700000 -0.300000,1.100000S4.600000,6.500000 4.300000,6.600000C4.700000,6.800000 5.000000,7.100000 5.200000,7.400000s0.300000,0.700000 0.300000,1.200000c0.000000,0.800000 -0.200000,1.400000 -0.700000,1.800000s-1.100000,0.700000 -1.900000,0.700000c-0.700000,0.000000 -1.300000,-0.200000 -1.800000,-0.600000s-0.700000,-1.000000 -0.700000,-1.800000L2.000000,8.700000C2.000000,9.000000 2.100000,9.300000 2.300000,9.500000s0.400000,0.300000 0.600000,0.300000c0.300000,0.000000 0.500000,-0.100000 0.700000,-0.300000S3.900000,9.000000 3.900000,8.600000c0.000000,-0.500000 -0.100000,-0.800000 -0.300000,-1.000000S3.200000,7.300000 2.800000,7.300000L2.000000,7.300000L2.000000,6.000000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.700000,9.000000 6.700000,7.900000L6.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000s-0.500000,-0.300000 -0.900000,-0.300000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S8.400000,5.000000 8.400000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.799999,7.800000L9.600000,7.800000L9.600000,6.600000l2.900000,0.000000L12.500000,9.900000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g.xml
deleted file mode 100644 (file)
index 61ecc9c..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 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="32.0dp"
-        android:height="32dp"
-        android:viewportWidth="12.0"
-        android:viewportHeight="12.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M4.600000,7.800000l0.700000,0.000000l0.000000,1.300000L4.600000,9.100000L4.600000,11.000000L3.000000,11.000000L3.000000,9.200000L0.100000,9.200000L0.000000,8.100000L3.000000,2.500000l1.700000,0.000000L4.700000,7.800000zM1.600000,7.800000L3.000000,7.800000l0.000000,-3.000000L2.900000,5.000000L1.600000,7.800000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M11.900000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S6.100000,9.000000 6.100000,7.900000L6.100000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000S8.100000,2.400000 9.000000,2.400000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000l-1.600000,0.000000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S9.500000,3.700000 9.000000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S7.700000,5.000000 7.700000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L10.099999,7.800000L9.000000,7.800000L9.000000,6.600000l2.900000,0.000000L11.900000,9.900000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_4g_plus.xml
deleted file mode 100644 (file)
index 782fbe4..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-    Copyright (C) 2016 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="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="19.0"
-        android:viewportHeight="19.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M4.6,7.8l0.7,0.0l0.0,1.3L4.6,9.1L4.6,11.0L3.0,11.0L3.0,9.2L0.1,9.2L0.0,8.2l3.0,-5.7l1.7,0.0L4.6,7.8L4.6,7.8zM1.7,7.8L3.0,7.8l0.0,-3.0L2.9,5.0L1.7,7.8z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M11.9,9.9c-0.2,0.4 -0.6,0.7 -1.0,0.9s-1.0,0.4 -1.8,0.4c-0.9,0.0 -1.7,-0.3 -2.2,-0.8S6.1,9.0 6.1,7.9L6.1,5.6c0.0,-1.1 0.3,-1.9 0.8,-2.4S8.2,2.4 9.0,2.4c1.0,0.0 1.7,0.2 2.1,0.7s0.7,1.2 0.7,2.1l-1.6,0.0c0.0,-0.5 -0.1,-0.9 -0.2,-1.1S9.5,3.7 9.0,3.7c-0.4,0.0 -0.7,0.2 -0.9,0.5S7.8,5.0 7.8,5.6l0.0,2.3c0.0,0.7 0.1,1.1 0.3,1.4c0.2,0.3 0.6,0.5 1.0,0.5c0.3,0.0 0.6,0.0 0.7,-0.1s0.3,-0.2 0.4,-0.3L10.2,7.8L9.0,7.8L9.0,6.6l2.9,0.0L11.9,9.9z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M17.7,4.4l-1.900001,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.900001,0.0z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml b/packages/SystemUI/res/drawable/ic_qs_signal_disabled.xml
deleted file mode 100644 (file)
index dd5843d..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<!--
-Copyright (C) 2014 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:autoMirrored="true"
-        android:width="32dp"
-        android:height="32dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.799999,22.299999l-1.199999,-1.299999 0.000000,0.000000 -9.600000,-10.000000 0.000000,0.000000 -6.400000,-6.700000 -1.300000,1.300000 6.400000,6.700000 -8.700000,8.700000 16.900000,0.000000 2.600000,2.700001z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M21.000000,1.000000l-8.600000,8.600000 8.600000,9.100000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_e.xml b/packages/SystemUI/res/drawable/ic_qs_signal_e.xml
deleted file mode 100644 (file)
index 4232126..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 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="32dp"
-        android:height="32dp"
-        android:viewportWidth="13.0"
-        android:viewportHeight="13.0">
-  <group
-    android:translateX="3.5" >
-    <path
-      android:fillColor="#FFFFFFFF"
-      android:pathData="M4.400000,7.300000L1.700000,7.300000l0.000000,2.400000l3.300000,0.000000L5.000000,11.000000L0.000000,11.000000L0.000000,2.500000l4.900000,0.000000l0.000000,1.300000L1.700000,3.800000l0.000000,2.100000l2.800000,0.000000L4.500000,7.300000z"/>
-  </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_g.xml b/packages/SystemUI/res/drawable/ic_qs_signal_g.xml
deleted file mode 100644 (file)
index 0c512d7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<!--
-Copyright (C) 2014 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="32dp"
-        android:height="32dp"
-        android:viewportWidth="13.0"
-        android:viewportHeight="13.0">
-    <group android:translateX="3.5" >
-      <path
-          android:fillColor="#FFFFFFFF"
-          android:pathData="M6.500000,9.900000c-0.200000,0.400000 -0.600000,0.700000 -1.000000,0.900000s-1.000000,0.400000 -1.800000,0.400000c-0.900000,0.000000 -1.700000,-0.300000 -2.200000,-0.800000S0.700000,9.000000 0.700000,7.900000L0.700000,5.600000c0.000000,-1.100000 0.300000,-1.900000 0.800000,-2.400000s1.200000,-0.800000 2.100000,-0.800000c1.000000,0.000000 1.700000,0.200000 2.100000,0.700000s0.700000,1.200000 0.700000,2.100000L4.700000,5.200000c0.000000,-0.500000 -0.100000,-0.900000 -0.200000,-1.100000S4.000000,3.700000 3.600000,3.700000c-0.400000,0.000000 -0.700000,0.200000 -0.900000,0.500000S2.300000,5.000000 2.300000,5.600000l0.000000,2.300000c0.000000,0.700000 0.100000,1.100000 0.300000,1.400000s0.600000,0.500000 1.000000,0.500000c0.300000,0.000000 0.600000,0.000000 0.700000,-0.100000s0.300000,-0.200000 0.400000,-0.300000L4.700000,7.800000L3.500000,7.800000L3.500000,6.600000l2.900000,0.000000L6.400000,9.900000z"/>
-    </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_h.xml b/packages/SystemUI/res/drawable/ic_qs_signal_h.xml
deleted file mode 100644 (file)
index b9572b2..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-<!--
-Copyright (C) 2014 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="32dp"
-        android:height="32dp"
-        android:viewportWidth="13.0"
-        android:viewportHeight="13.0">
-      <group
-        android:translateX="3.5" >
-        <path
-            android:fillColor="#FFFFFFFF"
-            android:pathData="M6.000000,11.000000L4.400000,11.000000L4.400000,7.500000L1.700000,7.500000L1.700000,11.000000L0.000000,11.000000L0.000000,2.500000l1.700000,0.000000l0.000000,3.700000l2.700000,0.000000L4.400000,2.500000L6.000000,2.500000L6.000000,11.000000z"/>
-      </group>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte.xml
deleted file mode 100644 (file)
index a381d03..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<!--
-Copyright (C) 2014 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="32dp"
-        android:height="32dp"
-        android:viewportWidth="13.0"
-        android:viewportHeight="13.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M2.000000,9.700000l2.000000,0.000000L4.000000,11.000000L0.300000,11.000000L0.300000,2.500000L2.000000,2.500000L2.000000,9.700000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M8.300000,3.800000L7.000000,3.800000L7.000000,11.000000L5.300000,11.000000L5.300000,3.800000L4.000000,3.800000L4.000000,2.500000l4.300000,0.000000L8.300000,3.800000z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.400000,7.300000l-1.700000,0.000000l0.000000,2.400000l2.100000,0.000000L12.799999,11.000000L9.000000,11.000000L9.000000,2.500000l3.700000,0.000000l0.000000,1.300000l-2.100000,0.000000l0.000000,2.100000l1.700000,0.000000L12.300000,7.300000z"/>
-</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml b/packages/SystemUI/res/drawable/ic_qs_signal_lte_plus.xml
deleted file mode 100644 (file)
index 3bed28a..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<!--
-    Copyright (C) 2016 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="32.0dp"
-        android:height="32.0dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0">
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M2.0,9.7l2.0,0.0L4.0,11.0L0.4,11.0L0.4,2.5L2.0,2.5L2.0,9.7z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M8.3,3.8L7.0,3.8L7.0,11.0L5.4,11.0L5.4,3.8L4.0,3.8L4.0,2.5l4.3,0.0L8.3,3.8z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.4,7.3l-1.7,0.0l0.0,2.4l2.1,0.0L12.799999,11.0L9.0,11.0L9.0,2.5l3.7,0.0l0.0,1.3l-2.1,0.0l0.0,2.1l1.7,0.0L12.4,7.3L12.4,7.3z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M18.4,4.4l-1.9,0.0 0.0,-1.9 -1.2,0.0 0.0,1.9 -1.900001,0.0 0.0,1.2 1.900001,0.0 0.0,1.9 1.2,0.0 0.0,-1.9 1.9,0.0z"/>
-</vector>
index f41c494..34e43ce 100644 (file)
     android:paddingBottom="8dp"
     android:visibility="invisible">
 
-    <com.android.systemui.ResizingSpace
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/qs_detail_margin_top" />
-
     <include
         android:id="@+id/qs_detail_header"
         layout="@layout/qs_detail_header"
index 871ed67..a1f0ee7 100644 (file)
     android:layout_height="wrap_content"
     android:paddingLeft="@dimen/qs_detail_header_padding"
     android:paddingTop="@dimen/qs_detail_header_padding"
-    android:paddingBottom="@dimen/qs_detail_header_bottom_padding"
+    android:paddingBottom="@dimen/qs_detail_items_padding_top"
     android:paddingEnd="@dimen/qs_panel_padding"
     android:background="@drawable/btn_borderless_rect"
+    android:orientation="vertical"
     android:gravity="center">
 
-    <TextView
-        android:id="@android:id/title"
-        android:paddingStart="@dimen/qs_detail_header_text_padding"
-        android:layout_width="0dp"
-        android:layout_height="wrap_content"
-        android:layout_weight="1"
-        android:textDirection="locale"
-        android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
-
-    <ImageView
-        android:id="@+id/settings"
-        android:layout_width="@dimen/qs_detail_image_width"
-        android:layout_height="@dimen/qs_detail_image_height"
-        android:background="?android:attr/selectableItemBackground"
-        android:padding="@dimen/qs_detail_image_padding"
-        android:src="@drawable/ic_settings"
-        android:visibility="gone"/>
-
-    <Switch
-        android:id="@android:id/toggle"
-        android:layout_width="wrap_content"
+    <com.android.systemui.ResizingSpace
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/qs_detail_margin_top" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:clickable="false"
-        android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+        android:orientation="horizontal">
+
+        <TextView
+            android:id="@android:id/title"
+            android:paddingStart="@dimen/qs_detail_header_text_padding"
+            android:layout_width="0dp"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:textDirection="locale"
+            android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+
+        <ImageView
+            android:id="@+id/settings"
+            android:layout_width="@dimen/qs_detail_image_width"
+            android:layout_height="@dimen/qs_detail_image_height"
+            android:background="?android:attr/selectableItemBackground"
+            android:padding="@dimen/qs_detail_image_padding"
+            android:src="@drawable/ic_settings"
+            android:visibility="gone"/>
+
+        <Switch
+            android:id="@android:id/toggle"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:clickable="false"
+            android:textAppearance="@style/TextAppearance.QS.DetailHeader" />
+
+    </LinearLayout>
 
 </com.android.keyguard.AlphaOptimizedLinearLayout>
index b9cdf28..60cba67 100644 (file)
@@ -20,7 +20,6 @@
     xmlns:sysui="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:paddingTop="@dimen/qs_detail_items_padding_top"
     android:paddingStart="@dimen/qs_detail_padding_start"
     android:paddingEnd="16dp">
 
index 577be2f..871d1f3 100644 (file)
@@ -27,6 +27,7 @@
     android:clipChildren="false"
     android:clipToPadding="false"
     android:paddingTop="0dp"
+    android:background="#00000000"
     android:gravity="center_vertical"
     android:orientation="horizontal">
 
index 005e955..97376c3 100644 (file)
     android:clickable="false"
     android:clipChildren="false"
     android:clipToPadding="false"
-    android:paddingBottom="48dp"
     android:paddingTop="0dp"
     android:paddingEnd="0dp"
     android:paddingStart="0dp">
 
     <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="24dp"
+        android:layout_height="32dp"
         android:layout_alignParentEnd="true"
         android:clipChildren="false"
         android:clipToPadding="false"
     <com.android.systemui.qs.QuickQSPanel
         android:id="@+id/quick_qs_panel"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="48dp"
         android:layout_alignParentEnd="true"
-        android:layout_marginTop="36dp"
-        android:layout_marginBottom="8dp"
+        android:layout_marginTop="31dp"
         android:layout_alignParentTop="true"
         android:accessibilityTraversalAfter="@+id/date_time_group"
         android:accessibilityTraversalBefore="@id/expand_indicator"
@@ -95,8 +93,7 @@
         android:layout_marginStart="8dp"
         android:layout_marginEnd="8dp"
         android:focusable="true"
-        android:importantForAccessibility="yes"
-        android:paddingTop="0dp"/>
+        android:importantForAccessibility="yes" />
 
     <com.android.systemui.statusbar.AlphaOptimizedImageView
         android:id="@+id/qs_detail_header_progress"
index 78b580f..3528f9e 100644 (file)
@@ -30,7 +30,7 @@
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:singleLine="true"
-        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Clock"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Date"
         android:textSize="@dimen/qs_time_collapsed_size"
         android:gravity="center_vertical"
         systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
index 8707840..200eabf 100644 (file)
@@ -36,7 +36,6 @@
             android:layout_height="wrap_content"
             android:layout_marginStart="16dp"
             android:layout_marginEnd="16dp"
-            android:layout_marginTop="8dp"
             android:layout_marginBottom="8dp" />
 
         <RelativeLayout
index 36ceff5..32f3ca5 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minute"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minute"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 uur"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 uur"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ONTDOEN"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Sluimer vir <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batterygebruik"</string>
index f9edd7c..a217d3c 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ደቂቃዎች"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 ደቂቃዎች"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ሰዓት"</string>
+    <!-- no translation found for snooze_option_2_hour (8332218255658969475) -->
+    <skip />
     <string name="snooze_undo" msgid="6074877317002985129">"ቀልብስ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"ለ<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> አሸልቧል"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"የባትሪ አጠቃቀም"</string>
index 4ab49a0..8281bf9 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"١٥ دقيقة"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"٣۰ دقيقة"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"ساعة واحدة"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"ساعتان"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"تراجع"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"تم تأجيل الإشعار لمدة <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"استخدام البطارية"</string>
index aca6a3b..40bd32a 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 dəqiqə"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 dəqiqə"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 saat"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 saat"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"GERİ QAYTARIN"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> üçün təxirə salınıb"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batareya istifadəsi"</string>
index 29a5e19..6e27760 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 sata"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Odloženo je za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
index 15f1d86..1096141 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 хвілін"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 хвілін"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 гадзіна"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 гадзіны"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"АДРАБІЦЬ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Адкладзена на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Выкарыстанне зараду"</string>
index b77cc9e..00a1a17 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минути"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 минути"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 часа"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ОТМЯНА"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Отложено за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Ползв. на батерията"</string>
index b9fa325..65ea6b1 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"১৫ মিনিট"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"৩০ মিনিট"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"১ ঘণ্টা"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"২ ঘণ্টা"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"পূর্বাবস্থায় ফিরুন"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> পরে আবার মনে করানো হবে"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ব্যাটারির ব্যবহার"</string>
index 11450ae..e420ae3 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 sata"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"OPOZOVI"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Odgođeno za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
index 16f2a32..d8292ec 100644 (file)
@@ -62,7 +62,7 @@
     <string name="always_use_accessory" msgid="1210954576979621596">"Utilitza de manera predet. per a l\'accessori USB"</string>
     <string name="usb_debugging_title" msgid="4513918393387141949">"Vols permetre la depuració USB?"</string>
     <string name="usb_debugging_message" msgid="2220143855912376496">"L\'empremta digital de la clau de l\'RSA de l\'equip és:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
-    <string name="usb_debugging_always" msgid="303335496705863070">"Dóna sempre permís des d\'aquest equip"</string>
+    <string name="usb_debugging_always" msgid="303335496705863070">"Dona sempre permís des d\'aquest equip"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"No es permet la depuració USB"</string>
     <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"L\'usuari que té iniciada la sessió al dispositiu en aquest moment no pot activar la depuració USB. Per utilitzar aquesta funció, cal canviar a l\'usuari administrador."</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"Zoom per omplir pantalla"</string>
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuts"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuts"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hores"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"DESFÉS"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"S\'ha posposat <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Ús de la bateria"</string>
index f4a45c2..84ee9ee 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minut"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minut"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hodina"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hodiny"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"VRÁTIT ZPĚT"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Odloženo o <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Využití baterie"</string>
index 55b39d5..3fb7acf 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 timer"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"FORTRYD"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Udsat i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batteriforbrug"</string>
index bc7f1d5..0697ead 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 Minuten"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 Minuten"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 Stunde"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 Stunden"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"RÜCKGÄNGIG"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Erinnerung in <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Akkunutzung"</string>
index bbefef4..094fd84 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 λεπτά"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 λεπτά"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ώρα"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ώρες"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ΑΝΑΙΡΕΣΗ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Σε αφύπνιση για <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Χρήση της μπαταρίας"</string>
index 2561d29..35263c2 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hours"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
index 2561d29..35263c2 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hours"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
index 2561d29..35263c2 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hour"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hours"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"UNDO"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozed for <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Battery usage"</string>
index 64a4bfe..3b77658 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Posponer <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
index 8d9f8a5..adba00a 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"DESHACER"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Volverá a mostrarse en <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Uso de la batería"</string>
index 604d266..f4605e0 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutit"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutit"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"Üks tund"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"kaks tundi"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"VÕTA TAGASI"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Edasi lükatud <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Akukasutus"</string>
index 2c83e5b..1919df3 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutu"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutu"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ordu"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ordu"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"DESEGIN"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>z atzeratu da"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Bateriaren erabilera"</string>
index 1f49e98..b16ff8e 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"۱۵ دقیقه"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"۳۰ دقیقه"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"۱ ساعت"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"۲ ساعت"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"واگرد"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> به تعویق افتاد"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"مصرف باتری"</string>
index f5b0b6b..f4e5616 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuuttia"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuuttia"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 tunti"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 tuntia"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"KUMOA"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Torkku: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Akun käyttö"</string>
index e615ff4..827958c 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 heure"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 heures"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ANNULER"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Reporté pour <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation de la pile"</string>
index 811b16c..e78c892 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutes"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutes"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 heure"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 heures"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ANNULER"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Répétée après <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Utilisation batterie"</string>
index 7481d1a..3cd4e71 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"DESFACER"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Adiouse <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Uso de batería"</string>
index ca7a779..2cb19ed 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 મિનિટ"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 મિનિટ"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 કલાક"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 કલાક"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"પૂર્વવત્ કરો"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> માટે સ્નૂઝ કરો"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"બૅટરી વપરાશ"</string>
index 92bc82e..e5c013f 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनट"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनट"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 घंटा"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 घंटे"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"पहले जैसा करें"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> के लिए याद दिलाया गया"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"बैटरी उपयोग"</string>
index 2065b8c..e71a6a6 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 sat"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 sata"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"PONIŠTI"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Odgođeno <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Potrošnja baterije"</string>
index d1e85d9..05dd386 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 perc"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 perc"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 óra"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 óra"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"VISSZAVONÁS"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Elhalasztva: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Akkumulátorhasználat"</string>
index 1189b05..12c4b60 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 րոպե"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 րոպե"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ժամ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ժամ"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ՀԵՏԱՐԿԵԼ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Հետաձգվել է <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ով"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Մարտկոցի օգտագործում"</string>
index ac7711b..0493584 100644 (file)
@@ -19,7 +19,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Նկարը նկարի մեջ"</string>
+    <string name="notification_channel_tv_pip" msgid="134047986446577723">"Նկար նկարի մեջ"</string>
     <string name="pip_notification_unknown_title" msgid="6289156118095849438">"(Առանց վերնագրի ծրագիր)"</string>
     <string name="pip_close" msgid="3480680679023423574">"Փակել PIP-ն"</string>
     <string name="pip_fullscreen" msgid="8604643018538487816">"Լիէկրան"</string>
index 25a2a14..5f72bb2 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 menit"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 menit"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 jam"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 jam"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"URUNG"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Ditunda selama <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Pemakaian baterai"</string>
index d2b9787..ce665e2 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 mínútur"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 mínútur"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 klukkustund"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 klukkustundir"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"AFTURKALLA"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Þaggað í <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Rafhlöðunotkun"</string>
index 01b2464..5ff02b0 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuti"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuti"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ore"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ANNULLA"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Posticipato di <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Utilizzo batteria"</string>
index b7e9508..b3a8146 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 דקות"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 דקות"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"שעה אחת"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"שעתיים"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ביטול"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"נדחה לטיפול בעוד <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"שימוש בסוללה"</string>
     <string name="headset" msgid="4534219457597457353">"אוזניות"</string>
     <string name="accessibility_status_bar_headphones" msgid="9156307120060559989">"אוזניות מחוברות"</string>
     <string name="accessibility_status_bar_headset" msgid="8666419213072449202">"אוזניות מחוברות"</string>
-    <string name="data_saver" msgid="5037565123367048522">"‏חוסך הנתונים&lt;br&gt;(Data Saver)"</string>
+    <string name="data_saver" msgid="5037565123367048522">"‏חוסך הנתונים (Data Saver)"</string>
     <string name="accessibility_data_saver_on" msgid="8454111686783887148">"‏חוסך הנתונים (Data Saver) פועל"</string>
     <string name="accessibility_data_saver_off" msgid="8841582529453005337">"‏חוסך הנתונים (Data Saver) כבוי"</string>
     <string name="switch_bar_on" msgid="1142437840752794229">"פועל"</string>
index 15fccc6..f63af80 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15分"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30分"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1時間"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2時間"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"元に戻す"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"スヌーズ: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"電池の使用状況"</string>
index 17320ef..5efe0ab 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 წუთი"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 წუთი"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 საათი"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 საათი"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"მოქმედების გაუქმება"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"ჩაჩუმებული იქნება <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ბატარეის მოხმარება"</string>
index 724af88..9478a96 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 сағат"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 сағат"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"КЕРІ ҚАЙТАРУ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> кідіртілді"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Батареяны пайдалану"</string>
index 229e345..6954d2b 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 នាទី"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 នាទី"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ម៉ោង"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ម៉ោង"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"មិន​ធ្វើវិញ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"បាន​ផ្អាក​រយៈពេល <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ការប្រើប្រាស់ថ្ម"</string>
index 9c87cf7..096416e 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ನಿಮಿಷಗಳು"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 ನಿಮಿಷಗಳು"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ಗಂಟೆ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ಗಂಟೆಗಳು"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ರದ್ದುಮಾಡಿ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ಗೆ ಸ್ನೂಜ್ ಮಾಡಲಾಗಿದೆ"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ಬ್ಯಾಟರಿ ಬಳಕೆ"</string>
index 273b390..cf5fc2c 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15분"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30분"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1시간"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2시간"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"실행취소"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> 동안 일시 중지됨"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"배터리 사용량"</string>
index 209d38d..aceb1c2 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 мүнөт"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 мүнөт"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 саат"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 саат"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"КАЙТАРУУ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> тындырылды"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Батарея колдонулушу"</string>
index 5369583..d7f1200 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ນາທີ"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 ນາທີ"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ຊົ່ວໂມງ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ຊົ່ວໂມງ"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ຍົກເລີກ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"ເລື່ອນໄປ <xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ນາທີແລ້ວ"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ການໃຊ້ແບັດເຕີຣີ"</string>
index cc123cf..8b03861 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 min."</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 min."</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 val."</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 val."</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ANULIUOTI"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Nustatyta snausti <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Akum. energ. vartoj."</string>
index 9bd3c65..26f4370 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minūtes"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minūtes"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 stunda"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 stundas"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ATSAUKT"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Atlikts: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Akumulatora lietojums"</string>
index 519cfac..4d4e227 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минути"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 минути"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 часа"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ВРАТИ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Одложено за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Користење батерија"</string>
index a7aa20a..67d7404 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 മിനിറ്റ്"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 മിനിറ്റ്"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"ഒരു മണിക്കൂർ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 മണിക്കൂർ"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"പഴയപടിയാക്കുക"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> സമയത്തേക്ക് സ്‌നൂസ് ‌ചെയ്‌തു"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ബാറ്ററി ഉപയോഗം"</string>
index 7144c28..ea5ab82 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 цаг"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 цаг"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"БУЦААХ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>-д түр хойшлуулсан"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Тэжээл ашиглалт"</string>
index f7360c9..fd6b0c3 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 मिनिटे"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 मिनिटे"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 तास"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 तास"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"पूर्ववत करा"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> साठी स्नूझ करा"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"बॅटरी वापर"</string>
index a05dd2b..46fcf43 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minit"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minit"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 jam"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 jam"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"BUAT ASAL"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Ditunda selama <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Penggunaan bateri"</string>
index 797aa97..dd7e923 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"၁၅ မိနစ်"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"၃၀ မိနစ်"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"၁ နာရီ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"၂ နာရီ"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"တစ်ဆင့် နောက်ပြန်ပြန်ပါ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ဆိုင်းငံ့ရန်"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ဘက်ထရီ အသုံးပြုမှု"</string>
index f59367f..3fdc266 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutter"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutter"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 time"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 timer"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ANGRE"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Slumrer i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batteribruk"</string>
index fb49b17..038587e 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"१५ मिनेट"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"३० मिनेट"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"१ घन्टा"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"२ घन्टा"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"अनडू गर्नुहोस्"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> का लागि स्नुज गरियो"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ब्याट्री उपयोग"</string>
index b708e66..040f0a8 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuten"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuten"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 uur"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 uur"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ONGEDAAN MAKEN"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozefunctie <xliff:g id="TIME_AMOUNT">%1$s</xliff:g> actief"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Accugebruik"</string>
index 1039e34..12b1dcb 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 ਮਿੰਟ"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 ਮਿੰਟ"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ਘੰਟਾ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ਘੰਟੇ"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ਅਣਕੀਤਾ ਕਰੋ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> ਲਈ ਸਨੂਜ਼ ਕੀਤਾ ਗਿਆ"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"ਬੈਟਰੀ ਵਰਤੋਂ"</string>
index 91a7c09..fd59150 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 min"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 min"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 godz."</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 godziny"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"COFNIJ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Odłożono na <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Wykorzystanie baterii"</string>
index ab705e7..7cd023c 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"Uma hora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"DESFAZER"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
index 74089b2..fe0859e 100644 (file)
     <string name="monitoring_description_managed_profile_ca_certificate" msgid="4683248196789897964">"A sua entidade instalou uma autoridade de certificação no seu perfil de trabalho. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
     <string name="monitoring_description_ca_certificate" msgid="7886985418413598352">"Está instalada uma autoridade de certificação neste dispositivo. O tráfego da sua rede segura pode ser monitorizado ou alterado."</string>
     <string name="monitoring_description_management_network_logging" msgid="7184005419733060736">"O administrador ativou os registos de rede, que monitorizam o tráfego no seu dispositivo."</string>
-    <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string>
-    <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"Está ligado às redes <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que podem monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string>
-    <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"O seu perfil de trabalho está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string>
-    <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"O seu perfil pessoal está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string>
+    <string name="monitoring_description_named_vpn" msgid="7403457334088909254">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
+    <string name="monitoring_description_two_named_vpns" msgid="4198511413729213802">"Está ligado às redes <xliff:g id="VPN_APP_0">%1$s</xliff:g> e <xliff:g id="VPN_APP_1">%2$s</xliff:g>, que podem monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
+    <string name="monitoring_description_managed_profile_named_vpn" msgid="1427905889862420559">"O seu perfil de trabalho está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
+    <string name="monitoring_description_personal_profile_named_vpn" msgid="3133980926929069283">"O seu perfil pessoal está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
     <string name="monitoring_description_do_header_generic" msgid="96588491028288691">"O seu dispositivo é gerido pelo <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g>."</string>
     <string name="monitoring_description_do_header_with_name" msgid="5511133708978206460">"A <xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> utiliza o <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g> para gerir o seu dispositivo."</string>
     <string name="monitoring_description_do_body" msgid="3639594537660975895">"O administ. pode monitorizar e gerir definições, acesso empresarial, aplic. e dados associados ao dispositivo, bem como inf. de localiz. do disp."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="3785251953067436862">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="1849514470437907421">"Saiba mais"</string>
-    <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string>
+    <string name="monitoring_description_do_body_vpn" msgid="8255218762488901796">"Está ligado à rede <xliff:g id="VPN_APP">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="1933186756733474388">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="8869300202410505143">"Abrir as definições de VPN"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="4987350385906393626">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="5489969458872997092">"Abrir credenciais fidedignas"</string>
     <string name="monitoring_description_network_logging" msgid="7223505523384076027">"O seu administrador ativou os registos de rede, que monitorizam o tráfego no seu dispositivo.\n\nPara obter mais informações, contacte o administrador."</string>
-    <string name="monitoring_description_vpn" msgid="4445150119515393526">"Concedeu autorização a uma aplicação para configurar uma ligação VPN.\n\nEsta aplicação pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Websites."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu administrador tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Websites.\n\nPara obter mais informações, contacte o administrador.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
+    <string name="monitoring_description_vpn" msgid="4445150119515393526">"Concedeu autorização a uma aplicação para configurar uma ligação VPN.\n\nEsta aplicação pode monitorizar a atividade do dispositivo e da rede, incluindo emails, aplicações e Sites."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="2958019119161161530">"O seu perfil de trabalho é gerido por <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nO seu administrador tem a capacidade de monitorizar a sua atividade da rede, incluindo emails, aplicações e Sites.\n\nPara obter mais informações, contacte o administrador.\n\nAlém disso, está ligado a uma VPN, que pode monitorizar a sua atividade da rede."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
-    <string name="monitoring_description_app" msgid="1828472472674709532">"Está associado à aplicação <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Websites."</string>
-    <string name="monitoring_description_app_personal" msgid="484599052118316268">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Websites."</string>
-    <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Está ligado ao <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Websites."</string>
-    <string name="monitoring_description_app_work" msgid="4612997849787922906">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nContacte o administrador para obter mais informações."</string>
-    <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Websites.\n\nTambém está associado à aplicação <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorizar a atividade da rede pessoal."</string>
+    <string name="monitoring_description_app" msgid="1828472472674709532">"Está associado à aplicação <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a sua atividade de rede, incluindo emails, aplicações e Sites."</string>
+    <string name="monitoring_description_app_personal" msgid="484599052118316268">"Está ligado a <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Sites."</string>
+    <string name="branded_monitoring_description_app_personal" msgid="2669518213949202599">"Está ligado ao <xliff:g id="APPLICATION">%1$s</xliff:g>, que pode monitorizar a atividade da rede pessoal, incluindo emails, aplicações e Sites."</string>
+    <string name="monitoring_description_app_work" msgid="4612997849787922906">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Sites.\n\nContacte o administrador para obter mais informações."</string>
+    <string name="monitoring_description_app_personal_work" msgid="5664165460056859391">"O seu perfil de trabalho é gerido pela <xliff:g id="ORGANIZATION">%1$s</xliff:g>. O perfil está associado à aplicação <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, que pode monitorizar a atividade da rede de trabalho, incluindo emails, aplicações e Sites.\n\nTambém está associado à aplicação <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, que pode monitorizar a atividade da rede pessoal."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"O dispositivo permanecerá bloqueado até ser desbloqueado manualmente"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Receber notificações mais rapidamente"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"Ver antes de desbloquear"</string>
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ANULAR"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Suspensa por <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Utiliz. da bateria"</string>
index ab705e7..7cd023c 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minutos"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minutos"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"Uma hora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 horas"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"DESFAZER"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Adiada para <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Uso da bateria"</string>
index cadce25..3fd6b9b 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minute"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 de minute"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 oră"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ore"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ANULAȚI"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Amânată <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Utilizarea bateriei"</string>
index 34939b5..2fa3ad2 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минут"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 минут"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 час"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 часа"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ОТМЕНИТЬ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Отложено на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Уровень заряда"</string>
index 7065c83..c8865ae 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"මිනිත්තු 15"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"මිනිත්තු 30"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"පැය 1"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"පැය 2"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"අස් කරන්න"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>ක් මදක් නතර කරන ලදී"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"බැටරි භාවිතය"</string>
index 6e4c33b..9d5eb79 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minút"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minút"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 hod."</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 hodiny"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"SPÄŤ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Stlmené na <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Využitie batérie"</string>
index b0e770f..8289516 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minut"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minut"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ura"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 uri"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"RAZVELJAVI"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Preloženo za <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Poraba akumulatorja"</string>
index a68ec87..15cc542 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuta"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuta"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 orë"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 orë"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ZHBËJ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"U shty për <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Përdorimi i baterisë"</string>
index f4b4884..4ef7267 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 минута"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 минута"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 сат"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 сата"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ОПОЗОВИ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Одложено је за <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Потрошња батерије"</string>
index 685c0a4..a479bea 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuter"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuter"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 timme"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 timmar"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ÅNGRA"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Snoozad i <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batteriförbrukning"</string>
index 9a52d9b..adbf29b 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"Dakika 15"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"Dakika 30"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"Saa 1"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"Saa 2"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"TENDUA"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Imeahirishwa kwa <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Matumizi ya betri"</string>
index 1c4b7de..ea75cec 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 நிமிடங்கள்"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 நிமிடங்கள்"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 மணிநேரம்"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 மணிநேரம்"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"செயல்தவிர்"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"உறக்கநிலையில் வைத்திருந்த நேரம்: <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"பேட்டரி உபயோகம்"</string>
index 2bdabd2..97763d4 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 నిమిషాలు"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 నిమిషాలు"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 గంట"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 గంటలు"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"చర్య రద్దు చేయి"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> వరకు తాత్కాలికంగా ఆపివేయబడింది"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"బ్యాటరీ వినియోగం"</string>
index 8077d14..28957c5 100644 (file)
@@ -64,7 +64,7 @@
     <string name="usb_debugging_message" msgid="2220143855912376496">"ลายนิ้วมือหลัก RSA ของคอมพิวเตอร์คือ:\n<xliff:g id="FINGERPRINT">%1$s</xliff:g>"</string>
     <string name="usb_debugging_always" msgid="303335496705863070">"อนุญาตจากคอมพิวเตอร์เครื่องนี้เสมอ"</string>
     <string name="usb_debugging_secondary_user_title" msgid="6353808721761220421">"ไม่อนุญาตให้แก้ไขข้อบกพร่องผ่าน USB"</string>
-    <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89าà¹\83à¸\8aà¹\89อุà¸\9bà¸\81รà¸\93à¹\8cà¸\99ีà¹\89อยูà¹\88à¹\83à¸\99à¸\82à¸\93ะà¸\99ีà¹\89à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bิà¸\94à¸\81ารà¹\81à¸\81à¹\89à¸\9bัà¸\8dหาà¸\9cà¹\88าà¸\99 USB à¹\84à¸\94à¹\89 à¸«à¸²à¸\81à¸\95à¹\89อà¸\87à¸\81ารà¹\83à¸\8aà¹\89à¸\84ุà¸\93ลัà¸\81ษà¸\93ะนี้ โปรดเปลี่ยนไปเป็นผู้ใช้ที่เป็นผู้ดูแลระบบ"</string>
+    <string name="usb_debugging_secondary_user_message" msgid="8572228137833020196">"à¸\9cูà¹\89à¹\83à¸\8aà¹\89à¸\97ีà¹\88ลà¸\87à¸\8aืà¹\88อà¹\80à¸\82à¹\89าà¹\83à¸\8aà¹\89อุà¸\9bà¸\81รà¸\93à¹\8cà¸\99ีà¹\89อยูà¹\88à¹\83à¸\99à¸\82à¸\93ะà¸\99ีà¹\89à¹\84มà¹\88สามารà¸\96à¹\80à¸\9bิà¸\94à¸\81ารà¹\81à¸\81à¹\89à¸\9bัà¸\8dหาà¸\9cà¹\88าà¸\99 USB à¹\84à¸\94à¹\89 à¸«à¸²à¸\81à¸\95à¹\89อà¸\87à¸\81ารà¹\83à¸\8aà¹\89à¸\9fีà¹\80à¸\88อรà¹\8cนี้ โปรดเปลี่ยนไปเป็นผู้ใช้ที่เป็นผู้ดูแลระบบ"</string>
     <string name="compat_mode_on" msgid="6623839244840638213">"ขยายจนเต็มหน้าจอ"</string>
     <string name="compat_mode_off" msgid="4434467572461327898">"ยืดจนเต็มหน้าจอ"</string>
     <string name="screenshot_saving_ticker" msgid="7403652894056693515">"กำลังบันทึกภาพหน้าจอ..."</string>
     <string name="accessibility_status_bar_hotspot" msgid="4099381329956402865">"ฮอตสปอต"</string>
     <string name="accessibility_managed_profile" msgid="6613641363112584120">"โปรไฟล์งาน"</string>
     <string name="tuner_warning_title" msgid="7094689930793031682">"เพลิดเพลินกับบางส่วนแต่ไม่ใช่ทั้งหมด"</string>
-    <string name="tuner_warning" msgid="8730648121973575701">"à¸\95ัวรัà¸\9aสัà¸\8dà¸\8dาà¸\93 UI à¸£à¸°à¸\9aà¸\9aà¸\8aà¹\88วยà¹\83หà¹\89à¸\84ุà¸\93มีวิà¸\98ีà¸\9eิà¹\80ศษà¹\83à¸\99à¸\81ารà¸\9bรัà¸\9aà¹\81à¸\95à¹\88à¸\87à¹\81ละà¸\81ำหà¸\99à¸\94à¸\84à¹\88าสà¹\88วà¸\99à¸\95ิà¸\94à¸\95à¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89 Android à¸\84ุà¸\93ลัà¸\81ษà¸\93ะรุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
-    <string name="tuner_persistent_warning" msgid="8597333795565621795">"à¸\84ุà¸\93ลัà¸\81ษà¸\93ะรุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
+    <string name="tuner_warning" msgid="8730648121973575701">"à¸\95ัวรัà¸\9aสัà¸\8dà¸\8dาà¸\93 UI à¸£à¸°à¸\9aà¸\9aà¸\8aà¹\88วยà¹\83หà¹\89à¸\84ุà¸\93มีวิà¸\98ีà¸\9eิà¹\80ศษà¹\83à¸\99à¸\81ารà¸\9bรัà¸\9aà¹\81à¸\95à¹\88à¸\87à¹\81ละà¸\81ำหà¸\99à¸\94à¸\84à¹\88าสà¹\88วà¸\99à¸\95ิà¸\94à¸\95à¹\88อà¸\9cูà¹\89à¹\83à¸\8aà¹\89 Android à¸\9fีà¹\80à¸\88อรà¹\8cรุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
+    <string name="tuner_persistent_warning" msgid="8597333795565621795">"à¸\9fีà¹\80à¸\88อรà¹\8cรุ่นทดลองเหล่านี้อาจมีการเปลี่ยนแปลง ขัดข้อง หรือหายไปในเวอร์ชันอนาคต โปรดดำเนินการด้วยความระมัดระวัง"</string>
     <string name="got_it" msgid="2239653834387972602">"รับทราบ"</string>
     <string name="tuner_toast" msgid="603429811084428439">"ยินดีด้วย! เพิ่มตัวรับสัญญาณ UI ระบบไปยังการตั้งค่าแล้ว"</string>
     <string name="remove_from_settings" msgid="8389591916603406378">"นำออกจากการตั้งค่า"</string>
-    <string name="remove_from_settings_prompt" msgid="6069085993355887748">"à¸\99ำà¸\95ัวรัà¸\9aสัà¸\8dà¸\8dาà¸\93 UI à¸£à¸°à¸\9aà¸\9aออà¸\81à¸\88าà¸\81à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¹\81ละหยุà¸\94à¹\83à¸\8aà¹\89à¸\84ุà¸\93ลัà¸\81ษà¸\93ะทั้งหมดของตัวรับสัญญาณใช่ไหม"</string>
+    <string name="remove_from_settings_prompt" msgid="6069085993355887748">"à¸\99ำà¸\95ัวรัà¸\9aสัà¸\8dà¸\8dาà¸\93 UI à¸£à¸°à¸\9aà¸\9aออà¸\81à¸\88าà¸\81à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¹\81ละหยุà¸\94à¹\83à¸\8aà¹\89à¸\9fีà¹\80à¸\88อรà¹\8cทั้งหมดของตัวรับสัญญาณใช่ไหม"</string>
     <string name="activity_not_found" msgid="348423244327799974">"ยังไม่ได้ติดตั้งแอปพลิเคชันบนอุปกรณ์ของคุณ"</string>
     <string name="clock_seconds" msgid="7689554147579179507">"แสดงวินาทีของนาฬิกา"</string>
     <string name="clock_seconds_desc" msgid="6282693067130470675">"แสดงวินาทีของนาฬิกาในแถบสถานะ อาจส่งผลต่ออายุแบตเตอรี"</string>
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 นาที"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 นาที"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ชั่วโมง"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 ชั่วโมง"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"เลิกทำ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"ปิดเสียงเตือนชั่วคราวไว้เป็นเวลา <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"การใช้งานแบตเตอรี่"</string>
     <string name="pip_phone_dismiss_hint" msgid="6351678169095923899">"ลากลงเพื่อปิด"</string>
     <string name="pip_menu_title" msgid="3328510504196964712">"เมนูการแสดงผลหลายแหล่งพร้อมกัน"</string>
     <string name="pip_notification_title" msgid="3204024940158161322">"<xliff:g id="NAME">%s</xliff:g> ใช้การแสดงผลหลายแหล่งพร้อมกัน"</string>
-    <string name="pip_notification_message" msgid="4171698133469539591">"หาà¸\81à¸\84ุà¸\93à¹\84มà¹\88à¸\95à¹\89อà¸\87à¸\81ารà¹\83หà¹\89 <xliff:g id="NAME">%s</xliff:g> à¹\83à¸\8aà¹\89à¸\84ุà¸\93ลัà¸\81ษà¸\93ะà¸\99ีà¹\89 à¹\83หà¹\89à¹\81à¸\95ะà¹\80à¸\9eืà¹\88อà¹\80à¸\9bิà¸\94à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¹\81ลà¹\89วà¸\9bิà¸\94à¸\84ุà¸\93ลัà¸\81ษà¸\93ะ"</string>
+    <string name="pip_notification_message" msgid="4171698133469539591">"หาà¸\81à¸\84ุà¸\93à¹\84มà¹\88à¸\95à¹\89อà¸\87à¸\81ารà¹\83หà¹\89 <xliff:g id="NAME">%s</xliff:g> à¹\83à¸\8aà¹\89à¸\9fีà¹\80à¸\88อรà¹\8cà¸\99ีà¹\89 à¹\83หà¹\89à¹\81à¸\95ะà¹\80à¸\9eืà¹\88อà¹\80à¸\9bิà¸\94à¸\81ารà¸\95ัà¹\89à¸\87à¸\84à¹\88าà¹\81ลà¹\89วà¸\9bิà¸\94à¸\9fีà¹\80à¸\88อรà¹\8c"</string>
     <string name="pip_play" msgid="1417176722760265888">"เล่น"</string>
     <string name="pip_pause" msgid="8881063404466476571">"หยุดชั่วคราว"</string>
     <string name="pip_skip_to_next" msgid="1948440006726306284">"ข้ามไปรายการถัดไป"</string>
     <string name="thermal_shutdown_message" msgid="9006456746902370523">"ขณะนี้โทรศัพท์ทำงานเป็นปกติ"</string>
     <string name="thermal_shutdown_dialog_message" msgid="566347880005304139">"โทรศัพท์ร้อนเกินไปจึงปิดเครื่องเพื่อให้เย็นลง ขณะนี้โทรศัพท์ทำงานเป็นปกติ\n\nโทรศัพท์อาจร้อนเกินไปหากคุณ\n        • ใช้แอปที่ใช้ทรัพยากรมาก (เช่น เกม วิดีโอ หรือแอปการนำทาง)\n   • ดาวน์โหลดหรืออัปโหลดไฟล์ขนาดใหญ่\n  • ใช้โทรศัพท์ในอุณหภูมิที่สูง"</string>
     <string name="high_temp_title" msgid="4589508026407318374">"โทรศัพท์เริ่มเครื่องร้อน"</string>
-    <string name="high_temp_notif_message" msgid="5642466103153429279">"à¸\84ุà¸\93ลัà¸\81ษà¸\93ะบางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์ลดอุณหภูมิลง"</string>
+    <string name="high_temp_notif_message" msgid="5642466103153429279">"à¸\9fีà¹\80à¸\88อรà¹\8cบางอย่างจะใช้งานได้จำกัดขณะโทรศัพท์ลดอุณหภูมิลง"</string>
     <string name="high_temp_dialog_message" msgid="6840700639374113553">"โทรศัพท์จะพยายามลดอุณหภูมิลงโดยอัตโนมัติ คุณยังสามารถใช้โทรศัพท์ได้ แต่โทรศัพท์อาจทำงานช้าลง\n\nโทรศัพท์จะทำงานตามปกติเมื่อเย็นลงแล้ว"</string>
     <string name="lockscreen_shortcut_left" msgid="2182769107618938629">"ทางลัดทางซ้าย"</string>
     <string name="lockscreen_shortcut_right" msgid="3328683699505226536">"ทางลัดทางขวา"</string>
index 194b161..4788a0e 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 minuto"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 minuto"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 oras"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 oras"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"I-UNDO"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Na-snooze ng <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Paggamit ng baterya"</string>
index 7f1d8ff..903f2c8 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 dakika"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 dakika"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 saat"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 saat"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"GERİ AL"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> süreyle ertelendi"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Pil kullanımı"</string>
index 1006eae..937822c 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 хвилин"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 хвилин"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 годину"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 години"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"ВІДМІНИТИ"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Відкладено на <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Використання заряду"</string>
index 9f28494..23a0626 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 منٹ"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 منٹ"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 گھنٹہ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 گھنٹے"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"کالعدم کریں"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> کیلئے اسنوز کیا گیا"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"بیٹری کا استعمال"</string>
index 02f7c43..530b317 100644 (file)
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Parvoz rejimi o‘chirildi."</string>
     <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Parvoz rejimi yoqildi."</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"“Bezovta qilinmasin” funksiyasi yoqilgan, faqat muhim bildirishnomalar ko‘rsatiladi."</string>
-    <string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"Bezovta qilinmasin, tinchlik saqlansin"</string>
+    <string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"Bezovta qilinmasin, jimjitlik."</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Bezovta qilinmasin, faqat signallar"</string>
     <string name="accessibility_quick_settings_dnd" msgid="6607873236717185815">"Bezovta qilinmasin."</string>
     <string name="accessibility_quick_settings_dnd_off" msgid="2371832603753738581">"“Bezovta qilinmasin” funksiyasi o‘chirilgan."</string>
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 daqiqa"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 daqiqa"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 soat"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 soat"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"BEKOR QILISH"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"<xliff:g id="TIME_AMOUNT">%1$s</xliff:g> muddatga kechiktirildi"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Batareya sarfi"</string>
index 167d0a1..29c70c6 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 phút"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 phút"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 giờ"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 giờ"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"HOÀN TÁC"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Báo lại sau <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Mức sử dụng pin"</string>
index cf9b7d2..33dc240 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 分钟"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 分钟"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小时"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 小时"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"撤消"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"已延后 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"电池使用情况"</string>
index d123c93..cab3aea 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 分鐘"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 分鐘"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小時"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 小時"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"復原"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"已延後 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string>
index af7ed48..9526426 100644 (file)
     <string name="ethernet_label" msgid="7967563676324087464">"乙太網路"</string>
     <string name="quick_settings_dnd_label" msgid="8735855737575028208">"零打擾"</string>
     <string name="quick_settings_dnd_priority_label" msgid="483232950670692036">"僅限優先通知"</string>
-    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"僅允許鬧鐘"</string>
+    <string name="quick_settings_dnd_alarms_label" msgid="2559229444312445858">"僅鬧鐘"</string>
     <string name="quick_settings_dnd_none_label" msgid="5025477807123029478">"完全靜音"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"藍牙"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"藍牙 (<xliff:g id="NUMBER">%d</xliff:g> 個裝置)"</string>
     <string name="interruption_level_none_with_warning" msgid="5114872171614161084">"完全靜音。這也會關閉螢幕閱讀器的音訊。"</string>
     <string name="interruption_level_none" msgid="6000083681244492992">"完全靜音"</string>
     <string name="interruption_level_priority" msgid="6426766465363855505">"僅限優先通知"</string>
-    <string name="interruption_level_alarms" msgid="5226306993448328896">"僅允許鬧鐘"</string>
+    <string name="interruption_level_alarms" msgid="5226306993448328896">"僅鬧鐘"</string>
     <string name="interruption_level_none_twoline" msgid="3957581548190765889">"完全\n靜音"</string>
     <string name="interruption_level_priority_twoline" msgid="1564715335217164124">"僅允許\n優先通知"</string>
     <string name="interruption_level_alarms_twoline" msgid="3266909566410106146">"僅允許\n鬧鐘"</string>
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 分鐘"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 分鐘"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 小時"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 小時"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"復原"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"已延後 <xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"電池用量"</string>
index c1765c6..80ce905 100644 (file)
     <string name="snooze_option_15_min" msgid="1068727451405610715">"15 amaminithi"</string>
     <string name="snooze_option_30_min" msgid="867081342535195788">"30 amaminithi"</string>
     <string name="snooze_option_1_hour" msgid="1098086401880077154">"1 ihora"</string>
+    <string name="snooze_option_2_hour" msgid="8332218255658969475">"2 amahora"</string>
     <string name="snooze_undo" msgid="6074877317002985129">"HLEHLISA"</string>
     <string name="snoozed_for_time" msgid="2390718332980204462">"Kusnuzwe u-<xliff:g id="TIME_AMOUNT">%1$s</xliff:g>"</string>
     <string name="battery_panel_title" msgid="7944156115535366613">"Ukusetshenziswa kwebhethri"</string>
index 6604b6c..4245b11 100644 (file)
     <dimen name="qs_panel_padding_bottom">0dp</dimen>
     <dimen name="qs_detail_header_height">56dp</dimen>
     <dimen name="qs_detail_header_padding">0dp</dimen>
-    <dimen name="qs_detail_header_bottom_padding">0dp</dimen>
     <dimen name="qs_detail_image_width">56dp</dimen>
     <dimen name="qs_detail_image_height">56dp</dimen>
     <dimen name="qs_detail_image_padding">16dp</dimen>
index 44da876..d98b789 100644 (file)
 
     <style name="TextAppearance.StatusBar.Expanded.Clock">
         <item name="android:textSize">@dimen/qs_time_expanded_size</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:fontFamily">sans-serif-medium</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
         <item name="android:textStyle">normal</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.Date">
-        <item name="android:textSize">@dimen/qs_date_collapsed_size</item>
+        <item name="android:textSize">@dimen/qs_time_expanded_size</item>
         <item name="android:textStyle">normal</item>
-        <item name="android:textColor">?android:attr/textColorSecondary</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
+        <item name="android:fontFamily">sans-serif</item>
     </style>
 
     <style name="TextAppearance.StatusBar.Expanded.AboveDateTime">
index f0ff22d..d214d55 100644 (file)
@@ -37,6 +37,7 @@ import android.widget.TextView;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.ChargingView;
+import com.android.systemui.statusbar.policy.DateView;
 
 import java.util.Locale;
 
@@ -48,7 +49,7 @@ public class KeyguardStatusView extends GridLayout {
     private final AlarmManager mAlarmManager;
 
     private TextView mAlarmStatusView;
-    private TextClock mDateView;
+    private DateView mDateView;
     private TextClock mClockView;
     private TextView mOwnerInfo;
     private ViewGroup mClockContainer;
@@ -118,7 +119,6 @@ public class KeyguardStatusView extends GridLayout {
         mAlarmStatusView = findViewById(R.id.alarm_status);
         mDateView = findViewById(R.id.date_view);
         mClockView = findViewById(R.id.clock_view);
-        mDateView.setShowCurrentUserTime(true);
         mClockView.setShowCurrentUserTime(true);
         mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
         mOwnerInfo = findViewById(R.id.owner_info);
@@ -147,13 +147,14 @@ public class KeyguardStatusView extends GridLayout {
         mClockView.setLayoutParams(layoutParams);
         mDateView.setTextSize(TypedValue.COMPLEX_UNIT_PX,
                 getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
-        mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
+        if (mOwnerInfo != null) {
+            mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
+                    getResources().getDimensionPixelSize(R.dimen.widget_label_font_size));
+        }
     }
 
     public void refreshTime() {
-        mDateView.setFormat24Hour(Patterns.dateView);
-        mDateView.setFormat12Hour(Patterns.dateView);
+        mDateView.setDatePattern(Patterns.dateViewSkel);
 
         mClockView.setFormat12Hour(Patterns.clockView12);
         mClockView.setFormat24Hour(Patterns.clockView24);
@@ -244,7 +245,7 @@ public class KeyguardStatusView extends GridLayout {
     // DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
     // This is an optimization to ensure we only recompute the patterns when the inputs change.
     private static final class Patterns {
-        static String dateView;
+        static String dateViewSkel;
         static String clockView12;
         static String clockView24;
         static String cacheKey;
@@ -252,7 +253,7 @@ public class KeyguardStatusView extends GridLayout {
         static void update(Context context, boolean hasAlarm) {
             final Locale locale = Locale.getDefault();
             final Resources res = context.getResources();
-            final String dateViewSkel = res.getString(hasAlarm
+            dateViewSkel = res.getString(hasAlarm
                     ? R.string.abbrev_wday_month_day_no_year_alarm
                     : R.string.abbrev_wday_month_day_no_year);
             final String clockView12Skel = res.getString(R.string.clock_12hr_format);
@@ -260,8 +261,6 @@ public class KeyguardStatusView extends GridLayout {
             final String key = locale.toString() + dateViewSkel + clockView12Skel + clockView24Skel;
             if (key.equals(cacheKey)) return;
 
-            dateView = DateFormat.getBestDateTimePattern(locale, dateViewSkel);
-
             clockView12 = DateFormat.getBestDateTimePattern(locale, clockView12Skel);
             // CLDR insists on adding an AM/PM indicator even though it wasn't in the skeleton
             // format.  The following code removes the AM/PM indicator if we didn't want it.
index 0cf8ff0..8ba33c3 100644 (file)
@@ -264,6 +264,9 @@ public class Dependency extends SystemUI {
         mProviders.put(AccessibilityManagerWrapper.class,
                 () -> new AccessibilityManagerWrapper(mContext));
 
+        mProviders.put(ForegroundServiceController.class,
+                () -> new ForegroundServiceControllerImpl(mContext));
+
         mProviders.put(UiOffloadThread.class, UiOffloadThread::new);
 
         // Put all dependencies above here so the factory can override them if it wants.
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceController.java
new file mode 100644 (file)
index 0000000..a2c9ab4
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.service.notification.StatusBarNotification;
+
+public interface ForegroundServiceController {
+    /**
+     * @param sbn notification that was just posted
+     * @param importance
+     */
+    void addNotification(StatusBarNotification sbn, int importance);
+
+    /**
+     * @param sbn notification that was just changed in some way
+     * @param newImportance
+     */
+    void updateNotification(StatusBarNotification sbn, int newImportance);
+
+    /**
+     * @param sbn notification that was just canceled
+     */
+    boolean removeNotification(StatusBarNotification sbn);
+
+    /**
+     * @param userId
+     * @return true if this user has services missing notifications and therefore needs a
+     * disclosure notification.
+     */
+    boolean isDungeonNeededForUser(int userId);
+
+    /**
+     * @param sbn
+     * @return true if sbn is the system-provided "dungeon" (list of running foreground services).
+     */
+    boolean isDungeonNotification(StatusBarNotification sbn);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java b/packages/SystemUI/src/com/android/systemui/ForegroundServiceControllerImpl.java
new file mode 100644 (file)
index 0000000..c930d56
--- /dev/null
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Bundle;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto;
+
+import java.util.Arrays;
+
+/**
+ * Foreground service controller, a/k/a Dianne's Dungeon.
+ */
+public class ForegroundServiceControllerImpl
+        implements ForegroundServiceController {
+    private static final String TAG = "FgServiceController";
+    private static final boolean DBG = false;
+
+    private final SparseArray<UserServices> mUserServices = new SparseArray<>();
+    private final Object mMutex = new Object();
+
+    public ForegroundServiceControllerImpl(Context context) {
+    }
+
+    @Override
+    public boolean isDungeonNeededForUser(int userId) {
+        synchronized (mMutex) {
+            final UserServices services = mUserServices.get(userId);
+            if (services == null) return false;
+            return services.isDungeonNeeded();
+        }
+    }
+
+    @Override
+    public void addNotification(StatusBarNotification sbn, int importance) {
+        updateNotification(sbn, importance);
+    }
+
+    @Override
+    public boolean removeNotification(StatusBarNotification sbn) {
+        synchronized (mMutex) {
+            final UserServices userServices = mUserServices.get(sbn.getUserId());
+            if (userServices == null) {
+                if (DBG) {
+                    Log.w(TAG, String.format(
+                            "user %d with no known notifications got removeNotification for %s",
+                            sbn.getUserId(), sbn));
+                }
+                return false;
+            }
+            if (isDungeonNotification(sbn)) {
+                // if you remove the dungeon entirely, we take that to mean there are
+                // no running services
+                userServices.setRunningServices(null);
+                return true;
+            } else {
+                // this is safe to call on any notification, not just FLAG_FOREGROUND_SERVICE
+                return userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
+            }
+        }
+    }
+
+    @Override
+    public void updateNotification(StatusBarNotification sbn, int newImportance) {
+        synchronized (mMutex) {
+            UserServices userServices = mUserServices.get(sbn.getUserId());
+            if (userServices == null) {
+                userServices = new UserServices();
+                mUserServices.put(sbn.getUserId(), userServices);
+            }
+
+            if (isDungeonNotification(sbn)) {
+                final Bundle extras = sbn.getNotification().extras;
+                if (extras != null) {
+                    final String[] svcs = extras.getStringArray(Notification.EXTRA_FOREGROUND_APPS);
+                    userServices.setRunningServices(svcs); // null ok
+                }
+            } else {
+                userServices.removeNotification(sbn.getPackageName(), sbn.getKey());
+                if (0 != (sbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE)
+                        && newImportance > NotificationManager.IMPORTANCE_MIN) {
+                    userServices.addNotification(sbn.getPackageName(), sbn.getKey());
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean isDungeonNotification(StatusBarNotification sbn) {
+        return sbn.getId() == SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES
+                && sbn.getTag() == null
+                && sbn.getPackageName().equals("android");
+    }
+
+    /**
+     * Struct to track relevant packages and notifications for a userid's foreground services.
+     */
+    private static class UserServices {
+        private String[] mRunning = null;
+        private ArrayMap<String, ArraySet<String>> mNotifications = new ArrayMap<>(1);
+        public void setRunningServices(String[] pkgs) {
+            mRunning = pkgs != null ? Arrays.copyOf(pkgs, pkgs.length) : null;
+        }
+        public void addNotification(String pkg, String key) {
+            if (mNotifications.get(pkg) == null) {
+                mNotifications.put(pkg, new ArraySet<String>());
+            }
+            mNotifications.get(pkg).add(key);
+        }
+        public boolean removeNotification(String pkg, String key) {
+            final boolean found;
+            final ArraySet<String> keys = mNotifications.get(pkg);
+            if (keys == null) {
+                found = false;
+            } else {
+                found = keys.remove(key);
+                if (keys.size() == 0) {
+                    mNotifications.remove(pkg);
+                }
+            }
+            return found;
+        }
+        public boolean isDungeonNeeded() {
+            if (mRunning != null) {
+                for (String pkg : mRunning) {
+                    final ArraySet<String> set = mNotifications.get(pkg);
+                    if (set == null || set.size() == 0) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+    }
+}
index 09fdf5a..3b81cc4 100644 (file)
@@ -92,7 +92,9 @@ public class AssistManager implements ConfigurationChangedReceiver {
         mAssistDisclosure = new AssistDisclosure(context, new Handler());
 
         registerVoiceInteractionSessionListener();
-        mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION);
+        mInterestingConfigChanges = new InterestingConfigChanges(ActivityInfo.CONFIG_ORIENTATION
+                | ActivityInfo.CONFIG_LOCALE | ActivityInfo.CONFIG_UI_MODE
+                | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
         onConfigurationChanged(context.getResources().getConfiguration());
     }
 
index 8ac97f3..ee155d9 100644 (file)
@@ -49,7 +49,8 @@ public class FragmentHostManager {
     private final HashMap<String, ArrayList<FragmentListener>> mListeners = new HashMap<>();
     private final View mRootView;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
-            ActivityInfo.CONFIG_FONT_SCALE);
+            ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
+                | ActivityInfo.CONFIG_SCREEN_LAYOUT | ActivityInfo.CONFIG_ASSETS_PATHS);
     private final FragmentService mManager;
     private final PluginFragmentManager mPlugins = new PluginFragmentManager();
 
index 3532f41..2d5d198 100644 (file)
@@ -194,6 +194,12 @@ public class KeyguardService extends Service {
             mKeyguardViewMediator.startKeyguardExitAnimation(startTime, fadeoutDuration);
             Trace.endSection();
         }
+
+        @Override
+        public void onShortPowerPressedGoHome() {
+            checkPermission();
+            mKeyguardViewMediator.onShortPowerPressedGoHome();
+        }
     };
 }
 
index b977dd4..f745956 100644 (file)
@@ -2013,6 +2013,10 @@ public class KeyguardViewMediator extends SystemUI {
         Trace.endSection();
     }
 
+    public void onShortPowerPressedGoHome() {
+        // do nothing
+    }
+
     public ViewMediatorCallback getViewMediatorCallback() {
         return mViewMediatorCallback;
     }
index c35fdd5..854696e 100644 (file)
@@ -716,9 +716,15 @@ public class PipTouchHandler {
      * Updates the current movement bounds based on whether the menu is currently visible.
      */
     private void updateMovementBounds(int menuState) {
-        mMovementBounds = menuState == MENU_STATE_FULL
+        boolean isMenuExpanded = menuState == MENU_STATE_FULL;
+        mMovementBounds = isMenuExpanded
                 ? mExpandedMovementBounds
                 : mNormalMovementBounds;
+        try {
+            mPinnedStackController.setMinEdgeSize(isMenuExpanded ? mExpandedShortestEdgeSize : 0);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not set minimized state", e);
+        }
     }
 
     /**
index 5414aad..f98310d 100644 (file)
@@ -239,7 +239,11 @@ public class PipManager implements BasePipManager {
             }
         }
 
-        loadConfigurationsAndApply(mContext.getResources().getConfiguration());
+        // Initialize the last orientation and apply the current configuration
+        Configuration initialConfig = mContext.getResources().getConfiguration();
+        mLastOrientation = initialConfig.orientation;
+        loadConfigurationsAndApply(initialConfig);
+
         mMediaSessionManager =
                 (MediaSessionManager) mContext.getSystemService(Context.MEDIA_SESSION_SERVICE);
 
index ec5f9e7..493d244 100644 (file)
@@ -30,13 +30,13 @@ import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Build;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.Looper;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.widget.Toast;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
@@ -166,7 +166,9 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
         }
         if (!mPluginMap.containsKey(listener)) return;
         mPluginMap.remove(listener).destroy();
-        stopListening();
+        if (mPluginMap.size() == 0) {
+            stopListening();
+        }
     }
 
     private void startListening() {
@@ -237,7 +239,9 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
                 mContext.getSystemService(NotificationManager.class).notifyAsUser(pkg,
                         SystemMessage.NOTE_PLUGIN, nb.build(), UserHandle.ALL);
             }
-            clearClassLoader(pkg);
+            if (clearClassLoader(pkg)) {
+                Toast.makeText(mContext, "Reloading " + pkg, Toast.LENGTH_LONG).show();
+            }
             if (!Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) {
                 for (PluginInstanceManager manager : mPluginMap.values()) {
                     manager.onPackageChange(pkg);
@@ -259,8 +263,8 @@ public class PluginManagerImpl extends BroadcastReceiver implements PluginManage
         return classLoader;
     }
 
-    private void clearClassLoader(String pkg) {
-        mClassLoaders.remove(pkg);
+    private boolean clearClassLoader(String pkg) {
+        return mClassLoaders.remove(pkg) != null;
     }
 
     ClassLoader getParentClassLoader() {
index 149b5cc..0d74b7a 100644 (file)
@@ -58,6 +58,16 @@ public class QSContainerImpl extends FrameLayout {
         mBackground = findViewById(R.id.qs_background);
         mGutterHeight = getContext().getResources().getDimensionPixelSize(R.dimen.qs_gutter_height);
         mFullElevation = mQSPanel.getElevation();
+
+        setClickable(true);
+        setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_NO);
+    }
+
+    @Override
+    public boolean performClick() {
+        // Want to receive clicks so missing QQS tiles doesn't cause collapse, but
+        // don't want to do anything with them.
+        return true;
     }
 
     @Override
index 87b042d..488fc03 100644 (file)
@@ -18,12 +18,14 @@ package com.android.systemui.qs;
 
 import static com.android.internal.logging.nano.MetricsProto.MetricsEvent.ACTION_QS_DATE;
 
+import android.app.ActivityManager;
 import android.app.AlarmManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
 import android.content.res.Resources;
+import android.graphics.PorterDuff.Mode;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.RippleDrawable;
 import android.os.UserManager;
@@ -42,6 +44,7 @@ import android.widget.Toast;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.keyguard.KeyguardStatusView;
+import com.android.settingslib.Utils;
 import com.android.systemui.Dependency;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
@@ -101,6 +104,8 @@ public class QSFooter extends FrameLayout implements
     private boolean mShowEditIcon;
     private TouchAnimator mAnimator;
     private View mDateTimeGroup;
+    private boolean mKeyguardShowing;
+    private TouchAnimator mAlarmAnimator;
 
     public QSFooter(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -163,13 +168,14 @@ public class QSFooter extends FrameLayout implements
         int remaining = (width - numTiles * size) / (numTiles - 1);
         int defSpace = mContext.getResources().getDimensionPixelOffset(R.dimen.default_gear_space);
 
-        final Builder builder = new Builder()
+        mAnimator = new Builder()
                 .addFloat(mSettingsContainer, "translationX", -(remaining - defSpace), 0)
                 .addFloat(mSettingsButton, "rotation", -120, 0)
-                .addFloat(mAlarmStatus, "alpha", 0, 1);
+                .build();
         if (mAlarmShowing) {
-            builder.addFloat(mDate, "alpha", 1, 0)
+            mAlarmAnimator = new Builder().addFloat(mDate, "alpha", 1, 0)
                     .addFloat(mDateTimeGroup, "translationX", 0, -mDate.getWidth())
+                    .addFloat(mAlarmStatus, "alpha", 0, 1)
                     .setListener(new ListenerAdapter() {
                         @Override
                         public void onAnimationAtStart() {
@@ -180,13 +186,13 @@ public class QSFooter extends FrameLayout implements
                         public void onAnimationStarted() {
                             mAlarmStatus.setVisibility(View.VISIBLE);
                         }
-                    });
+                    }).build();
         } else {
+            mAlarmAnimator = null;
             mAlarmStatus.setVisibility(View.GONE);
             mDate.setAlpha(1);
             mDateTimeGroup.setTranslationX(0);
         }
-        mAnimator = builder.build();
         setExpansion(mExpansionAmount);
     }
 
@@ -248,6 +254,11 @@ public class QSFooter extends FrameLayout implements
         return animatorBuilder.build();
     }
 
+    public void setKeyguardShowing(boolean keyguardShowing) {
+        mKeyguardShowing = keyguardShowing;
+        setExpansion(mExpansionAmount);
+    }
+
     public void setExpanded(boolean expanded) {
         if (mExpanded == expanded) return;
         mExpanded = expanded;
@@ -275,6 +286,8 @@ public class QSFooter extends FrameLayout implements
     public void setExpansion(float headerExpansionFraction) {
         mExpansionAmount = headerExpansionFraction;
         if (mAnimator != null) mAnimator.setPosition(headerExpansionFraction);
+        if (mAlarmAnimator != null) mAlarmAnimator.setPosition(
+                mKeyguardShowing ? 0 : headerExpansionFraction);
 
         if (mSettingsAlpha != null) {
             mSettingsAlpha.setPosition(headerExpansionFraction);
@@ -413,6 +426,13 @@ public class QSFooter extends FrameLayout implements
 
     @Override
     public void onUserInfoChanged(String name, Drawable picture, String userAccount) {
+        if (picture != null &&
+                UserManager.get(mContext).isGuestUser(ActivityManager.getCurrentUser())) {
+            picture = picture.getConstantState().newDrawable().mutate();
+            picture.setColorFilter(
+                    Utils.getColorAttr(mContext, android.R.attr.colorForeground),
+                    Mode.SRC_IN);
+        }
         mMultiUserAvatar.setImageDrawable(picture);
     }
 }
index 61fd624..c9c3a7f 100644 (file)
@@ -222,6 +222,7 @@ public class QSFragment extends Fragment implements QS {
             mQSAnimator.setOnKeyguard(keyguardShowing);
         }
 
+        mFooter.setKeyguardShowing(keyguardShowing);
         updateQsState();
     }
 
index 8539cb9..00b883a 100644 (file)
@@ -60,6 +60,12 @@ public class QuickQSPanel extends QSPanel {
         mTileLayout = new HeaderTileLayout(context);
         mTileLayout.setListening(mListening);
         addView((View) mTileLayout, 0 /* Between brightness and footer */);
+        super.setPadding(0, 0, 0, 0);
+    }
+
+    @Override
+    public void setPadding(int left, int top, int right, int bottom) {
+        // Always have no padding.
     }
 
     @Override
index e457d72..abafd64 100644 (file)
@@ -23,13 +23,11 @@ import android.support.annotation.VisibleForTesting;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.RelativeLayout;
-import android.widget.TextClock;
 
 import com.android.settingslib.Utils;
 import com.android.systemui.BatteryMeterView;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
-import com.android.systemui.R.id;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.qs.QSDetail.Callback;
 import com.android.systemui.statusbar.SignalClusterView;
@@ -79,7 +77,7 @@ public class QuickStatusBarHeader extends RelativeLayout {
         battery.setForceShowPercent(true);
         // Don't show the Wi-Fi indicator here, because it is shown just below in the tile.
         SignalClusterView signalCluster = findViewById(R.id.signal_cluster);
-        signalCluster.setForceBlockWifi();
+        signalCluster.setQsSignalCluster();
 
         mActivityStarter = Dependency.get(ActivityStarter.class);
     }
index ecbc4f7..9557262 100644 (file)
@@ -140,7 +140,8 @@ public class DndTile extends QSTileImpl<BooleanState> {
         if (mState.value) {
             mController.setZen(ZEN_MODE_OFF, null, TAG);
         } else {
-            mController.setZen(ZEN_MODE_ALARMS, null, TAG);
+            int zen = Prefs.getInt(mContext, Prefs.Key.DND_FAVORITE_ZEN, Global.ZEN_MODE_ALARMS);
+            mController.setZen(zen, null, TAG);
         }
     }
 
index 1afce64..76f6e7d 100644 (file)
@@ -353,13 +353,20 @@ public class WifiTile extends QSTileImpl<SignalState> {
 
         private void updateItems() {
             if (mItems == null) return;
-            if (mSignalCallback.mInfo.enabled) {
-                mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
-                        R.string.quick_settings_wifi_detail_empty_text);
-            } else {
+
+            // Wi-Fi is off
+            if (!mSignalCallback.mInfo.enabled) {
                 mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
                         R.string.wifi_is_off);
+                mItems.setItems(null);
+                return;
             }
+
+            // No available access points
+            mItems.setEmptyState(R.drawable.ic_qs_wifi_detail_empty,
+                    R.string.quick_settings_wifi_detail_empty_text);
+
+            // Build the list
             Item[] items = null;
             if (mAccessPoints != null) {
                 items = new Item[mAccessPoints.length];
index 7697061..ba3bcc7 100644 (file)
@@ -514,6 +514,9 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
             RecentsActivityLaunchState launchState = config.getLaunchState();
             launchState.reset();
         }
+
+        // Force a gc to attempt to clean up bitmap references more quickly (b/38258699)
+        Recents.getSystemServices().gc();
     }
 
     @Override
index e2e9b1b..611169f 100644 (file)
@@ -30,6 +30,7 @@ import android.content.Intent;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
@@ -239,8 +240,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
         }
     });
 
-    protected Bitmap mThumbTransitionBitmapCache;
-
     public RecentsImpl(Context context) {
         mContext = context;
         mHandler = new Handler();
@@ -775,14 +774,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                 }
                 mHeaderBar.layout(0, 0, taskViewWidth, mTaskBarHeight);
             }
-
-            // Update the transition bitmap to match the new header bar height
-            if (mThumbTransitionBitmapCache == null ||
-                    (mThumbTransitionBitmapCache.getWidth() != taskViewWidth) ||
-                    (mThumbTransitionBitmapCache.getHeight() != mTaskBarHeight)) {
-                mThumbTransitionBitmapCache = Bitmap.createBitmap(taskViewWidth,
-                        mTaskBarHeight, Bitmap.Config.ARGB_8888);
-            }
         }
     }
 
@@ -864,8 +855,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                     mTmpTransform = stackLayout.getStackTransformScreenCoordinates(task,
                             stackScroller.getStackScroll(), mTmpTransform, null,
                             windowOverrideRect);
-                    Bitmap thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform,
-                            mThumbTransitionBitmapCache);
+                    GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(task, mTmpTransform);
                     Rect toTaskRect = new Rect();
                     mTmpTransform.rect.round(toTaskRect);
                     specs.add(new AppTransitionAnimationSpec(task.key.id, thumbnail, toTaskRect));
@@ -887,8 +877,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                             () -> {
                         Rect rect = new Rect();
                         toTaskRect.round(rect);
-                        Bitmap thumbnail = drawThumbnailTransitionBitmap(toTask, toTransform,
-                                mThumbTransitionBitmapCache);
+                        GraphicBuffer thumbnail = drawThumbnailTransitionBitmap(toTask,
+                                toTransform);
                         return Lists.newArrayList(new AppTransitionAnimationSpec(
                                 toTask.key.id, thumbnail, rect));
                     });
@@ -924,19 +914,19 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
     /**
      * Draws the header of a task used for the window animation into a bitmap.
      */
-    private Bitmap drawThumbnailTransitionBitmap(Task toTask, TaskViewTransform toTransform,
-            Bitmap thumbnail) {
+    private GraphicBuffer drawThumbnailTransitionBitmap(Task toTask,
+            TaskViewTransform toTransform) {
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (toTransform != null && toTask.key != null) {
             synchronized (mHeaderBarLock) {
                 boolean disabledInSafeMode = !toTask.isSystemApp && ssp.isInSafeMode();
-                mHeaderBar.onTaskViewSizeChanged((int) toTransform.rect.width(),
-                        (int) toTransform.rect.height());
+                int width = (int) toTransform.rect.width();
+                int height = (int) toTransform.rect.height();
+                mHeaderBar.onTaskViewSizeChanged(width, height);
                 if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
-                    thumbnail.eraseColor(0xFFff0000);
+                    return RecentsTransitionHelper.drawViewIntoGraphicBuffer(width, mTaskBarHeight,
+                            null, 1f, 0xFFff0000);
                 } else {
-                    thumbnail.eraseColor(0);
-                    Canvas c = new Canvas(thumbnail);
                     // Workaround for b/27815919, reset the callback so that we do not trigger an
                     // invalidate on the header bar as a result of updating the icon
                     Drawable icon = mHeaderBar.getIconView().getDrawable();
@@ -947,11 +937,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
                             disabledInSafeMode);
                     mHeaderBar.onTaskDataLoaded();
                     mHeaderBar.setDimAlpha(toTransform.dimAlpha);
-                    mHeaderBar.draw(c);
-                    c.setBitmap(null);
+                    return RecentsTransitionHelper.drawViewIntoGraphicBuffer(width, mTaskBarHeight,
+                            mHeaderBar, 1f, 0);
                 }
             }
-            return thumbnail.createAshmemBitmap();
         }
         return null;
     }
index cbfa0e5..1f13830 100644 (file)
@@ -362,6 +362,19 @@ public class SystemServicesProxy {
     }
 
     /**
+     * Requests a gc() from the background thread.
+     */
+    public void gc() {
+        BackgroundThread.getHandler().post(new Runnable() {
+            @Override
+            public void run() {
+                System.gc();
+                System.runFinalization();
+            }
+        });
+    }
+
+    /**
      * @return whether the provided {@param className} is blacklisted
      */
     public boolean isBlackListedActivity(String className) {
index 5e87e2a..716d1bc 100644 (file)
@@ -54,7 +54,6 @@ public class AnimationProps {
     public static final int FOCUS_STATE = 8;
 
     private SparseLongArray mPropStartDelay;
-    private SparseLongArray mPropInitialPlayTime;
     private SparseLongArray mPropDuration;
     private SparseArray<Interpolator> mPropInterpolators;
     private Animator.AnimatorListener mListener;
@@ -122,10 +121,6 @@ public class AnimationProps {
         animator.setStartDelay(getStartDelay(propertyType));
         animator.setDuration(getDuration(propertyType));
         animator.setInterpolator(getInterpolator(propertyType));
-        long initialPlayTime = getInitialPlayTime(propertyType);
-        if (initialPlayTime != 0) {
-            animator.setCurrentPlayTime(initialPlayTime);
-        }
         return animator;
     }
 
@@ -141,17 +136,6 @@ public class AnimationProps {
     }
 
     /**
-     * Sets a initial play time for a specific property.
-     */
-    public AnimationProps setInitialPlayTime(@PropType int propertyType, int initialPlayTime) {
-        if (mPropInitialPlayTime == null) {
-            mPropInitialPlayTime = new SparseLongArray();
-        }
-        mPropInitialPlayTime.append(propertyType, initialPlayTime);
-        return this;
-    }
-
-    /**
      * Returns the start delay for a specific property.
      */
     public long getStartDelay(@PropType int propertyType) {
@@ -217,20 +201,6 @@ public class AnimationProps {
     }
 
     /**
-     * Returns the initial play time for a specific property, falling back to the general initial
-     * play time if there is no specific property interpolator.
-     */
-    public long getInitialPlayTime(@PropType int propertyType) {
-        if (mPropInitialPlayTime != null) {
-            if (mPropInitialPlayTime.indexOfKey(propertyType) != -1) {
-                return mPropInitialPlayTime.get(propertyType);
-            }
-            return mPropInitialPlayTime.get(ALL, 0);
-        }
-        return 0;
-    }
-
-    /**
      * Sets an animator listener for this animation.
      */
     public AnimationProps setListener(Animator.AnimatorListener listener) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsEntrancePathInterpolator.java
new file mode 100644 (file)
index 0000000..e32da2d
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.view.animation.PathInterpolator;
+
+/**
+ * A helper interpolator to stagger the entrance animation in recents by offsetting the start time
+ */
+public class RecentsEntrancePathInterpolator extends PathInterpolator {
+    final float mStartOffsetFraction;
+
+    /**
+     * Create an interpolator for a cubic Bezier curve with an offset play time. The end points
+     * <code>(0, 0)</code> and <code>(1, 1)</code> are assumed.
+     *
+     * @param controlX1 The x coordinate of the first control point of the cubic Bezier.
+     * @param controlY1 The y coordinate of the first control point of the cubic Bezier.
+     * @param controlX2 The x coordinate of the second control point of the cubic Bezier.
+     * @param controlY2 The y coordinate of the second control point of the cubic Bezier.
+     * @param startOffsetFraction The fraction from 0 to 1 to start the animation from
+     */
+    public RecentsEntrancePathInterpolator(float controlX1, float controlY1, float controlX2,
+            float controlY2, float startOffsetFraction) {
+        super(controlX1, controlY1, controlX2, controlY2);
+        mStartOffsetFraction = startOffsetFraction;
+    }
+
+    @Override
+    public float getInterpolation(float t) {
+        return super.getInterpolation(t + mStartOffsetFraction);
+    }
+}
index d7d264e..21dfe8c 100644 (file)
@@ -30,6 +30,7 @@ import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
@@ -37,7 +38,11 @@ import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.util.Log;
 import android.view.AppTransitionAnimationSpec;
+import android.view.DisplayListCanvas;
 import android.view.IAppTransitionAnimationSpecsFuture;
+import android.view.RenderNode;
+import android.view.ThreadedRenderer;
+import android.view.View;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.recents.Recents;
@@ -264,8 +269,8 @@ public class RecentsTransitionHelper {
             Rect bounds) {
         mTmpTransform.fillIn(taskView);
         Task task = taskView.getTask();
-        Bitmap thumbnail = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform);
-        return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, thumbnail,
+        GraphicBuffer buffer = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform);
+        return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, buffer,
                 bounds));
     }
 
@@ -346,7 +351,7 @@ public class RecentsTransitionHelper {
         return new AppTransitionAnimationSpec(task.key.id, null, taskRect);
     }
 
-    public static Bitmap composeTaskBitmap(TaskView taskView, TaskViewTransform transform) {
+    public static GraphicBuffer composeTaskBitmap(TaskView taskView, TaskViewTransform transform) {
         float scale = transform.scale;
         int fromWidth = (int) (transform.rect.width() * scale);
         int fromHeight = (int) (transform.rect.height() * scale);
@@ -354,26 +359,17 @@ public class RecentsTransitionHelper {
             Log.e(TAG, "Could not compose thumbnail for task: " + taskView.getTask() +
                     " at transform: " + transform);
 
-            Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
-            b.eraseColor(Color.TRANSPARENT);
-            return b;
+            return drawViewIntoGraphicBuffer(1, 1, null, 1f, 0x00ffffff);
         } else {
-            Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight,
-                    Bitmap.Config.ARGB_8888);
-
             if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
-                b.eraseColor(0xFFff0000);
+                return drawViewIntoGraphicBuffer(fromWidth, fromHeight, null, 1f, 0xFFff0000);
             } else {
-                Canvas c = new Canvas(b);
-                c.scale(scale, scale);
-                taskView.draw(c);
-                c.setBitmap(null);
+                return drawViewIntoGraphicBuffer(fromWidth, fromHeight, taskView, scale, 0);
             }
-            return b.createAshmemBitmap();
         }
     }
 
-    private static Bitmap composeHeaderBitmap(TaskView taskView,
+    private static GraphicBuffer composeHeaderBitmap(TaskView taskView,
             TaskViewTransform transform) {
         float scale = transform.scale;
         int headerWidth = (int) (transform.rect.width());
@@ -382,16 +378,30 @@ public class RecentsTransitionHelper {
             return null;
         }
 
-        Bitmap b = Bitmap.createBitmap(headerWidth, headerHeight, Bitmap.Config.ARGB_8888);
         if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
-            b.eraseColor(0xFFff0000);
+            return drawViewIntoGraphicBuffer(headerWidth, headerHeight, null, 1f, 0xFFff0000);
         } else {
-            Canvas c = new Canvas(b);
-            c.scale(scale, scale);
-            taskView.mHeaderView.draw(c);
-            c.setBitmap(null);
+            return drawViewIntoGraphicBuffer(headerWidth, headerHeight, taskView.mHeaderView,
+                    scale, 0);
+        }
+    }
+
+    public static GraphicBuffer drawViewIntoGraphicBuffer(int bufferWidth, int bufferHeight,
+            View view, float scale, int eraseColor) {
+        RenderNode node = RenderNode.create("RecentsTransition", null);
+        node.setLeftTopRightBottom(0, 0, bufferWidth, bufferHeight);
+        node.setClipToBounds(false);
+        DisplayListCanvas c = node.start(bufferWidth, bufferHeight);
+        c.scale(scale, scale);
+        if (eraseColor != 0) {
+            c.drawColor(eraseColor);
+        }
+        if (view != null) {
+            view.draw(c);
         }
-        return b.createAshmemBitmap();
+        node.end(c);
+        return ThreadedRenderer.createHardwareBitmap(node, bufferWidth, bufferHeight)
+                .createGraphicBufferHandle();
     }
 
     /**
@@ -399,7 +409,7 @@ public class RecentsTransitionHelper {
      */
     private static AppTransitionAnimationSpec composeAnimationSpec(TaskStackView stackView,
             TaskView taskView, TaskViewTransform transform, boolean addHeaderBitmap) {
-        Bitmap b = null;
+        GraphicBuffer b = null;
         if (addHeaderBitmap) {
             b = composeHeaderBitmap(taskView, transform);
             if (b == null) {
index 2180ec8..46619c2 100644 (file)
@@ -138,7 +138,7 @@ public class RecentsViewTouchHandler {
         }
 
         mVisibleDockStates.clear();
-        if (ActivityManager.supportsMultiWindow() && !ssp.hasDockedTask()
+        if (ActivityManager.supportsMultiWindow(mRv.getContext()) && !ssp.hasDockedTask()
                 && mDividerSnapAlgorithm.isSplitScreenFeasible()) {
             Recents.logDockAttempt(mRv.getContext(), event.task.getTopComponent(),
                     event.task.resizeMode);
index f1314ab..0fc68e6 100644 (file)
@@ -82,8 +82,6 @@ public class TaskStackAnimationHelper {
 
     private static final int ENTER_FROM_HOME_ALPHA_DURATION = 100;
     public static final int ENTER_FROM_HOME_TRANSLATION_DURATION = 300;
-    private static final Interpolator ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR =
-            Interpolators.LINEAR_OUT_SLOW_IN;
     private static final Interpolator ENTER_FROM_HOME_ALPHA_INTERPOLATOR = Interpolators.LINEAR;
 
     public static final int EXIT_TO_HOME_TRANSLATION_DURATION = 200;
@@ -260,17 +258,18 @@ public class TaskStackAnimationHelper {
             } else if (launchState.launchedFromHome) {
                 // Animate the tasks up, but offset the animations to be relative to the front-most
                 // task animation
+                final float startOffsetFraction = (float) (Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS,
+                        taskIndexFromFront) * mEnterAndExitFromHomeTranslationOffset) /
+                        ENTER_FROM_HOME_TRANSLATION_DURATION;
                 AnimationProps taskAnimation = new AnimationProps()
-                        .setInitialPlayTime(AnimationProps.BOUNDS,
-                                Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
-                                        mEnterAndExitFromHomeTranslationOffset)
                         .setStartDelay(AnimationProps.ALPHA,
                                 Math.min(ENTER_EXIT_NUM_ANIMATING_TASKS, taskIndexFromFront) *
                                         FRAME_OFFSET_MS)
                         .setDuration(AnimationProps.BOUNDS, ENTER_FROM_HOME_TRANSLATION_DURATION)
                         .setDuration(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_DURATION)
                         .setInterpolator(AnimationProps.BOUNDS,
-                                ENTER_FROM_HOME_TRANSLATION_INTERPOLATOR)
+                                new RecentsEntrancePathInterpolator(0f, 0f, 0.2f, 1f,
+                                        startOffsetFraction))
                         .setInterpolator(AnimationProps.ALPHA, ENTER_FROM_HOME_ALPHA_INTERPOLATOR)
                         .setListener(postAnimationTrigger.decrementOnAnimationEnd());
                 postAnimationTrigger.increment();
index 2c3e78f..0c6b6b8 100644 (file)
@@ -59,7 +59,7 @@ public class TaskViewAccessibilityDelegate extends View.AccessibilityDelegate {
     @Override
     public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
         super.onInitializeAccessibilityNodeInfo(host, info);
-        if (ActivityManager.supportsSplitScreenMultiWindow()
+        if (ActivityManager.supportsSplitScreenMultiWindow(mTaskView.getContext())
                 && !Recents.getSystemServices().hasDockedTask()) {
             TaskStack.DockState[] dockStates = Recents.getConfiguration()
                     .getDockStatesForCurrentOrientation();
index 0b09acc..3b37437 100644 (file)
@@ -91,6 +91,9 @@ public class Divider extends SystemUI {
     }
 
     private void removeDivider() {
+        if (mView != null) {
+            mView.onDividerRemoved();
+        }
         mWindowManager.remove();
     }
 
index 012accd..6dc7870 100644 (file)
@@ -160,7 +160,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
     private boolean mHomeStackResizable;
     private boolean mAdjustedForIme;
     private DividerState mState;
-    private SurfaceFlingerVsyncChoreographer mSfChoreographer;
+    private final SurfaceFlingerVsyncChoreographer mSfChoreographer;
+
+    // The view is removed or in the process of been removed from the system.
+    private boolean mRemoved;
 
     private final Handler mHandler = new Handler() {
         @Override
@@ -250,20 +253,22 @@ public class DividerView extends FrameLayout implements OnTouchListener,
     };
 
     public DividerView(Context context) {
-        super(context);
+        this(context, null);
     }
 
     public DividerView(Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0);
     }
 
     public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
+        this(context, attrs, defStyleAttr, 0);
     }
 
     public DividerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        mSfChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, context.getDisplay(),
+                Choreographer.getInstance());
     }
 
     @Override
@@ -313,8 +318,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
         EventBus.getDefault().register(this);
-        mSfChoreographer = new SurfaceFlingerVsyncChoreographer(mHandler, getDisplay(),
-                Choreographer.getInstance());
     }
 
     @Override
@@ -323,6 +326,11 @@ public class DividerView extends FrameLayout implements OnTouchListener,
         EventBus.getDefault().unregister(this);
     }
 
+    void onDividerRemoved() {
+        mRemoved = true;
+        mHandler.removeMessages(MSG_RESIZE_STACK);
+    }
+
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
         if (mStableInsets.left != insets.getStableInsetLeft()
@@ -832,7 +840,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
                 .setDuration(animDuration)
                 .start();
         mAdjustedForIme = adjustedForIme;
-        if (mHomeStackResizable && adjustedForIme) {
+
+        // Only get new position if home stack is resizable, ime is open and not minimized
+        // (including the animation)
+        if (mHomeStackResizable && adjustedForIme && !mIsInMinimizeInteraction) {
             mDividerPositionBeforeMinimized = getCurrentPosition();
         }
     }
@@ -914,6 +925,10 @@ public class DividerView extends FrameLayout implements OnTouchListener,
     }
 
     public void resizeStack(int position, int taskPosition, SnapTarget taskSnapTarget) {
+        if (mRemoved) {
+            // This divider view has been removed so shouldn't have any additional influence.
+            return;
+        }
         calculateBoundsForPosition(position, mDockSide, mDockedRect);
 
         if (mDockedRect.equals(mLastResizeRect) && !mEntranceAnimationRunning) {
index a2c782e..578a18a 100644 (file)
@@ -142,7 +142,9 @@ public class ForcedResizableInfoActivityController {
             Intent intent = new Intent(mContext, ForcedResizableInfoActivity.class);
             ActivityOptions options = ActivityOptions.makeBasic();
             options.setLaunchTaskId(pendingRecord.taskId);
-            options.setTaskOverlay(true, false /* canResume */);
+            // Set as task overlay and allow to resume, so that when an app enters split-screen and
+            // becomes paused, the overlay will still be shown.
+            options.setTaskOverlay(true, true /* canResume */);
             intent.putExtra(EXTRA_FORCED_RESIZEABLE_REASON, pendingRecord.reason);
             mContext.startActivityAsUser(intent, options.toBundle(), UserHandle.CURRENT);
         }
index 3542500..1c1be98 100644 (file)
@@ -91,6 +91,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
     }
 
     private LayoutListener mLayoutListener;
+    private boolean mLowPriorityStateUpdated;
     private final NotificationInflater mNotificationInflater;
     private int mIconTransformContentShift;
     private int mIconTransformContentShiftNoIcon;
@@ -356,15 +357,21 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
         updateShelfIconColor();
     }
 
-    private void updateShelfIconColor() {
+    @VisibleForTesting
+    void updateShelfIconColor() {
         StatusBarIconView expandedIcon = mEntry.expandedIcon;
         boolean isPreL = Boolean.TRUE.equals(expandedIcon.getTag(R.id.icon_is_pre_L));
         boolean colorize = !isPreL || NotificationUtils.isGrayscale(expandedIcon,
                 NotificationColorUtil.getInstance(mContext));
         int color = StatusBarIconView.NO_COLOR;
         if (colorize) {
-            color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
-                    getBackgroundColorWithoutTint());
+            NotificationHeaderView header = getVisibleNotificationHeader();
+            if (header != null) {
+                color = header.getOriginalIconColor();
+            } else {
+                color = mEntry.getContrastedColor(mContext, mIsLowPriority && !isExpanded(),
+                        getBackgroundColorWithoutTint());
+            }
         }
         expandedIcon.setStaticDrawableColor(color);
     }
@@ -1121,6 +1128,15 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
         }
     }
 
+
+    public void setLowPriorityStateUpdated(boolean lowPriorityStateUpdated) {
+        mLowPriorityStateUpdated = lowPriorityStateUpdated;
+    }
+
+    public boolean hasLowPriorityStateUpdated() {
+        return mLowPriorityStateUpdated;
+    }
+
     public boolean isLowPriority() {
         return mIsLowPriority;
     }
@@ -1379,6 +1395,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
         if (mIsSummaryWithChildren) {
             mChildrenContainer.setDark(dark, fade, delay);
         }
+        updateShelfIconColor();
     }
 
     public boolean isExpandable() {
@@ -1718,6 +1735,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView
         NotificationContentView showingLayout = getShowingLayout();
         showingLayout.updateBackgroundColor(animated);
         mPrivateLayout.updateExpandButtons(isExpandable());
+        updateShelfIconColor();
         showingLayout.setDark(isDark(), false /* animate */, 0 /* delay */);
         mShowingPublicInitialized = true;
     }
index baf0c2c..c432ea8 100644 (file)
@@ -49,11 +49,11 @@ import com.android.systemui.statusbar.policy.RemoteInputView;
  */
 public class NotificationContentView extends FrameLayout {
 
-    private static final int VISIBLE_TYPE_CONTRACTED = 0;
-    private static final int VISIBLE_TYPE_EXPANDED = 1;
-    private static final int VISIBLE_TYPE_HEADSUP = 2;
+    public static final int VISIBLE_TYPE_CONTRACTED = 0;
+    public static final int VISIBLE_TYPE_EXPANDED = 1;
+    public static final int VISIBLE_TYPE_HEADSUP = 2;
     private static final int VISIBLE_TYPE_SINGLELINE = 3;
-    private static final int VISIBLE_TYPE_AMBIENT = 4;
+    public static final int VISIBLE_TYPE_AMBIENT = 4;
     private static final int VISIBLE_TYPE_AMBIENT_SINGLELINE = 5;
     public static final int UNDEFINED = -1;
 
@@ -928,7 +928,7 @@ public class NotificationContentView extends FrameLayout {
         }
     }
 
-    private NotificationViewWrapper getVisibleWrapper(int visibleType) {
+    public NotificationViewWrapper getVisibleWrapper(int visibleType) {
         switch (visibleType) {
             case VISIBLE_TYPE_EXPANDED:
                 return mExpandedWrapper;
@@ -1085,16 +1085,16 @@ public class NotificationContentView extends FrameLayout {
         mBeforeN = entry.targetSdk < Build.VERSION_CODES.N;
         updateAllSingleLineViews();
         if (mContractedChild != null) {
-            mContractedWrapper.notifyContentUpdated(entry.row);
+            mContractedWrapper.onContentUpdated(entry.row);
         }
         if (mExpandedChild != null) {
-            mExpandedWrapper.notifyContentUpdated(entry.row);
+            mExpandedWrapper.onContentUpdated(entry.row);
         }
         if (mHeadsUpChild != null) {
-            mHeadsUpWrapper.notifyContentUpdated(entry.row);
+            mHeadsUpWrapper.onContentUpdated(entry.row);
         }
         if (mAmbientChild != null) {
-            mAmbientWrapper.notifyContentUpdated(entry.row);
+            mAmbientWrapper.onContentUpdated(entry.row);
         }
         applyRemoteInput(entry);
         updateLegacy();
index 1844946..58844ad 100644 (file)
@@ -24,6 +24,8 @@ import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.Context;
 import android.graphics.drawable.Icon;
+import android.os.AsyncTask;
+import android.os.Bundle;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.service.notification.NotificationListenerService;
@@ -38,8 +40,11 @@ import android.widget.RemoteViews;
 import android.Manifest;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationColorUtil;
+import com.android.systemui.Dependency;
+import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.statusbar.notification.InflationException;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -141,12 +146,12 @@ public class NotificationData {
 
             // Construct the icon.
             icon = new StatusBarIconView(context,
-                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
             icon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
 
             // Construct the expanded icon.
             expandedIcon = new StatusBarIconView(context,
-                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), n);
+                    sbn.getPackageName() + "/0x" + Integer.toHexString(sbn.getId()), sbn);
             expandedIcon.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
             final StatusBarIcon ic = new StatusBarIcon(
                     sbn.getUser(),
@@ -182,9 +187,11 @@ public class NotificationData {
          * @param n the notification to read the icon from.
          * @throws InflationException
          */
-        public void updateIcons(Context context, Notification n) throws InflationException {
+        public void updateIcons(Context context, StatusBarNotification sbn)
+                throws InflationException {
             if (icon != null) {
                 // Update the icon
+                Notification n = sbn.getNotification();
                 final StatusBarIcon ic = new StatusBarIcon(
                         notification.getUser(),
                         notification.getPackageName(),
@@ -192,8 +199,8 @@ public class NotificationData {
                         n.iconLevel,
                         n.number,
                         StatusBarIconView.contentDescForNotification(context, n));
-                icon.setNotification(n);
-                expandedIcon.setNotification(n);
+                icon.setNotification(sbn);
+                expandedIcon.setNotification(sbn);
                 if (!icon.set(ic) || !expandedIcon.set(ic)) {
                     throw new InflationException("Couldn't update icon: " + ic);
                 }
@@ -339,6 +346,7 @@ public class NotificationData {
             mEntries.put(entry.notification.getKey(), entry);
         }
         mGroupManager.onEntryAdded(entry);
+
         updateRankingAndSort(mRankingMap);
     }
 
@@ -466,6 +474,10 @@ public class NotificationData {
         Collections.sort(mSortedAndFiltered, mRankingComparator);
     }
 
+    /**
+     * @param sbn
+     * @return true if this notification should NOT be shown right now
+     */
     public boolean shouldFilterOut(StatusBarNotification sbn) {
         if (!(mEnvironment.isDeviceProvisioned() ||
                 showNotificationEvenIfUnprovisioned(sbn))) {
@@ -487,6 +499,13 @@ public class NotificationData {
                 && mGroupManager.isChildInGroupWithSummary(sbn)) {
             return true;
         }
+
+        final ForegroundServiceController fsc = Dependency.get(ForegroundServiceController.class);
+        if (fsc.isDungeonNotification(sbn) && !fsc.isDungeonNeededForUser(sbn.getUserId())) {
+            // this is a foreground-service disclosure for a user that does not need to show one
+            return true;
+        }
+
         return false;
     }
 
index 5cb3c1f..bbcbfd6 100644 (file)
@@ -165,7 +165,7 @@ public class NotificationShelf extends ActivatableNotificationView implements
             openedAmount = Math.min(1.0f, openedAmount);
             mShelfState.openedAmount = openedAmount;
             mShelfState.clipTopAmount = 0;
-            mShelfState.alpha = mAmbientState.isPulsing() ? 0 : 1;
+            mShelfState.alpha = mAmbientState.hasPulsingNotifications() ? 0 : 1;
             mShelfState.belowSpeedBump = mAmbientState.getSpeedBumpIndex() == 0;
             mShelfState.shadowAlpha = 1.0f;
             mShelfState.hideSensitive = false;
@@ -456,9 +456,8 @@ public class NotificationShelf extends ActivatableNotificationView implements
             }
             int shelfColor = icon.getStaticDrawableColor();
             if (!noIcon && shelfColor != StatusBarIconView.NO_COLOR) {
-                int notificationColor
-                        = row.getVisibleNotificationHeader().getOriginalNotificationColor();
-                shelfColor = NotificationUtils.interpolateColors(notificationColor, shelfColor,
+                int iconColor = row.getVisibleNotificationHeader().getOriginalIconColor();
+                shelfColor = NotificationUtils.interpolateColors(iconColor, shelfColor,
                         iconState.iconAppearAmount);
             }
             iconState.iconColor = shelfColor;
index 28a858c..18cc872 100644 (file)
@@ -121,6 +121,7 @@ public class SignalClusterView extends LinearLayout implements NetworkController
     private boolean mBlockEthernet;
     private boolean mActivityEnabled;
     private boolean mForceBlockWifi;
+    private boolean mQsSignal;
 
     public SignalClusterView(Context context) {
         this(context, null);
@@ -152,9 +153,10 @@ public class SignalClusterView extends LinearLayout implements NetworkController
         updateActivityEnabled();
     }
 
-    public void setForceBlockWifi() {
+    public void setQsSignalCluster() {
         mForceBlockWifi = true;
         mBlockWifi = true;
+        mQsSignal = true;
         if (isAttachedToWindow()) {
             // Re-register to get new callbacks.
             mNetworkController.removeCallback(this);
@@ -292,26 +294,30 @@ public class SignalClusterView extends LinearLayout implements NetworkController
         mWifiStrengthId = statusIcon.icon;
         mWifiBadgeId = statusIcon.iconOverlay;
         mWifiDescription = statusIcon.contentDescription;
-        mWifiIn = activityIn && mActivityEnabled;
-        mWifiOut = activityOut && mActivityEnabled;
+        mWifiIn = activityIn && mActivityEnabled && mWifiVisible;
+        mWifiOut = activityOut && mActivityEnabled && mWifiVisible;
 
         apply();
     }
 
     @Override
-    public void setMobileDataIndicators(IconState statusIcon, IconState qsIcon, int statusType,
+    public void setMobileDataIndicators(IconState icon, IconState qsIcon, int type,
             int qsType, boolean activityIn, boolean activityOut, String typeContentDescription,
             String description, boolean isWide, int subId, boolean roaming) {
         PhoneState state = getState(subId);
         if (state == null) {
             return;
         }
-        state.mMobileVisible = statusIcon.visible && !mBlockMobile;
-        state.mMobileStrengthId = statusIcon.icon;
-        state.mMobileTypeId = statusType;
-        state.mMobileDescription = statusIcon.contentDescription;
+        if (mQsSignal && qsIcon != null) {
+            icon = qsIcon;
+            type = qsType;
+        }
+        state.mMobileVisible = icon.visible && !mBlockMobile;
+        state.mMobileStrengthId = icon.icon;
+        state.mMobileTypeId = type;
+        state.mMobileDescription = icon.contentDescription;
         state.mMobileTypeDescription = typeContentDescription;
-        state.mIsMobileTypeIconWide = statusType != 0 && isWide;
+        state.mIsMobileTypeIconWide = type != 0 && isWide;
         state.mRoaming = roaming;
         state.mActivityIn = activityIn && mActivityEnabled;
         state.mActivityOut = activityOut && mActivityEnabled;
index c7fbbf9..3c7ddb5 100644 (file)
@@ -34,6 +34,7 @@ import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
@@ -99,7 +100,7 @@ public class StatusBarIconView extends AnimatedImageView {
     private int mNumberX;
     private int mNumberY;
     private String mNumberText;
-    private Notification mNotification;
+    private StatusBarNotification mNotification;
     private final boolean mBlocked;
     private int mDensity;
     private float mIconScale = 1.0f;
@@ -127,11 +128,11 @@ public class StatusBarIconView extends AnimatedImageView {
     };
     private final NotificationIconDozeHelper mDozer;
 
-    public StatusBarIconView(Context context, String slot, Notification notification) {
-        this(context, slot, notification, false);
+    public StatusBarIconView(Context context, String slot, StatusBarNotification sbn) {
+        this(context, slot, sbn, false);
     }
 
-    public StatusBarIconView(Context context, String slot, Notification notification,
+    public StatusBarIconView(Context context, String slot, StatusBarNotification sbn,
             boolean blocked) {
         super(context);
         mDozer = new NotificationIconDozeHelper(context);
@@ -141,7 +142,7 @@ public class StatusBarIconView extends AnimatedImageView {
         mNumberPain.setTextAlign(Paint.Align.CENTER);
         mNumberPain.setColor(context.getColor(R.drawable.notification_number_text_color));
         mNumberPain.setAntiAlias(true);
-        setNotification(notification);
+        setNotification(sbn);
         maybeUpdateIconScaleDimens();
         setScaleType(ScaleType.CENTER);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
@@ -179,6 +180,10 @@ public class StatusBarIconView extends AnimatedImageView {
         mIconScale = (float)imageBounds / (float)outerBounds;
     }
 
+    public float getIconScaleFullyDark() {
+        return (float) mStatusBarIconDrawingSizeDark / mStatusBarIconDrawingSize;
+    }
+
     public float getIconScale() {
         return mIconScale;
     }
@@ -203,9 +208,11 @@ public class StatusBarIconView extends AnimatedImageView {
         }
     }
 
-    public void setNotification(Notification notification) {
+    public void setNotification(StatusBarNotification notification) {
         mNotification = notification;
-        setContentDescription(notification);
+        if (notification != null) {
+            setContentDescription(notification.getNotification());
+        }
     }
 
     public StatusBarIconView(Context context, AttributeSet attrs) {
@@ -311,6 +318,10 @@ public class StatusBarIconView extends AnimatedImageView {
         return true;
     }
 
+    public Icon getSourceIcon() {
+        return mIcon.icon;
+    }
+
     private Drawable getIcon(StatusBarIcon icon) {
         return getIcon(getContext(), icon);
     }
@@ -350,7 +361,7 @@ public class StatusBarIconView extends AnimatedImageView {
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
         if (mNotification != null) {
-            event.setParcelableData(mNotification);
+            event.setParcelableData(mNotification.getNotification());
         }
     }
 
@@ -452,6 +463,10 @@ public class StatusBarIconView extends AnimatedImageView {
             + " notification=" + mNotification + ")";
     }
 
+    public StatusBarNotification getNotification() {
+        return mNotification;
+    }
+
     public String getSlot() {
         return mSlot;
     }
index 7a34b6e..cf12e94 100644 (file)
@@ -36,8 +36,8 @@ public class NotificationBigPictureTemplateViewWrapper extends NotificationTempl
     }
 
     @Override
-    public void notifyContentUpdated(ExpandableNotificationRow row) {
-        super.notifyContentUpdated(row);
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        super.onContentUpdated(row);
         updateImageTag(row.getStatusBarNotification());
     }
 
index 9476eed..20a3d8f 100644 (file)
@@ -41,11 +41,11 @@ public class NotificationBigTextTemplateViewWrapper extends NotificationTemplate
     }
 
     @Override
-    public void notifyContentUpdated(ExpandableNotificationRow row) {
+    public void onContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
         resolveViews(row.getStatusBarNotification());
-        super.notifyContentUpdated(row);
+        super.onContentUpdated(row);
     }
 
     @Override
index 0b9244a..15cca5f 100644 (file)
@@ -128,8 +128,8 @@ public class NotificationHeaderViewWrapper extends NotificationViewWrapper {
     }
 
     @Override
-    public void notifyContentUpdated(ExpandableNotificationRow row) {
-        super.notifyContentUpdated(row);
+    public void onContentUpdated(ExpandableNotificationRow row) {
+        super.onContentUpdated(row);
         mIsLowPriority = row.isLowPriority();
         mTransformLowPriorityTitle = !row.isChildInGroup() && !row.isSummaryWithChildren();
         ArraySet<View> previousViews = mTransformationHelper.getAllTransformingViews();
index 4b08f2b..7eaa290 100644 (file)
@@ -36,7 +36,6 @@ import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.util.Assert;
 
 import java.util.HashMap;
-import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Executor;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.ThreadFactory;
@@ -207,7 +206,8 @@ public class NotificationInflater {
             };
             applyRemoteView(result, reInflateFlags, flag, row, redactAmbient,
                     isNewView, remoteViewClickHandler, callback, entry, privateLayout,
-                    privateLayout.getContractedChild(),
+                    privateLayout.getContractedChild(), privateLayout.getVisibleWrapper(
+                            NotificationContentView.VISIBLE_TYPE_CONTRACTED),
                     runningInflations, applyCallback);
         }
 
@@ -229,7 +229,9 @@ public class NotificationInflater {
                 };
                 applyRemoteView(result, reInflateFlags, flag, row,
                         redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                        privateLayout, privateLayout.getExpandedChild(), runningInflations,
+                        privateLayout, privateLayout.getExpandedChild(),
+                        privateLayout.getVisibleWrapper(
+                                NotificationContentView.VISIBLE_TYPE_EXPANDED), runningInflations,
                         applyCallback);
             }
         }
@@ -252,7 +254,9 @@ public class NotificationInflater {
                 };
                 applyRemoteView(result, reInflateFlags, flag, row,
                         redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                        privateLayout, privateLayout.getHeadsUpChild(), runningInflations,
+                        privateLayout, privateLayout.getHeadsUpChild(),
+                        privateLayout.getVisibleWrapper(
+                                NotificationContentView.VISIBLE_TYPE_HEADSUP), runningInflations,
                         applyCallback);
             }
         }
@@ -274,8 +278,9 @@ public class NotificationInflater {
             };
             applyRemoteView(result, reInflateFlags, flag, row,
                     redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                    publicLayout, publicLayout.getContractedChild(), runningInflations,
-                    applyCallback);
+                    publicLayout, publicLayout.getContractedChild(),
+                    publicLayout.getVisibleWrapper(NotificationContentView.VISIBLE_TYPE_CONTRACTED),
+                    runningInflations, applyCallback);
         }
 
         flag = FLAG_REINFLATE_AMBIENT_VIEW;
@@ -296,7 +301,8 @@ public class NotificationInflater {
             };
             applyRemoteView(result, reInflateFlags, flag, row,
                     redactAmbient, isNewView, remoteViewClickHandler, callback, entry,
-                    newParent, newParent.getAmbientChild(), runningInflations,
+                    newParent, newParent.getAmbientChild(), newParent.getVisibleWrapper(
+                            NotificationContentView.VISIBLE_TYPE_AMBIENT), runningInflations,
                     applyCallback);
         }
 
@@ -316,6 +322,7 @@ public class NotificationInflater {
             RemoteViews.OnClickHandler remoteViewClickHandler,
             @Nullable final InflationCallback callback, NotificationData.Entry entry,
             NotificationContentView parentLayout, View existingView,
+            NotificationViewWrapper existingWrapper,
             final HashMap<Integer, CancellationSignal> runningInflations,
             ApplyCallback applyCallback) {
         RemoteViews.OnViewAppliedListener listener
@@ -326,6 +333,8 @@ public class NotificationInflater {
                 if (isNewView) {
                     v.setIsRootNamespace(true);
                     applyCallback.setResultView(v);
+                } else if (existingWrapper != null) {
+                    existingWrapper.onReinflated();
                 }
                 runningInflations.remove(inflationId);
                 finishIfDone(result, reInflateFlags, runningInflations, callback, row,
index 8596cb3..eb211a1 100644 (file)
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.notification;
 
 import android.content.Context;
-import android.service.notification.StatusBarNotification;
 import android.view.View;
 
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -40,11 +39,11 @@ public class NotificationMediaTemplateViewWrapper extends NotificationTemplateVi
     }
 
     @Override
-    public void notifyContentUpdated(ExpandableNotificationRow row) {
+    public void onContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
         resolveViews();
-        super.notifyContentUpdated(row);
+        super.onContentUpdated(row);
     }
 
     @Override
index 9631556..f6ee1ca 100644 (file)
@@ -70,11 +70,11 @@ public class NotificationMessagingTemplateViewWrapper extends NotificationTempla
     }
 
     @Override
-    public void notifyContentUpdated(ExpandableNotificationRow row) {
+    public void onContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
         resolveViews();
-        super.notifyContentUpdated(row);
+        super.onContentUpdated(row);
     }
 
     @Override
index f0b6b2e..abb4cf6 100644 (file)
@@ -133,11 +133,11 @@ public class NotificationTemplateViewWrapper extends NotificationHeaderViewWrapp
     }
 
     @Override
-    public void notifyContentUpdated(ExpandableNotificationRow row) {
+    public void onContentUpdated(ExpandableNotificationRow row) {
         // Reinspect the notification. Before the super call, because the super call also updates
         // the transformation types and we need to have our values set by then.
         resolveTemplateViews(row.getStatusBarNotification());
-        super.notifyContentUpdated(row);
+        super.onContentUpdated(row);
     }
 
     @Override
index 5cc39cc..4b73613 100644 (file)
@@ -66,6 +66,7 @@ public abstract class NotificationViewWrapper implements TransformableView {
         mView = view;
         mRow = row;
         mDozer = createDozer(ctx);
+        onReinflated();
     }
 
     protected NotificationDozeHelper createDozer(Context ctx) {
@@ -92,12 +93,15 @@ public abstract class NotificationViewWrapper implements TransformableView {
      * Notifies this wrapper that the content of the view might have changed.
      * @param row the row this wrapper is attached to
      */
-    public void notifyContentUpdated(ExpandableNotificationRow row) {
+    public void onContentUpdated(ExpandableNotificationRow row) {
         mDarkInitialized = false;
-        Drawable background = mView.getBackground();
+    }
+
+    public void onReinflated() {
         if (shouldClearBackgroundOnReapply()) {
             mBackgroundColor = 0;
         }
+        Drawable background = mView.getBackground();
         if (background instanceof ColorDrawable) {
             mBackgroundColor = ((ColorDrawable) background).getColor();
             mView.setBackground(null);
index 8dab069..09aff1b 100644 (file)
@@ -38,6 +38,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener {
     private boolean mReorderingAllowed;
     private VisibilityLocationProvider mVisibilityLocationProvider;
     private ArraySet<View> mAllowedReorderViews = new ArraySet<>();
+    private ArraySet<View> mLowPriorityReorderingViews = new ArraySet<>();
     private ArraySet<View> mAddedChildren = new ArraySet<>();
     private boolean mPulsing;
 
@@ -115,6 +116,9 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener {
         if (mAddedChildren.contains(row)) {
             return true;
         }
+        if (mLowPriorityReorderingViews.contains(row)) {
+            return true;
+        }
         if (mAllowedReorderViews.contains(row)
                 && !mVisibilityLocationProvider.isInVisibleLocation(row)) {
             return true;
@@ -130,6 +134,7 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener {
     public void onReorderingFinished() {
         mAllowedReorderViews.clear();
         mAddedChildren.clear();
+        mLowPriorityReorderingViews.clear();
     }
 
     @Override
@@ -141,6 +146,10 @@ public class VisualStabilityManager implements OnHeadsUpChangedListener {
         }
     }
 
+    public void onLowPriorityUpdated(NotificationData.Entry entry) {
+        mLowPriorityReorderingViews.add(entry.row);
+    }
+
     /**
      * Notify the visual stability manager that a new view was added and should be allowed to
      * reorder next time.
index 4bfc16b..d047fa9 100644 (file)
@@ -545,7 +545,7 @@ public class NavigationBarFragment extends Fragment implements Callbacks {
     }
 
     private boolean onLongPressRecents() {
-        if (mRecents == null || !ActivityManager.supportsMultiWindow()
+        if (mRecents == null || !ActivityManager.supportsMultiWindow(getContext())
                 || !mDivider.getView().getSnapAlgorithm().isSplitScreenFeasible()) {
             return false;
         }
index 52838b0..5bfdd1f 100644 (file)
@@ -4,11 +4,15 @@ import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.Icon;
 import android.support.annotation.NonNull;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
 
+import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationColorUtil;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -180,14 +184,54 @@ public class NotificationIconAreaController implements DarkReceiver {
             }
         }
 
+        // In case we are changing the suppression of a group, the replacement shouldn't flicker
+        // and it should just be replaced instead. We therefore look for notifications that were
+        // just replaced by the child or vice-versa to suppress this.
 
+        ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons = new ArrayMap<>();
         ArrayList<View> toRemove = new ArrayList<>();
         for (int i = 0; i < hostLayout.getChildCount(); i++) {
             View child = hostLayout.getChildAt(i);
+            if (!(child instanceof StatusBarIconView)) {
+                continue;
+            }
             if (!toShow.contains(child)) {
-                toRemove.add(child);
+                boolean iconWasReplaced = false;
+                StatusBarIconView removedIcon = (StatusBarIconView) child;
+                String removedGroupKey = removedIcon.getNotification().getGroupKey();
+                for (int j = 0; j < toShow.size(); j++) {
+                    StatusBarIconView candidate = toShow.get(j);
+                    if (candidate.getSourceIcon().sameAs((removedIcon.getSourceIcon()))
+                            && candidate.getNotification().getGroupKey().equals(removedGroupKey)) {
+                        if (!iconWasReplaced) {
+                            iconWasReplaced = true;
+                        } else {
+                            iconWasReplaced = false;
+                            break;
+                        }
+                    }
+                }
+                if (iconWasReplaced) {
+                    ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(removedGroupKey);
+                    if (statusBarIcons == null) {
+                        statusBarIcons = new ArrayList<>();
+                        replacingIcons.put(removedGroupKey, statusBarIcons);
+                    }
+                    statusBarIcons.add(removedIcon.getStatusBarIcon());
+                }
+                toRemove.add(removedIcon);
+            }
+        }
+        // removing all duplicates
+        ArrayList<String> duplicates = new ArrayList<>();
+        for (String key : replacingIcons.keySet()) {
+            ArrayList<StatusBarIcon> statusBarIcons = replacingIcons.get(key);
+            if (statusBarIcons.size() != 1) {
+                duplicates.add(key);
             }
         }
+        replacingIcons.removeAll(duplicates);
+        hostLayout.setReplacingIcons(replacingIcons);
 
         final int toRemoveCount = toRemove.size();
         for (int i = 0; i < toRemoveCount; i++) {
@@ -217,6 +261,7 @@ public class NotificationIconAreaController implements DarkReceiver {
             hostLayout.addView(expected, i);
         }
         hostLayout.setChangingViewPositions(false);
+        hostLayout.setReplacingIcons(null);
     }
 
     /**
index 9000eb4..a4fadc4 100644 (file)
@@ -21,9 +21,13 @@ import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.drawable.Icon;
+import android.support.v4.util.ArrayMap;
+import android.support.v4.util.ArraySet;
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.statusbar.AlphaOptimizedFrameLayout;
@@ -33,6 +37,7 @@ import com.android.systemui.statusbar.stack.AnimationProperties;
 import com.android.systemui.statusbar.stack.StackStateAnimator;
 import com.android.systemui.statusbar.stack.ViewState;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 
 /**
@@ -117,6 +122,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
     private float mVisualOverflowAdaption;
     private boolean mDisallowNextAnimation;
     private boolean mAnimationsEnabled = true;
+    private ArrayMap<String, ArrayList<StatusBarIcon>> mReplacingIcons;
 
     public NotificationIconContainer(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -183,11 +189,17 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
     @Override
     public void onViewAdded(View child) {
         super.onViewAdded(child);
+        boolean isReplacingIcon = isReplacingIcon(child);
         if (!mChangingViewPositions) {
-            mIconStates.put(child, new IconState());
+            IconState v = new IconState();
+            if (isReplacingIcon) {
+                v.justAdded = false;
+                v.justReplaced = true;
+            }
+            mIconStates.put(child, v);
         }
         int childIndex = indexOfChild(child);
-        if (childIndex < getChildCount() - 1
+        if (childIndex < getChildCount() - 1 && !isReplacingIcon
             && mIconStates.get(getChildAt(childIndex + 1)).iconAppearAmount > 0.0f) {
             if (mAddAnimationStartIndex < 0) {
                 mAddAnimationStartIndex = childIndex;
@@ -200,13 +212,34 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
         }
     }
 
+    private boolean isReplacingIcon(View child) {
+        if (mReplacingIcons == null) {
+            return false;
+        }
+        if (!(child instanceof StatusBarIconView)) {
+            return false;
+        }
+        StatusBarIconView iconView = (StatusBarIconView) child;
+        Icon sourceIcon = iconView.getSourceIcon();
+        String groupKey = iconView.getNotification().getGroupKey();
+        ArrayList<StatusBarIcon> statusBarIcons = mReplacingIcons.get(groupKey);
+        if (statusBarIcons != null) {
+            StatusBarIcon replacedIcon = statusBarIcons.get(0);
+            if (sourceIcon.sameAs(replacedIcon.icon)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
     @Override
     public void onViewRemoved(View child) {
         super.onViewRemoved(child);
         if (child instanceof StatusBarIconView) {
+            boolean isReplacingIcon = isReplacingIcon(child);
             final StatusBarIconView icon = (StatusBarIconView) child;
             if (icon.getVisibleState() != StatusBarIconView.STATE_HIDDEN
-                    && child.getVisibility() == VISIBLE) {
+                    && child.getVisibility() == VISIBLE && isReplacingIcon) {
                 int animationStartIndex = findFirstViewIndexAfter(icon.getTranslationX());
                 if (mAddAnimationStartIndex < 0) {
                     mAddAnimationStartIndex = animationStartIndex;
@@ -216,9 +249,11 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
             }
             if (!mChangingViewPositions) {
                 mIconStates.remove(child);
-                addTransientView(icon, 0);
-                icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
-                        () -> removeTransientView(icon));
+                if (!isReplacingIcon) {
+                    addTransientView(icon, 0);
+                    icon.setVisibleState(StatusBarIconView.STATE_HIDDEN, true /* animate */,
+                            () -> removeTransientView(icon));
+                }
             }
         }
     }
@@ -267,6 +302,9 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
             boolean forceOverflow = mSpeedBumpIndex != -1 && i >= mSpeedBumpIndex
                     && iconState.iconAppearAmount > 0.0f || i >= maxVisibleIcons;
             boolean noOverflowAfter = i == childCount - 1;
+            float drawingScale = mDark && view instanceof StatusBarIconView
+                    ? ((StatusBarIconView) view).getIconScaleFullyDark()
+                    : 1f;
             if (mOpenedAmount != 0.0f) {
                 noOverflowAfter = noOverflowAfter && !hasAmbient && !forceOverflow;
             }
@@ -303,7 +341,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
                     visualOverflowStart += mVisualOverflowAdaption * (1f - mOpenedAmount);
                 }
             }
-            translationX += iconState.iconAppearAmount * view.getWidth();
+            translationX += iconState.iconAppearAmount * view.getWidth() * drawingScale;
         }
         if (firstOverflowIndex != -1) {
             int numDots = 1;
@@ -470,11 +508,16 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
         mAnimationsEnabled = enabled;
     }
 
+    public void setReplacingIcons(ArrayMap<String, ArrayList<StatusBarIcon>> replacingIcons) {
+        mReplacingIcons = replacingIcons;
+    }
+
     public class IconState extends ViewState {
         public float iconAppearAmount = 1.0f;
         public float clampedAppearAmount = 1.0f;
         public int visibleState;
         public boolean justAdded = true;
+        private boolean justReplaced;
         public boolean needsCannedAnimation;
         public boolean useFullTransitionAmount;
         public boolean useLinearTransitionAmount;
@@ -493,9 +536,9 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
                         && !mDisallowNextAnimation
                         && !noAnimations;
                 if (animationsAllowed) {
-                    if (justAdded) {
+                    if (justAdded || justReplaced) {
                         super.applyToView(icon);
-                        if (iconAppearAmount != 0.0f) {
+                        if (justAdded && iconAppearAmount != 0.0f) {
                             icon.setAlpha(0.0f);
                             icon.setVisibleState(StatusBarIconView.STATE_HIDDEN,
                                     false /* animate */);
@@ -554,6 +597,7 @@ public class NotificationIconContainer extends AlphaOptimizedFrameLayout {
                 }
             }
             justAdded = false;
+            justReplaced = false;
             needsCannedAnimation = false;
             justUndarkened = false;
         }
index 4b1d7d7..b1d82b1 100644 (file)
@@ -55,6 +55,7 @@ public abstract class PanelView extends FrameLayout {
     private long mDownTime;
     private float mMinExpandHeight;
     private LockscreenGestureLogger mLockscreenGestureLogger = new LockscreenGestureLogger();
+    private boolean mPanelUpdateWhenAnimatorEnds;
 
     private final void logf(String fmt, Object... args) {
         Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
@@ -507,7 +508,7 @@ public abstract class PanelView extends FrameLayout {
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
-        if (mInstantExpanding || !mNotificationsDragEnabled
+        if (mInstantExpanding || !mNotificationsDragEnabled || mTouchDisabled
                 || (mMotionAborted && event.getActionMasked() != MotionEvent.ACTION_DOWN)) {
             return false;
         }
@@ -758,14 +759,14 @@ public abstract class PanelView extends FrameLayout {
                 if (clearAllExpandHack && !mCancelled) {
                     setExpandedHeightInternal(getMaxPanelHeight());
                 }
-                mHeightAnimator = null;
+                setAnimator(null);
                 if (!mCancelled) {
                     notifyExpandingFinished();
                 }
                 notifyBarPanelExpansionChanged();
             }
         });
-        mHeightAnimator = animator;
+        setAnimator(animator);
         animator.start();
     }
 
@@ -802,15 +803,28 @@ public abstract class PanelView extends FrameLayout {
     protected void requestPanelHeightUpdate() {
         float currentMaxPanelHeight = getMaxPanelHeight();
 
-        // If the user isn't actively poking us, let's update the height
-        if ((!mTracking || isTrackingBlocked())
-                && mHeightAnimator == null
-                && !isFullyCollapsed()
-                && currentMaxPanelHeight != mExpandedHeight
-                && mPeekAnimator == null
-                && !mPeekTouching) {
-            setExpandedHeight(currentMaxPanelHeight);
+        if (isFullyCollapsed()) {
+            return;
+        }
+
+        if (currentMaxPanelHeight == mExpandedHeight) {
+            return;
+        }
+
+        if (mPeekAnimator != null || mPeekTouching) {
+            return;
+        }
+
+        if (mTracking && !isTrackingBlocked()) {
+            return;
+        }
+
+        if (mHeightAnimator != null) {
+            mPanelUpdateWhenAnimatorEnds = true;
+            return;
         }
+
+        setExpandedHeight(currentMaxPanelHeight);
     }
 
     public void setExpandedHeightInternal(float h) {
@@ -1062,7 +1076,7 @@ public abstract class PanelView extends FrameLayout {
             @Override
             public void onAnimationEnd(Animator animation) {
                 if (mCancelled) {
-                    mHeightAnimator = null;
+                    setAnimator(null);
                     onAnimationFinished.run();
                 } else {
                     startUnlockHintAnimationPhase2(onAnimationFinished);
@@ -1070,7 +1084,7 @@ public abstract class PanelView extends FrameLayout {
             }
         });
         animator.start();
-        mHeightAnimator = animator;
+        setAnimator(animator);
         mKeyguardBottomArea.getIndicationArea().animate()
                 .translationY(-mHintDistance)
                 .setDuration(250)
@@ -1088,6 +1102,14 @@ public abstract class PanelView extends FrameLayout {
                 .start();
     }
 
+    private void setAnimator(ValueAnimator animator) {
+        mHeightAnimator = animator;
+        if (animator == null && mPanelUpdateWhenAnimatorEnds) {
+            mPanelUpdateWhenAnimatorEnds = false;
+            requestPanelHeightUpdate();
+        }
+    }
+
     /**
      * Phase 2: Bounce down.
      */
@@ -1098,13 +1120,13 @@ public abstract class PanelView extends FrameLayout {
         animator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                mHeightAnimator = null;
+                setAnimator(null);
                 onAnimationFinished.run();
                 notifyBarPanelExpansionChanged();
             }
         });
         animator.start();
-        mHeightAnimator = animator;
+        setAnimator(animator);
     }
 
     private ValueAnimator createHeightAnimator(float targetHeight) {
index ccb6438..f4f48a3 100644 (file)
@@ -36,11 +36,17 @@ import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.annotation.NonNull;
 import android.app.ActivityManager;
+import android.app.ActivityManager.StackId;
 import android.app.ActivityOptions;
+import android.app.INotificationManager;
+import android.app.KeyguardManager;
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
+import android.app.RemoteInput;
 import android.app.StatusBarManager;
+import android.app.TaskStackBuilder;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentCallbacks2;
@@ -49,8 +55,11 @@ import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.database.ContentObserver;
@@ -75,7 +84,9 @@ import android.media.session.PlaybackState;
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.AsyncTask;
+import android.os.Build;
 import android.os.Bundle;
+import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.PowerManager;
@@ -83,54 +94,73 @@ import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.os.SystemService;
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
+import android.service.vr.IVrManager;
+import android.service.vr.IVrStateCallbacks;
+import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.Slog;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.view.ContextThemeWrapper;
 import android.view.Display;
+import android.view.IWindowManager;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.ThreadedRenderer;
 import android.view.View;
+import android.view.ViewAnimationUtils;
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewStub;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.widget.DateTimeView;
 import android.widget.ImageView;
+import android.widget.RemoteViews;
 import android.widget.TextView;
+import android.widget.Toast;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.util.NotificationMessagingUtil;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.ActivityStarterDelegate;
+import com.android.systemui.DejankUtils;
 import com.android.systemui.DemoMode;
 import com.android.systemui.Dependency;
 import com.android.systemui.EventLogTags;
+import com.android.systemui.ForegroundServiceController;
 import com.android.systemui.Interpolators;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
+import com.android.systemui.RecentsComponent;
+import com.android.systemui.SwipeHelper;
+import com.android.systemui.SystemUI;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.UiOffloadThread;
 import com.android.systemui.assist.AssistManager;
@@ -141,12 +171,14 @@ import com.android.systemui.doze.DozeLog;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.fragments.PluginFragmentListener;
 import com.android.systemui.keyguard.KeyguardViewMediator;
-import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
 import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.qs.QSTileHost;
+import com.android.systemui.recents.Recents;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.recents.events.EventBus;
 import com.android.systemui.recents.events.activity.AppTransitionFinishedEvent;
@@ -194,11 +226,15 @@ import com.android.systemui.statusbar.policy.KeyguardUserSwitcher;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 import com.android.systemui.statusbar.policy.PreviewInflater;
+import com.android.systemui.statusbar.policy.RemoteInputView;
 import com.android.systemui.statusbar.policy.UserInfoController;
 import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+        .OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackStateAnimator;
+import com.android.systemui.util.NotificationChannels;
 import com.android.systemui.util.leak.LeakDetector;
 import com.android.systemui.volume.VolumeComponent;
 
@@ -209,48 +245,10 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import android.app.ActivityManager.StackId;
-import android.app.INotificationManager;
-import android.app.KeyguardManager;
-import android.app.NotificationChannel;
-import android.app.RemoteInput;
-import android.app.TaskStackBuilder;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
-import android.os.Build;
-import android.os.Handler;
-import android.service.notification.NotificationListenerService;
-import android.service.vr.IVrManager;
-import android.service.vr.IVrStateCallbacks;
-import android.text.TextUtils;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-import android.view.IWindowManager;
-import android.view.ViewAnimationUtils;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.RemoteViews;
-import android.widget.Toast;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.RecentsComponent;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.SystemUI;
-import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.statusbar.policy.RemoteInputView;
-import com.android.systemui.statusbar.stack.StackStateAnimator;
-import com.android.systemui.util.NotificationChannels;
-
 import java.util.HashSet;
+import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Set;
 import java.util.Stack;
 
@@ -473,6 +471,7 @@ public class StatusBar extends SystemUI implements DemoMode,
     int mSystemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE;
     private final Rect mLastFullscreenStackBounds = new Rect();
     private final Rect mLastDockedStackBounds = new Rect();
+    private final Rect mTmpRect = new Rect();
 
     // last value sent to window manager
     private int mLastDispatchedSystemUiVisibility = ~View.SYSTEM_UI_FLAG_VISIBLE;
@@ -718,6 +717,7 @@ public class StatusBar extends SystemUI implements DemoMode,
     private ConfigurationListener mConfigurationListener;
     private boolean mReinflateNotificationsOnUserSwitched;
     private HashMap<String, Entry> mPendingNotifications = new HashMap<>();
+    private ForegroundServiceController mForegroundServiceController;
 
     private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
         final int N = array.size();
@@ -759,6 +759,9 @@ public class StatusBar extends SystemUI implements DemoMode,
         mBatteryController = Dependency.get(BatteryController.class);
         mAssistManager = Dependency.get(AssistManager.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
+        mSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
+
+        mForegroundServiceController = Dependency.get(ForegroundServiceController.class);
 
         mWindowManager = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
         mDisplay = mWindowManager.getDefaultDisplay();
@@ -1369,20 +1372,33 @@ public class StatusBar extends SystemUI implements DemoMode,
         int numChildren = mStackScroller.getChildCount();
 
         final ArrayList<View> viewsToHide = new ArrayList<View>(numChildren);
+        final ArrayList<ExpandableNotificationRow> viewsToRemove = new ArrayList<>(numChildren);
         for (int i = 0; i < numChildren; i++) {
             final View child = mStackScroller.getChildAt(i);
             if (child instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                boolean parentVisible = false;
+                boolean hasClipBounds = child.getClipBounds(mTmpRect);
                 if (mStackScroller.canChildBeDismissed(child)) {
-                    if (child.getVisibility() == View.VISIBLE) {
+                    viewsToRemove.add(row);
+                    if (child.getVisibility() == View.VISIBLE
+                            && (!hasClipBounds || mTmpRect.height() > 0)) {
                         viewsToHide.add(child);
+                        parentVisible = true;
                     }
+                } else if (child.getVisibility() == View.VISIBLE
+                        && (!hasClipBounds || mTmpRect.height() > 0)) {
+                    parentVisible = true;
                 }
-                ExpandableNotificationRow row = (ExpandableNotificationRow) child;
                 List<ExpandableNotificationRow> children = row.getNotificationChildren();
-                if (row.areChildrenExpanded() && children != null) {
+                if (children != null) {
                     for (ExpandableNotificationRow childRow : children) {
-                        if (mStackScroller.canChildBeDismissed(childRow)) {
-                            if (childRow.getVisibility() == View.VISIBLE) {
+                        viewsToRemove.add(childRow);
+                        if (parentVisible && row.areChildrenExpanded()
+                                && mStackScroller.canChildBeDismissed(childRow)) {
+                            hasClipBounds = childRow.getClipBounds(mTmpRect);
+                            if (childRow.getVisibility() == View.VISIBLE
+                                    && (!hasClipBounds || mTmpRect.height() > 0)) {
                                 viewsToHide.add(childRow);
                             }
                         }
@@ -1390,7 +1406,7 @@ public class StatusBar extends SystemUI implements DemoMode,
                 }
             }
         }
-        if (viewsToHide.isEmpty()) {
+        if (viewsToRemove.isEmpty()) {
             animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
             return;
         }
@@ -1399,6 +1415,13 @@ public class StatusBar extends SystemUI implements DemoMode,
             @Override
             public void run() {
                 mStackScroller.setDismissAllInProgress(false);
+                for (ExpandableNotificationRow rowToRemove : viewsToRemove) {
+                    if (mStackScroller.canChildBeDismissed(rowToRemove)) {
+                        removeNotification(rowToRemove.getEntry().key, null);
+                    } else {
+                        rowToRemove.resetTranslation();
+                    }
+                }
                 try {
                     mBarService.onClearAllNotifications(mCurrentUserId);
                 } catch (Exception ex) { }
@@ -1577,6 +1600,10 @@ public class StatusBar extends SystemUI implements DemoMode,
             }
         }
         abortExistingInflation(key);
+
+        mForegroundServiceController.addNotification(notification,
+                mNotificationData.getImportance(key));
+
         mPendingNotifications.put(key, shadeEntry);
     }
 
@@ -1614,9 +1641,14 @@ public class StatusBar extends SystemUI implements DemoMode,
         mPendingNotifications.remove(entry.key);
         // If there was an async task started after the removal, we don't want to add it back to
         // the list, otherwise we might get leaks.
-        if (mNotificationData.get(entry.key) == null && !entry.row.isRemoved()) {
+        boolean isNew = mNotificationData.get(entry.key) == null;
+        if (isNew && !entry.row.isRemoved()) {
             addEntry(entry);
+        } else if (!isNew && entry.row.hasLowPriorityStateUpdated()) {
+            mVisualStabilityManager.onLowPriorityUpdated(entry);
+            updateNotificationShade();
         }
+        entry.row.setLowPriorityStateUpdated(false);
     }
 
     private boolean shouldSuppressFullScreenIntent(String key) {
@@ -1710,6 +1742,10 @@ public class StatusBar extends SystemUI implements DemoMode,
             return;
         }
 
+        if (entry != null) {
+            mForegroundServiceController.removeNotification(entry.notification);
+        }
+
         if (entry != null && entry.row != null) {
             entry.row.setRemoved();
             mStackScroller.cleanUpViewState(entry.row);
@@ -1820,23 +1856,20 @@ public class StatusBar extends SystemUI implements DemoMode,
                 // temporarily become children if they were isolated before.
                 continue;
             }
-            int vis = ent.notification.getNotification().visibility;
             int userId = ent.notification.getUserId();
 
             // Display public version of the notification if we need to redact.
-            boolean deviceSensitive = (isLockscreenPublicMode(mCurrentUserId)
-                    && !userAllowsPrivateNotificationsInPublic(mCurrentUserId));
-            boolean userSensitive = deviceSensitive || (isLockscreenPublicMode(userId)
-                    && !userAllowsPrivateNotificationsInPublic(userId));
-            boolean sensitiveNote = vis == Notification.VISIBILITY_PRIVATE;
-            boolean sensitivePackage = packageHasVisibilityOverride(ent.notification.getKey());
-            boolean sensitive = (sensitiveNote && userSensitive) || sensitivePackage;
-            boolean showingPublic = sensitive && isLockscreenPublicMode(userId);
-            if (showingPublic) {
+            boolean devicePublic = isLockscreenPublicMode(mCurrentUserId);
+            boolean userPublic = devicePublic || isLockscreenPublicMode(userId);
+            boolean needsRedaction = needsRedaction(ent);
+            boolean sensitive = userPublic && needsRedaction;
+            boolean deviceSensitive = devicePublic
+                    && !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
+            if (sensitive) {
                 updatePublicContentView(ent, ent.notification);
             }
             ent.row.setSensitive(sensitive, deviceSensitive);
-            ent.row.setNeedsRedaction(needsRedaction(ent));
+            ent.row.setNeedsRedaction(needsRedaction);
             if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) {
                 ExpandableNotificationRow summary = mGroupManager.getGroupSummary(
                         ent.row.getStatusBarNotification());
@@ -3544,6 +3577,12 @@ public class StatusBar extends SystemUI implements DemoMode,
                     // Do it after DismissAction has been processed to conserve the needed ordering.
                     mHandler.post(this::runPostCollapseRunnables);
                 }
+            } else if (isInLaunchTransition() && mNotificationPanel.isLaunchTransitionFinished()) {
+
+                // We are not dismissing the shade, but the launch transition is already finished,
+                // so nobody will call readyForKeyguardDone anymore. Post it such that
+                // keyguardDonePending gets called first.
+                mHandler.post(mStatusBarKeyguardViewManager::readyForKeyguardDone);
             }
             return deferred;
         }, cancelAction, afterKeyguardGone);
@@ -4315,7 +4354,12 @@ public class StatusBar extends SystemUI implements DemoMode,
             final int userId = mCurrentProfiles.valueAt(i).id;
             boolean isProfilePublic = devicePublic;
             if (!devicePublic && userId != mCurrentUserId) {
-                if (mStatusBarKeyguardViewManager.isSecure(userId)) {
+                // We can't rely on KeyguardManager#isDeviceLocked() for unified profile challenge
+                // due to a race condition where this code could be called before
+                // TrustManagerService updates its internal records, resulting in an incorrect
+                // state being cached in mLockscreenPublicMode. (b/35951989)
+                if (mLockPatternUtils.isSeparateProfileChallengeEnabled(userId)
+                        && mStatusBarKeyguardViewManager.isSecure(userId)) {
                     isProfilePublic = mKeyguardManager.isDeviceLocked(userId);
                 }
             }
@@ -4932,7 +4976,6 @@ public class StatusBar extends SystemUI implements DemoMode,
             where.getLocationInWindow(mTmpInt2);
             mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
                     mTmpInt2[1] + where.getHeight() / 2);
-            mNotificationPanel.setTouchDisabled(false);
             mStatusBarKeyguardViewManager.notifyDeviceWakeUpRequested();
             mFalsingManager.onScreenOnFromTouch();
         }
@@ -5187,6 +5230,7 @@ public class StatusBar extends SystemUI implements DemoMode,
     protected KeyguardManager mKeyguardManager;
     private LockPatternUtils mLockPatternUtils;
     private DeviceProvisionedController mDeviceProvisionedController;
+    protected SystemServicesProxy mSystemServicesProxy;
 
     // UI-specific methods
 
@@ -6077,6 +6121,9 @@ public class StatusBar extends SystemUI implements DemoMode,
     }
 
     public boolean isLockscreenPublicMode(int userId) {
+        if (userId == UserHandle.USER_ALL) {
+            return mLockscreenPublicMode.get(mCurrentUserId, false);
+        }
         return mLockscreenPublicMode.get(userId, false);
     }
 
@@ -6244,7 +6291,10 @@ public class StatusBar extends SystemUI implements DemoMode,
             StatusBarNotification sbn, ExpandableNotificationRow row) {
         row.setNeedsRedaction(needsRedaction(entry));
         boolean isLowPriority = mNotificationData.isAmbient(sbn.getKey());
+        boolean isUpdate = mNotificationData.get(entry.key) != null;
+        boolean wasLowPriority = row.isLowPriority();
         row.setIsLowPriority(isLowPriority);
+        row.setLowPriorityStateUpdated(isUpdate && (wasLowPriority != isLowPriority));
         // bind the click event to the content area
         mNotificationClicker.register(row, sbn);
 
@@ -6752,9 +6802,12 @@ public class StatusBar extends SystemUI implements DemoMode,
         entry.notification = notification;
         mGroupManager.onEntryUpdated(entry, oldNotification);
 
-        entry.updateIcons(mContext, n);
+        entry.updateIcons(mContext, notification);
         inflateViews(entry, mStackScroller);
 
+        mForegroundServiceController.updateNotification(notification,
+                mNotificationData.getImportance(key));
+
         boolean shouldPeek = shouldPeek(entry, notification);
         boolean alertAgain = alertAgain(entry, n);
 
@@ -6772,6 +6825,7 @@ public class StatusBar extends SystemUI implements DemoMode,
             boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
             Log.d(TAG, "notification is " + (isForCurrentUser ? "" : "not ") + "for you");
         }
+
         setAreThereNotifications();
     }
 
@@ -6808,6 +6862,7 @@ public class StatusBar extends SystemUI implements DemoMode,
 
     protected boolean shouldPeek(Entry entry, StatusBarNotification sbn) {
         if (!mUseHeadsUp || isDeviceInVrMode()) {
+            if (DEBUG) Log.d(TAG, "No peeking: no huns or vr mode");
             return false;
         }
 
@@ -6816,8 +6871,7 @@ public class StatusBar extends SystemUI implements DemoMode,
             return false;
         }
 
-        boolean inUse = mPowerManager.isScreenOn()
-                && !SystemServicesProxy.getInstance(mContext).isDreaming();
+        boolean inUse = mPowerManager.isScreenOn() && !mSystemServicesProxy.isDreaming();
 
         if (!inUse && !isDozing()) {
             if (DEBUG) {
@@ -6860,6 +6914,12 @@ public class StatusBar extends SystemUI implements DemoMode,
             }
         }
 
+        // Don't peek notifications that are suppressed due to group alert behavior
+        if (sbn.isGroup() && sbn.getNotification().suppressAlertingDueToGrouping()) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed due to group alert behavior");
+            return false;
+        }
+
         return true;
     }
 
index f050be4..f58a91b 100644 (file)
@@ -277,7 +277,7 @@ public class StatusBarWindowView extends FrameLayout {
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (mService.isDozing() && !mService.isPulsing()) {
+        if (mService.isDozing() && !mStackScrollLayout.hasPulsingNotifications()) {
             // Capture all touch events in always-on.
             return true;
         }
@@ -722,6 +722,10 @@ public class StatusBarWindowView extends FrameLayout {
         }
 
         @Override
+        public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) {
+        }
+
+        @Override
         public void reportActivityRelaunched() {
         }
     };
index dc33633..74a30fa 100644 (file)
@@ -23,6 +23,7 @@ import android.content.IntentFilter;
 import android.content.res.TypedArray;
 import android.icu.text.DateFormat;
 import android.icu.text.DisplayContext;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
@@ -115,4 +116,15 @@ public class DateView extends TextView {
             mLastText = text;
         }
     }
+
+    public void setDatePattern(String pattern) {
+        if (TextUtils.equals(pattern, mDatePattern)) {
+            return;
+        }
+        mDatePattern = pattern;
+        mDateFormat = null;
+        if (isAttachedToWindow()) {
+            updateClock();
+        }
+    }
 }
index 8e51ddb..cc7943b 100644 (file)
@@ -194,6 +194,11 @@ public class KeyButtonRipple extends Drawable {
         return true;
     }
 
+    @Override
+    public boolean hasFocusStateSpecified() {
+        return true;
+    }
+
     public void setPressed(boolean pressed) {
         if (mDark != mLastDark && pressed) {
             mRipplePaint = null;
index 67b5596..03a50a2 100644 (file)
@@ -253,11 +253,6 @@ public class MobileSignalController extends SignalController<
     }
 
     @Override
-    public int getQsCurrentIconId() {
-        return getCurrentIconId();
-    }
-
-    @Override
     public void notifyListeners(SignalCallback callback) {
         MobileIconGroup icons = getIcons();
 
@@ -276,9 +271,9 @@ public class MobileSignalController extends SignalController<
         String description = null;
         // Only send data sim callbacks to QS.
         if (mCurrentState.dataSim) {
-            qsTypeIcon = showDataIcon ? icons.mQsDataType : 0;
+            qsTypeIcon = showDataIcon ? icons.mDataType : 0;
             qsIcon = new IconState(mCurrentState.enabled
-                    && !mCurrentState.isEmergency, getQsCurrentIconId(), contentDescription);
+                    && !mCurrentState.isEmergency, getCurrentIconId(), contentDescription);
             description = mCurrentState.isEmergency ? null : mCurrentState.networkName;
         }
         boolean activityIn = mCurrentState.dataConnected
index aaa0568..d91ae39 100644 (file)
@@ -22,16 +22,6 @@ import com.android.systemui.statusbar.policy.MobileSignalController.MobileIconGr
 class TelephonyIcons {
     //***** Data connection icons
 
-    static final int QS_DATA_G = R.drawable.ic_qs_signal_g;
-    static final int QS_DATA_3G = R.drawable.ic_qs_signal_3g;
-    static final int QS_DATA_E = R.drawable.ic_qs_signal_e;
-    static final int QS_DATA_H = R.drawable.ic_qs_signal_h;
-    static final int QS_DATA_1X = R.drawable.ic_qs_signal_1x;
-    static final int QS_DATA_4G = R.drawable.ic_qs_signal_4g;
-    static final int QS_DATA_4G_PLUS = R.drawable.ic_qs_signal_4g_plus;
-    static final int QS_DATA_LTE = R.drawable.ic_qs_signal_lte;
-    static final int QS_DATA_LTE_PLUS = R.drawable.ic_qs_signal_lte_plus;
-
     static final int FLIGHT_MODE_ICON = R.drawable.stat_sys_airplane_mode;
 
     static final int ICON_LTE = R.drawable.stat_sys_data_fully_connected_lte;
@@ -46,8 +36,6 @@ class TelephonyIcons {
 
     static final int ICON_DATA_DISABLED = R.drawable.stat_sys_data_disabled;
 
-    static final int QS_ICON_DATA_DISABLED = R.drawable.ic_qs_data_disabled;
-
     static final MobileIconGroup CARRIER_NETWORK_CHANGE = new MobileIconGroup(
             "CARRIER_NETWORK_CHANGE",
             null,
@@ -75,7 +63,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_3g,
             TelephonyIcons.ICON_3G,
             true,
-            TelephonyIcons.QS_DATA_3G
+            TelephonyIcons.ICON_3G
             );
 
     static final MobileIconGroup WFC = new MobileIconGroup(
@@ -114,7 +102,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_edge,
             TelephonyIcons.ICON_E,
             false,
-            TelephonyIcons.QS_DATA_E
+            TelephonyIcons.ICON_E
             );
 
     static final MobileIconGroup ONE_X = new MobileIconGroup(
@@ -129,7 +117,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_cdma,
             TelephonyIcons.ICON_1X,
             true,
-            TelephonyIcons.QS_DATA_1X
+            TelephonyIcons.ICON_1X
             );
 
     static final MobileIconGroup G = new MobileIconGroup(
@@ -144,7 +132,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_gprs,
             TelephonyIcons.ICON_G,
             false,
-            TelephonyIcons.QS_DATA_G
+            TelephonyIcons.ICON_G
             );
 
     static final MobileIconGroup H = new MobileIconGroup(
@@ -159,7 +147,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_3_5g,
             TelephonyIcons.ICON_H,
             false,
-            TelephonyIcons.QS_DATA_H
+            TelephonyIcons.ICON_H
             );
 
     static final MobileIconGroup FOUR_G = new MobileIconGroup(
@@ -174,7 +162,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_4g,
             TelephonyIcons.ICON_4G,
             true,
-            TelephonyIcons.QS_DATA_4G
+            TelephonyIcons.ICON_4G
             );
 
     static final MobileIconGroup FOUR_G_PLUS = new MobileIconGroup(
@@ -189,7 +177,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_4g_plus,
             TelephonyIcons.ICON_4G_PLUS,
             true,
-            TelephonyIcons.QS_DATA_4G_PLUS
+            TelephonyIcons.ICON_4G_PLUS
             );
 
     static final MobileIconGroup LTE = new MobileIconGroup(
@@ -204,7 +192,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_lte,
             TelephonyIcons.ICON_LTE,
             true,
-            TelephonyIcons.QS_DATA_LTE
+            TelephonyIcons.ICON_LTE
             );
 
     static final MobileIconGroup LTE_PLUS = new MobileIconGroup(
@@ -219,7 +207,7 @@ class TelephonyIcons {
             R.string.accessibility_data_connection_lte_plus,
             TelephonyIcons.ICON_LTE_PLUS,
             true,
-            TelephonyIcons.QS_DATA_LTE_PLUS
+            TelephonyIcons.ICON_LTE_PLUS
             );
 
     static final MobileIconGroup DATA_DISABLED = new MobileIconGroup(
@@ -234,7 +222,7 @@ class TelephonyIcons {
             R.string.accessibility_cell_data_off,
             TelephonyIcons.ICON_DATA_DISABLED,
             false,
-            TelephonyIcons.QS_ICON_DATA_DISABLED
+            TelephonyIcons.ICON_DATA_DISABLED
             );
 }
 
index e80d3b3..0fd2445 100644 (file)
@@ -36,11 +36,13 @@ import android.service.notification.Condition;
 import android.service.notification.IConditionListener;
 import android.service.notification.ZenModeConfig;
 import android.service.notification.ZenModeConfig.ZenRule;
+import android.support.annotation.VisibleForTesting;
 import android.util.Log;
 import android.util.Slog;
 
 import com.android.systemui.qs.GlobalSetting;
 import com.android.systemui.settings.CurrentUserTracker;
+import com.android.systemui.util.Utils;
 
 import java.util.ArrayList;
 import java.util.LinkedHashMap;
@@ -169,45 +171,32 @@ public class ZenModeControllerImpl extends CurrentUserTracker implements ZenMode
     }
 
     private void fireNextAlarmChanged() {
-        for (Callback cb : mCallbacks) {
-            cb.onNextAlarmChanged();
-        }
+        Utils.safeForeach(mCallbacks, c -> c.onNextAlarmChanged());
     }
 
     private void fireEffectsSuppressorChanged() {
-        for (Callback cb : mCallbacks) {
-            cb.onEffectsSupressorChanged();
-        }
+        Utils.safeForeach(mCallbacks, c -> c.onEffectsSupressorChanged());
     }
 
     private void fireZenChanged(int zen) {
-        for (Callback cb : mCallbacks) {
-            cb.onZenChanged(zen);
-        }
+        Utils.safeForeach(mCallbacks, c -> c.onZenChanged(zen));
     }
 
     private void fireZenAvailableChanged(boolean available) {
-        for (Callback cb : mCallbacks) {
-            cb.onZenAvailableChanged(available);
-        }
+        Utils.safeForeach(mCallbacks, c -> c.onZenAvailableChanged(available));
     }
 
     private void fireConditionsChanged(Condition[] conditions) {
-        for (Callback cb : mCallbacks) {
-            cb.onConditionsChanged(conditions);
-        }
+        Utils.safeForeach(mCallbacks, c -> c.onConditionsChanged(conditions));
     }
 
     private void fireManualRuleChanged(ZenRule rule) {
-        for (Callback cb : mCallbacks) {
-            cb.onManualRuleChanged(rule);
-        }
+        Utils.safeForeach(mCallbacks, c -> c.onManualRuleChanged(rule));
     }
 
-    private void fireConfigChanged(ZenModeConfig config) {
-        for (Callback cb : mCallbacks) {
-            cb.onConfigChanged(config);
-        }
+    @VisibleForTesting
+    protected void fireConfigChanged(ZenModeConfig config) {
+        Utils.safeForeach(mCallbacks, c -> c.onConfigChanged(config));
     }
 
     private void updateConditions(Condition[] conditions) {
index e409b9c..41ef781 100644 (file)
@@ -59,7 +59,7 @@ public class AmbientState {
     private boolean mPanelTracking;
     private boolean mExpansionChanging;
     private boolean mPanelFullWidth;
-    private boolean mPulsing;
+    private boolean mHasPulsingNotifications;
     private boolean mUnlockHintRunning;
 
     public AmbientState(Context context) {
@@ -287,12 +287,12 @@ public class AmbientState {
         mPanelTracking = panelTracking;
     }
 
-    public boolean isPulsing() {
-        return mPulsing;
+    public boolean hasPulsingNotifications() {
+        return mHasPulsingNotifications;
     }
 
-    public void setPulsing(boolean pulsing) {
-        mPulsing = pulsing;
+    public void setHasPulsingNotifications(boolean hasPulsing) {
+        mHasPulsingNotifications = hasPulsing;
     }
 
     public boolean isPanelTracking() {
index 0dbd1d6..b6964a0 100644 (file)
@@ -297,10 +297,10 @@ public class NotificationChildrenContainer extends ViewGroup {
         } else {
             header.reapply(getContext(), mNotificationHeader);
         }
-        mNotificationHeaderWrapper.notifyContentUpdated(mContainingNotification);
+        mNotificationHeaderWrapper.onContentUpdated(mContainingNotification);
         recreateLowPriorityHeader(builder);
         recreateAmbientHeader(builder);
-        resetHeaderVisibilityIfNeeded(mNotificationHeader, calculateDesiredHeader());
+        updateHeaderVisibility(false /* animate */);
         updateChildrenHeaderAppearance();
     }
 
@@ -316,14 +316,14 @@ public class NotificationChildrenContainer extends ViewGroup {
             mNotificationHeaderAmbient = (ViewGroup) header.apply(getContext(), this);
             mNotificationHeaderWrapperAmbient = NotificationViewWrapper.wrap(getContext(),
                     mNotificationHeaderAmbient, mContainingNotification);
-            mNotificationHeaderWrapperAmbient.notifyContentUpdated(mContainingNotification);
+            mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
             addView(mNotificationHeaderAmbient, 0);
             invalidate();
         } else {
             header.reapply(getContext(), mNotificationHeaderAmbient);
         }
         resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, calculateDesiredHeader());
-        mNotificationHeaderWrapperAmbient.notifyContentUpdated(mContainingNotification);
+        mNotificationHeaderWrapperAmbient.onContentUpdated(mContainingNotification);
     }
 
     /**
@@ -354,7 +354,7 @@ public class NotificationChildrenContainer extends ViewGroup {
             } else {
                 header.reapply(getContext(), mNotificationHeaderLowPriority);
             }
-            mNotificationHeaderWrapperLowPriority.notifyContentUpdated(mContainingNotification);
+            mNotificationHeaderWrapperLowPriority.onContentUpdated(mContainingNotification);
             resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, calculateDesiredHeader());
         } else {
             removeView(mNotificationHeaderLowPriority);
@@ -833,6 +833,11 @@ public class NotificationChildrenContainer extends ViewGroup {
         return mNotificationHeaderLowPriority;
     }
 
+    @VisibleForTesting
+    public ViewGroup getCurrentHeaderView() {
+        return mCurrentHeader;
+    }
+
     public void notifyShowAmbientChanged() {
         updateHeaderVisibility(false);
     }
@@ -869,7 +874,12 @@ public class NotificationChildrenContainer extends ViewGroup {
                 desiredHeader.setVisibility(VISIBLE);
             }
             if (currentHeader != null) {
-                getWrapperForView(currentHeader).setVisible(false);
+                // Wrapper can be null if we were a low priority notification
+                // and just destroyed it by calling setIsLowPriority(false)
+                NotificationViewWrapper wrapper = getWrapperForView(currentHeader);
+                if (wrapper != null) {
+                    wrapper.setVisible(false);
+                }
                 currentHeader.setVisibility(INVISIBLE);
             }
         }
@@ -878,7 +888,7 @@ public class NotificationChildrenContainer extends ViewGroup {
         resetHeaderVisibilityIfNeeded(mNotificationHeaderAmbient, desiredHeader);
         resetHeaderVisibilityIfNeeded(mNotificationHeaderLowPriority, desiredHeader);
 
-        mCurrentHeader = currentHeader;
+        mCurrentHeader = desiredHeader;
     }
 
     private void resetHeaderVisibilityIfNeeded(View header, View desiredHeader) {
index 431f646..3cc3604 100644 (file)
@@ -53,7 +53,6 @@ import android.view.ViewTreeObserver;
 import android.view.WindowInsets;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
-import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
 import android.widget.OverScroller;
@@ -816,7 +815,8 @@ public class NotificationStackScrollLayout extends ViewGroup
      */
     private float getAppearEndPosition() {
         int appearPosition;
-        if (mEmptyShadeView.getVisibility() == GONE) {
+        int notGoneChildCount = getNotGoneChildCount();
+        if (mEmptyShadeView.getVisibility() == GONE && notGoneChildCount != 0) {
             int minNotificationsForShelf = 1;
             if (mTrackingHeadsUp || mHeadsUpManager.hasPinnedHeadsUp()) {
                 appearPosition = mHeadsUpManager.getTopHeadsUpPinnedHeight();
@@ -824,7 +824,7 @@ public class NotificationStackScrollLayout extends ViewGroup
             } else {
                 appearPosition = 0;
             }
-            if (getNotGoneChildCount() >= minNotificationsForShelf) {
+            if (notGoneChildCount >= minNotificationsForShelf) {
                 appearPosition += mShelf.getIntrinsicHeight();
             }
         } else {
@@ -1941,7 +1941,7 @@ public class NotificationStackScrollLayout extends ViewGroup
         int numShownItems = 0;
         boolean finish = false;
         int maxDisplayedNotifications = mAmbientState.isDark()
-                ? (isPulsing() ? 1 : 0)
+                ? (hasPulsingNotifications() ? 1 : 0)
                 : mMaxDisplayedNotifications;
 
         for (int i = 0; i < getChildCount(); i++) {
@@ -1950,7 +1950,8 @@ public class NotificationStackScrollLayout extends ViewGroup
                     && !expandableView.hasNoContentHeight()) {
                 boolean limitReached = maxDisplayedNotifications != -1
                         && numShownItems >= maxDisplayedNotifications;
-                boolean notificationOnAmbientThatIsNotPulsing = isPulsing()
+                boolean notificationOnAmbientThatIsNotPulsing = mAmbientState.isDark()
+                        && hasPulsingNotifications()
                         && expandableView instanceof ExpandableNotificationRow
                         && !isPulsing(((ExpandableNotificationRow) expandableView).getEntry());
                 if (limitReached || notificationOnAmbientThatIsNotPulsing) {
@@ -2008,7 +2009,7 @@ public class NotificationStackScrollLayout extends ViewGroup
         return false;
     }
 
-    private boolean isPulsing() {
+    public boolean hasPulsingNotifications() {
         return mPulsing != null;
     }
 
@@ -2220,14 +2221,15 @@ public class NotificationStackScrollLayout extends ViewGroup
         ActivatableNotificationView firstView = mFirstVisibleBackgroundChild;
         int top = 0;
         if (firstView != null) {
-            int finalTranslationY = (int) ViewState.getFinalTranslationY(firstView);
+            // Round Y up to avoid seeing the background during animation
+            int finalTranslationY = (int) Math.ceil(ViewState.getFinalTranslationY(firstView));
             if (mAnimateNextBackgroundTop
                     || mTopAnimator == null && mCurrentBounds.top == finalTranslationY
                     || mTopAnimator != null && mEndAnimationRect.top == finalTranslationY) {
                 // we're ending up at the same location as we are now, lets just skip the animation
                 top = finalTranslationY;
             } else {
-                top = (int) firstView.getTranslationY();
+                top = (int) Math.ceil(firstView.getTranslationY());
             }
         }
         ActivatableNotificationView lastView = mShelf.hasItemsInStableShelf()
@@ -2837,7 +2839,7 @@ public class NotificationStackScrollLayout extends ViewGroup
     }
 
     private void updateNotificationAnimationStates() {
-        boolean running = mAnimationsEnabled || isPulsing();
+        boolean running = mAnimationsEnabled || hasPulsingNotifications();
         mShelf.setAnimationsEnabled(running);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
@@ -2848,7 +2850,7 @@ public class NotificationStackScrollLayout extends ViewGroup
     }
 
     private void updateAnimationState(View child) {
-        updateAnimationState((mAnimationsEnabled || isPulsing())
+        updateAnimationState((mAnimationsEnabled || hasPulsingNotifications())
                 && (mIsExpanded || isPinnedHeadsUp(child)), child);
     }
 
@@ -4117,7 +4119,7 @@ public class NotificationStackScrollLayout extends ViewGroup
             return;
         }
         mPulsing = pulsing;
-        mAmbientState.setPulsing(isPulsing());
+        mAmbientState.setHasPulsingNotifications(hasPulsingNotifications());
         updateNotificationAnimationStates();
         updateContentHeight();
         notifyHeightChangeListener(mShelf);
index 12a8783..5c10e7e 100644 (file)
@@ -413,6 +413,7 @@ public class StackScrollAlgorithm {
                 if (i == 0 && row.isAboveShelf()) {
                     // the first hun can't get off screen.
                     clampHunToMaxTranslation(ambientState, row, childState);
+                    childState.hidden = false;
                 }
             }
             if (row.isPinned()) {
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
new file mode 100644 (file)
index 0000000..f4aebae
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.util;
+
+import java.util.List;
+import java.util.function.Consumer;
+
+public class Utils {
+
+    /**
+     * Allows lambda iteration over a list. It is done in reverse order so it is safe
+     * to add or remove items during the iteration.
+     */
+    public static <T> void safeForeach(List<T> list, Consumer<T> c) {
+        for (int i = list.size() - 1; i >= 0; i--) {
+            c.accept(list.get(i));
+        }
+    }
+}
index e86a34a..f6d36e8 100644 (file)
@@ -60,7 +60,8 @@ public class VolumeDialogComponent implements VolumeComponent, TunerService.Tuna
     private final Context mContext;
     private final VolumeDialogControllerImpl mController;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
-            ActivityInfo.CONFIG_FONT_SCALE);
+            ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
+            | ActivityInfo.CONFIG_ASSETS_PATHS);
     private final Extension mExtension;
     private VolumeDialog mDialog;
     private VolumePolicy mVolumePolicy = new VolumePolicy(
index 51fcdbb..ecdea4f 100644 (file)
@@ -57,7 +57,6 @@ import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
-import com.android.systemui.R.string;
 import com.android.systemui.statusbar.policy.ZenModeController;
 
 import java.io.FileDescriptor;
@@ -294,11 +293,6 @@ public class ZenModePanel extends FrameLayout {
     private void onAttach() {
         setExpanded(true);
         mAttached = true;
-        for (int i = 0; i < mZenRadioGroupContent.getChildCount(); i++) {
-            ConditionTag tag = getConditionTagAt(i);
-            if (tag != null) tag.rb.setChecked(false);
-            mZenRadioGroupContent.getChildAt(i).setTag(null);
-        }
         mAttachedZen = mController.getZen();
         ZenRule manualRule = mController.getManualRule();
         mExitCondition = manualRule != null ? manualRule.condition : null;
@@ -311,6 +305,7 @@ public class ZenModePanel extends FrameLayout {
         setSessionExitCondition(copy(mExitCondition));
         updateWidgets();
         setRequestingConditions(!mHidden);
+        ensureSelection();
     }
 
     private void onDetach() {
@@ -366,9 +361,6 @@ public class ZenModePanel extends FrameLayout {
         if (expanded == mExpanded) return;
         if (DEBUG) Log.d(mTag, "setExpanded " + expanded);
         mExpanded = expanded;
-        if (mExpanded) {
-            ensureSelection();
-        }
         updateWidgets();
         fireExpanded();
     }
@@ -464,7 +456,8 @@ public class ZenModePanel extends FrameLayout {
                     ActivityManager.getCurrentUser(), false);
             return c;
         }
-        return null;
+        // If there is a manual rule, but it has no condition listed then it is forever.
+        return forever();
     }
 
     private void handleUpdateZen(int zen) {
@@ -491,6 +484,7 @@ public class ZenModePanel extends FrameLayout {
             final ConditionTag tag = getConditionTagAt(i);
             if (tag != null && sameConditionId(tag.condition, mExitCondition)) {
                 bind(exitCondition, mZenRadioGroupContent.getChildAt(i), i);
+                tag.rb.setChecked(true);
                 return;
             }
         }
@@ -498,6 +492,7 @@ public class ZenModePanel extends FrameLayout {
                 exitCondition.id)) {
             bind(exitCondition, mZenRadioGroupContent.getChildAt(COUNTDOWN_CONDITION_INDEX),
                     COUNTDOWN_CONDITION_INDEX);
+            getConditionTagAt(COUNTDOWN_CONDITION_INDEX).rb.setChecked(true);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/ForegroundServiceControllerTest.java
new file mode 100644 (file)
index 0000000..1f5255a
--- /dev/null
@@ -0,0 +1,296 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui;
+
+import android.annotation.UserIdInt;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+import com.android.internal.messages.nano.SystemMessageProto;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@SmallTest
+@RunWith(AndroidJUnit4.class)
+public class ForegroundServiceControllerTest extends SysuiTestCase {
+    public static @UserIdInt int USERID_ONE = 10; // UserManagerService.MIN_USER_ID;
+    public static @UserIdInt int USERID_TWO = USERID_ONE + 1;
+
+    private ForegroundServiceController fsc;
+
+    @Before
+    public void setUp() throws Exception {
+        fsc = new ForegroundServiceControllerImpl(mContext);
+    }
+
+    @Test
+    public void testNotificationCRUD() {
+        StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, "com.example.app1");
+        StatusBarNotification sbn_user2_app2_fg = makeMockFgSBN(USERID_TWO, "com.example.app2");
+        StatusBarNotification sbn_user1_app3_fg = makeMockFgSBN(USERID_ONE, "com.example.app3");
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user2_app1 = makeMockSBN(USERID_TWO, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+
+        assertFalse(fsc.removeNotification(sbn_user1_app3_fg));
+        assertFalse(fsc.removeNotification(sbn_user2_app2_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app1_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+        fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_DEFAULT);
+
+        // these are never added to the tracker
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+        fsc.updateNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.updateNotification(sbn_user2_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        // should still not be there
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+
+        fsc.updateNotification(sbn_user2_app2_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.updateNotification(sbn_user1_app3_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+
+        assertTrue(fsc.removeNotification(sbn_user1_app3_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app3_fg));
+
+        assertTrue(fsc.removeNotification(sbn_user2_app2_fg));
+        assertFalse(fsc.removeNotification(sbn_user2_app2_fg));
+
+        assertTrue(fsc.removeNotification(sbn_user1_app1_fg));
+        assertFalse(fsc.removeNotification(sbn_user1_app1_fg));
+
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.removeNotification(sbn_user2_app1));
+    }
+
+    @Test
+    public void testDungeonPredicate() {
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_dungeon = makeMockSBN(USERID_ONE, "android",
+                SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+                null, Notification.FLAG_NO_CLEAR);
+
+        assertTrue(fsc.isDungeonNotification(sbn_user1_dungeon));
+        assertFalse(fsc.isDungeonNotification(sbn_user1_app1));
+    }
+
+    @Test
+    public void testDungeonCRUD() {
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, "com.example.app1",
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_dungeon = makeMockSBN(USERID_ONE, "android",
+                SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+                null, Notification.FLAG_NO_CLEAR);
+
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        fsc.addNotification(sbn_user1_dungeon, NotificationManager.IMPORTANCE_DEFAULT);
+
+        fsc.removeNotification(sbn_user1_dungeon);
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+    }
+
+    @Test
+    public void testNeedsDungeonAfterRemovingUnrelatedNotification() {
+        final String PKG1 = "com.example.app100";
+
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
+
+        // first add a normal notification
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        // nothing required yet
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        // now the app starts a fg service
+        fsc.addNotification(makeMockDungeon(USERID_ONE, new String[]{ PKG1 }),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        // add the fg notification
+        fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has got it covered
+        // remove the boring notification
+        fsc.removeNotification(sbn_user1_app1);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has STILL got it covered
+        assertTrue(fsc.removeNotification(sbn_user1_app1_fg));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+    }
+
+    @Test
+    public void testSimpleAddRemove() {
+        final String PKG1 = "com.example.app1";
+        final String PKG2 = "com.example.app2";
+
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+
+        // no services are "running"
+        fsc.addNotification(makeMockDungeon(USERID_ONE, null),
+                NotificationManager.IMPORTANCE_DEFAULT);
+
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG1}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // switch to different package
+        fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG2}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.updateNotification(makeMockDungeon(USERID_TWO, new String[]{PKG1}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_TWO)); // finally user2 needs one too
+
+        fsc.updateNotification(makeMockDungeon(USERID_ONE, new String[]{PKG2, PKG1}),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.removeNotification(makeMockDungeon(USERID_ONE, null /*unused*/));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        fsc.removeNotification(makeMockDungeon(USERID_TWO, null /*unused*/));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+    }
+
+    @Test
+    public void testDungeonBasic() {
+        final String PKG1 = "com.example.app0";
+
+        StatusBarNotification sbn_user1_app1 = makeMockSBN(USERID_ONE, PKG1,
+                5000, "monkeys", Notification.FLAG_AUTO_CANCEL);
+        StatusBarNotification sbn_user1_app1_fg = makeMockFgSBN(USERID_ONE, PKG1);
+
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT); // not fg
+        fsc.addNotification(makeMockDungeon(USERID_ONE, new String[]{ PKG1 }),
+                NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        fsc.addNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // app1 has got it covered
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // let's take out the other notification and see what happens.
+
+        fsc.removeNotification(sbn_user1_app1);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE)); // still covered by sbn_user1_app1_fg
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // let's attempt to downgrade the notification from FLAG_FOREGROUND and see what we get
+        StatusBarNotification sbn_user1_app1_fg_sneaky = makeMockFgSBN(USERID_ONE, PKG1);
+        sbn_user1_app1_fg_sneaky.getNotification().flags = 0;
+        fsc.updateNotification(sbn_user1_app1_fg_sneaky, NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // ok, ok, we'll put it back
+        sbn_user1_app1_fg_sneaky.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
+        fsc.updateNotification(sbn_user1_app1_fg, NotificationManager.IMPORTANCE_DEFAULT);
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        assertTrue(fsc.removeNotification(sbn_user1_app1_fg_sneaky));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE)); // should be required!
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+
+        // now let's test an upgrade
+        fsc.addNotification(sbn_user1_app1, NotificationManager.IMPORTANCE_DEFAULT);
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+        sbn_user1_app1.getNotification().flags |= Notification.FLAG_FOREGROUND_SERVICE;
+        fsc.updateNotification(sbn_user1_app1,
+                NotificationManager.IMPORTANCE_DEFAULT); // this is now a fg notification
+
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+
+        // remove it, make sure we're out of compliance again
+        assertTrue(fsc.removeNotification(sbn_user1_app1)); // was fg, should return true
+        assertFalse(fsc.removeNotification(sbn_user1_app1));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+        assertTrue(fsc.isDungeonNeededForUser(USERID_ONE));
+
+        // finally, let's turn off the service
+        fsc.addNotification(makeMockDungeon(USERID_ONE, null),
+                NotificationManager.IMPORTANCE_DEFAULT);
+
+        assertFalse(fsc.isDungeonNeededForUser(USERID_ONE));
+        assertFalse(fsc.isDungeonNeededForUser(USERID_TWO));
+    }
+
+    private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
+            int flags) {
+        final Notification n = mock(Notification.class);
+        n.flags = flags;
+        return makeMockSBN(userid, pkg, id, tag, n);
+    }
+    private StatusBarNotification makeMockSBN(int userid, String pkg, int id, String tag,
+            Notification n) {
+        final StatusBarNotification sbn = mock(StatusBarNotification.class);
+        when(sbn.getNotification()).thenReturn(n);
+        when(sbn.getId()).thenReturn(id);
+        when(sbn.getPackageName()).thenReturn(pkg);
+        when(sbn.getTag()).thenReturn(null);
+        when(sbn.getUserId()).thenReturn(userid);
+        when(sbn.getUser()).thenReturn(new UserHandle(userid));
+        when(sbn.getKey()).thenReturn("MOCK:"+userid+"|"+pkg+"|"+id+"|"+tag);
+        return sbn;
+    }
+    private StatusBarNotification makeMockFgSBN(int userid, String pkg) {
+        return makeMockSBN(userid, pkg, 1000, "foo", Notification.FLAG_FOREGROUND_SERVICE);
+    }
+    private StatusBarNotification makeMockDungeon(int userid, String[] pkgs) {
+        final Notification n = mock(Notification.class);
+        n.flags = Notification.FLAG_ONGOING_EVENT;
+        final Bundle extras = new Bundle();
+        if (pkgs != null) extras.putStringArray(Notification.EXTRA_FOREGROUND_APPS, pkgs);
+        n.extras = extras;
+        final StatusBarNotification sbn = makeMockSBN(userid, "android",
+                SystemMessageProto.SystemMessage.NOTE_FOREGROUND_SERVICES,
+                null, n);
+        sbn.getNotification().extras = extras;
+        return sbn;
+    }
+}
index 15cebc7..8905d72 100644 (file)
 
 package com.android.systemui;
 
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
 import android.app.Fragment;
+import android.app.Instrumentation;
 import android.support.test.InstrumentationRegistry;
 import android.testing.BaseFragmentTest;
 
 import com.android.systemui.utils.leaks.LeakCheckedTest;
 import com.android.systemui.utils.leaks.LeakCheckedTest.SysuiLeakCheck;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 
@@ -33,6 +38,7 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest {
 
     protected final TestableDependency mDependency = new TestableDependency(mContext);
     protected SysuiTestableContext mSysuiContext;
+    private Instrumentation mRealInstrumentation;
 
     public SysuiBaseFragmentTest(Class<? extends Fragment> cls) {
         super(cls);
@@ -44,6 +50,20 @@ public abstract class SysuiBaseFragmentTest extends BaseFragmentTest {
         SystemUIFactory.createFromConfig(mContext);
         // TODO: Figure out another way to give reference to a SysuiTestableContext.
         mSysuiContext = (SysuiTestableContext) mContext;
+
+        mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
+        Instrumentation inst = spy(mRealInstrumentation);
+        when(inst.getContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        when(inst.getTargetContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        InstrumentationRegistry.registerInstance(inst, InstrumentationRegistry.getArguments());
+    }
+
+    @After
+    public void SysuiTeardown() {
+        InstrumentationRegistry.registerInstance(mRealInstrumentation,
+                InstrumentationRegistry.getArguments());
     }
 
     @Override
index 9b67529..361a20f 100644 (file)
  */
 package com.android.systemui;
 
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.app.Instrumentation;
 import android.content.Context;
 import android.os.Handler;
 import android.os.Looper;
@@ -24,6 +28,7 @@ import android.support.test.filters.SmallTest;
 import android.testing.LeakCheck;
 import android.util.Log;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 
@@ -42,11 +47,26 @@ public abstract class SysuiTestCase {
     public SysuiTestableContext mContext = new SysuiTestableContext(
             InstrumentationRegistry.getContext(), getLeakCheck());
     public TestableDependency mDependency = new TestableDependency(mContext);
+    private Instrumentation mRealInstrumentation;
 
     @Before
     public void SysuiSetup() throws Exception {
         System.setProperty("dexmaker.share_classloader", "true");
         SystemUIFactory.createFromConfig(mContext);
+
+        mRealInstrumentation = InstrumentationRegistry.getInstrumentation();
+        Instrumentation inst = spy(mRealInstrumentation);
+        when(inst.getContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        when(inst.getTargetContext()).thenThrow(new RuntimeException(
+                "SysUI Tests should use SysuiTestCase#getContext or SysuiTestCase#mContext"));
+        InstrumentationRegistry.registerInstance(inst, InstrumentationRegistry.getArguments());
+    }
+
+    @After
+    public void SysuiTeardown() {
+        InstrumentationRegistry.registerInstance(mRealInstrumentation,
+                InstrumentationRegistry.getArguments());
     }
 
     protected LeakCheck getLeakCheck() {
index 1161987..2e547e1 100644 (file)
@@ -18,6 +18,7 @@ package com.android.systemui.statusbar;
 
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 
 import android.content.Context;
@@ -87,5 +88,18 @@ public class ExpandableNotificationRowTest extends SysuiTestCase {
         verify(mockContainer).reInflateViews(any(), any());
     }
 
+    @Test
+    public void testIconColorShouldBeUpdatedWhenSensitive() throws Exception {
+        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+        row.setSensitive(true, true);
+        row.setHideSensitive(true, false, 0, 0);
+        verify(row).updateShelfIconColor();
+    }
 
+    @Test
+    public void testIconColorShouldBeUpdatedWhenSettingDark() throws Exception {
+        ExpandableNotificationRow row = spy(mNotificationTestHelper.createRow());
+        row.setDark(true, false, 0);
+        verify(row).updateShelfIconColor();
+    }
 }
index fc9b608..917a9f5 100644 (file)
@@ -53,11 +53,14 @@ public class NotificationCustomViewWrapperTest extends SysuiTestCase {
         RemoteViews views = new RemoteViews(mContext.getPackageName(), R.layout.custom_view_dark);
         View v = views.apply(mContext, null);
         NotificationViewWrapper wrap = NotificationCustomViewWrapper.wrap(mContext, v, mRow);
-        wrap.notifyContentUpdated(mRow);
-        Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+        wrap.onContentUpdated(mRow);
+        Assert.assertTrue("No background set, when applying custom background view",
+                wrap.getCustomBackgroundColor() != 0);
         views.reapply(mContext, v);
-        wrap.notifyContentUpdated(mRow);
-        Assert.assertTrue(wrap.getCustomBackgroundColor() != 0);
+        wrap.onReinflated();
+        wrap.onContentUpdated(mRow);
+        Assert.assertTrue("Reapplying a custom remote view lost it's background!",
+                wrap.getCustomBackgroundColor() != 0);
     }
 
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/SignalClusterViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/SignalClusterViewTest.java
new file mode 100644 (file)
index 0000000..28a5aa3
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the
+ * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the specific language governing
+ * permissions and limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import android.support.test.filters.SmallTest;
+import android.telephony.SubscriptionInfo;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.LayoutInflater;
+
+import com.android.systemui.R;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.NetworkController.IconState;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.Arrays;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class SignalClusterViewTest extends SysuiTestCase {
+
+    private SignalClusterView mSignalCluster;
+
+    @Before
+    public void setup() {
+        mSignalCluster = (SignalClusterView) LayoutInflater.from(mContext)
+                .inflate(R.layout.signal_cluster_view, null);
+    }
+
+    @Test
+    public void testNonDefaultSim() {
+        SubscriptionInfo first = mock(SubscriptionInfo.class);
+        SubscriptionInfo second = mock(SubscriptionInfo.class);
+        when(first.getSubscriptionId()).thenReturn(0);
+        when(second.getSubscriptionId()).thenReturn(1);
+        mSignalCluster.setSubs(Arrays.asList(first, second));
+        mSignalCluster.setQsSignalCluster();
+        mSignalCluster.setMobileDataIndicators(new IconState(true, 0, 0, ""), null, 0, 0,
+                false, false, "", "", false, 1, false);
+    }
+
+}
\ No newline at end of file
index ebeb24c..9da28a0 100644 (file)
@@ -24,6 +24,7 @@ import android.view.View;
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.NotificationTestHelper;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -35,7 +36,9 @@ public class NotificationViewWrapperTest extends SysuiTestCase {
 
     @Test
     public void constructor_doesntUseViewContext() throws Exception {
-        new TestableNotificationViewWrapper(mContext, null /* view */, null /* row */);
+        new TestableNotificationViewWrapper(mContext,
+                new View(mContext),
+                new NotificationTestHelper(getContext()).createRow());
     }
 
     static class TestableNotificationViewWrapper extends NotificationViewWrapper {
index bf6b394..db6647c 100644 (file)
 
 package com.android.systemui.statusbar.phone;
 
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
 import static org.mockito.Matchers.any;
 import static org.mockito.Matchers.anyBoolean;
+import static org.mockito.Matchers.anyString;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
+import android.app.Notification;
 import android.metrics.LogMaker;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.IPowerManager;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.service.notification.StatusBarNotification;
 import android.support.test.filters.SmallTest;
 import android.support.test.metricshelper.MetricsAsserts;
 import android.support.test.runner.AndroidJUnit4;
@@ -33,9 +47,11 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.logging.testing.FakeMetricsLogger;
 import com.android.keyguard.KeyguardHostView.OnDismissAction;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.recents.misc.SystemServicesProxy;
 import com.android.systemui.statusbar.ActivatableNotificationView;
 import com.android.systemui.statusbar.KeyguardIndicationController;
 import com.android.systemui.statusbar.NotificationData;
+import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 import org.junit.Before;
@@ -52,19 +68,35 @@ public class StatusBarTest extends SysuiTestCase {
     NotificationStackScrollLayout mStackScroller;
     StatusBar mStatusBar;
     FakeMetricsLogger mMetricsLogger;
-
+    HeadsUpManager mHeadsUpManager;
+    NotificationData mNotificationData;
+    PowerManager mPowerManager;
+    SystemServicesProxy mSystemServicesProxy;
+    NotificationPanelView mNotificationPanelView;
     private DisplayMetrics mDisplayMetrics = new DisplayMetrics();
 
     @Before
-    public void setup() {
+    public void setup() throws Exception {
         mStatusBarKeyguardViewManager = mock(StatusBarKeyguardViewManager.class);
         mUnlockMethodCache = mock(UnlockMethodCache.class);
         mKeyguardIndicationController = mock(KeyguardIndicationController.class);
         mStackScroller = mock(NotificationStackScrollLayout.class);
         mMetricsLogger = new FakeMetricsLogger();
+        mHeadsUpManager = mock(HeadsUpManager.class);
+        mNotificationData = mock(NotificationData.class);
+        mSystemServicesProxy = mock(SystemServicesProxy.class);
+        mNotificationPanelView = mock(NotificationPanelView.class);
+        IPowerManager powerManagerService = mock(IPowerManager.class);
+        HandlerThread handlerThread = new HandlerThread("TestThread");
+        handlerThread.start();
+        mPowerManager = new PowerManager(mContext, powerManagerService,
+                new Handler(handlerThread.getLooper()));
+        when(powerManagerService.isInteractive()).thenReturn(true);
+
         mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger);
         mStatusBar = new TestableStatusBar(mStatusBarKeyguardViewManager, mUnlockMethodCache,
-                mKeyguardIndicationController, mStackScroller);
+                mKeyguardIndicationController, mStackScroller, mHeadsUpManager,
+                mNotificationData, mPowerManager, mSystemServicesProxy, mNotificationPanelView);
 
         doAnswer(invocation -> {
             OnDismissAction onDismissAction = (OnDismissAction) invocation.getArguments()[0];
@@ -210,14 +242,63 @@ public class StatusBarTest extends SysuiTestCase {
                         .setType(MetricsEvent.TYPE_ACTION));
     }
 
+    @Test
+    public void testShouldPeek_nonSuppressedGroupSummary() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(getContext(), "a")
+                .setGroup("a")
+                .setGroupSummary(true)
+                .setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
+                .build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+
+        assertTrue(mStatusBar.shouldPeek(entry, sbn));
+    }
+
+    @Test
+    public void testShouldPeek_suppressedGroupSummary() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        Notification n = new Notification.Builder(getContext(), "a")
+                .setGroup("a")
+                .setGroupSummary(true)
+                .setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
+                .build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+
+        assertFalse(mStatusBar.shouldPeek(entry, sbn));
+    }
+
     static class TestableStatusBar extends StatusBar {
         public TestableStatusBar(StatusBarKeyguardViewManager man,
                 UnlockMethodCache unlock, KeyguardIndicationController key,
-                NotificationStackScrollLayout stack) {
+                NotificationStackScrollLayout stack, HeadsUpManager hum, NotificationData nd,
+                PowerManager pm, SystemServicesProxy ssp, NotificationPanelView panelView) {
             mStatusBarKeyguardViewManager = man;
             mUnlockMethodCache = unlock;
             mKeyguardIndicationController = key;
             mStackScroller = stack;
+            mHeadsUpManager = hum;
+            mNotificationData = nd;
+            mUseHeadsUp = true;
+            mPowerManager = pm;
+            mSystemServicesProxy = ssp;
+            mNotificationPanel = panelView;
         }
 
         @Override
index cb20639..6157d44 100644 (file)
@@ -111,7 +111,7 @@ public class CallbackHandlerTest extends SysuiTestCase {
         String typeDescription = "Test 1";
         String description = "Test 2";
         int type = R.drawable.stat_sys_data_fully_connected_1x;
-        int qsType = R.drawable.ic_qs_signal_1x;
+        int qsType = type;
         boolean wide = true;
         int subId = 5;
         boolean roaming = true;
index 505e1d8..c233fea 100644 (file)
@@ -70,7 +70,7 @@ public class NetworkControllerBaseTest extends SysuiTestCase {
     protected static final int DEFAULT_SIGNAL_STRENGTH = DEFAULT_LEVEL;
     protected static final int DEFAULT_QS_SIGNAL_STRENGTH = DEFAULT_LEVEL;
     protected static final int DEFAULT_ICON = TelephonyIcons.ICON_3G;
-    protected static final int DEFAULT_QS_ICON = TelephonyIcons.QS_DATA_3G;
+    protected static final int DEFAULT_QS_ICON = DEFAULT_ICON;
 
     protected NetworkControllerImpl mNetworkController;
     protected MobileSignalController mMobileSignalController;
index dfe00f9..ac64263 100644 (file)
@@ -25,7 +25,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
         setupDefaultSignal();
 
         verifyDataIndicators(TelephonyIcons.ICON_3G,
-                TelephonyIcons.QS_DATA_3G);
+                TelephonyIcons.ICON_3G);
     }
 
     @Test
@@ -35,7 +35,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
                 TelephonyManager.NETWORK_TYPE_GSM);
 
         verifyDataIndicators(TelephonyIcons.ICON_G,
-                TelephonyIcons.QS_DATA_G);
+                TelephonyIcons.ICON_G);
     }
 
     @Test
@@ -45,7 +45,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
                 TelephonyManager.NETWORK_TYPE_CDMA);
 
         verifyDataIndicators(TelephonyIcons.ICON_1X,
-                TelephonyIcons.QS_DATA_1X);
+                TelephonyIcons.ICON_1X);
     }
 
     @Test
@@ -55,7 +55,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
                 TelephonyManager.NETWORK_TYPE_EDGE);
 
         verifyDataIndicators(TelephonyIcons.ICON_E,
-                TelephonyIcons.QS_DATA_E);
+                TelephonyIcons.ICON_E);
     }
 
     @Test
@@ -65,7 +65,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
                 TelephonyManager.NETWORK_TYPE_LTE);
 
         verifyDataIndicators(TelephonyIcons.ICON_LTE,
-                TelephonyIcons.QS_DATA_LTE);
+                TelephonyIcons.ICON_LTE);
     }
 
     @Test
@@ -75,7 +75,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
                 TelephonyManager.NETWORK_TYPE_HSPA);
 
         verifyDataIndicators(TelephonyIcons.ICON_H,
-                TelephonyIcons.QS_DATA_H);
+                TelephonyIcons.ICON_H);
     }
 
     @Test
@@ -104,7 +104,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
                 TelephonyManager.NETWORK_TYPE_LTE);
 
         verifyDataIndicators(TelephonyIcons.ICON_4G,
-                TelephonyIcons.QS_DATA_4G);
+                TelephonyIcons.ICON_4G);
     }
 
     @Ignore("Flaky")
@@ -117,7 +117,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
         setConnectivity(NetworkCapabilities.TRANSPORT_CELLULAR, false, false);
 
         verifyDataIndicators(TelephonyIcons.ICON_DATA_DISABLED,
-                TelephonyIcons.QS_ICON_DATA_DISABLED);
+                TelephonyIcons.ICON_DATA_DISABLED);
     }
 
     @Test
@@ -148,7 +148,7 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
         mNetworkController.handleConfigurationChanged();
 
         verifyDataIndicators(TelephonyIcons.ICON_4G,
-                TelephonyIcons.QS_DATA_4G);
+                TelephonyIcons.ICON_4G);
     }
 
     @Test
@@ -158,13 +158,13 @@ public class NetworkControllerDataTest extends NetworkControllerBaseTest {
                 TelephonyManager.NETWORK_TYPE_LTE);
 
         verifyDataIndicators(TelephonyIcons.ICON_LTE,
-                TelephonyIcons.QS_DATA_LTE);
+                TelephonyIcons.ICON_LTE);
 
         when(mServiceState.getDataNetworkType())
                 .thenReturn(TelephonyManager.NETWORK_TYPE_HSPA);
         updateServiceState();
         verifyDataIndicators(TelephonyIcons.ICON_H,
-                TelephonyIcons.QS_DATA_H);
+                TelephonyIcons.ICON_H);
     }
 
     @Test
index 1627925..aa62075 100644 (file)
@@ -214,7 +214,7 @@ public class NetworkControllerSignalTest extends NetworkControllerBaseTest {
 
             verifyLastQsMobileDataIndicators(true,
                     testStrength,
-                    TelephonyIcons.QS_DATA_1X, false, false);
+                    TelephonyIcons.ICON_1X, false, false);
         }
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/ZenModeControllerImplTest.java
new file mode 100644 (file)
index 0000000..8124bf3
--- /dev/null
@@ -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 com.android.systemui.statusbar.policy;
+
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import android.os.Handler;
+import android.service.notification.ZenModeConfig;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.policy.ZenModeController.Callback;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@SmallTest
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+public class ZenModeControllerImplTest extends SysuiTestCase {
+
+    private Callback mCallback;
+
+    @Test
+    public void testRemoveDuringCallback() {
+        ZenModeControllerImpl controller = new ZenModeControllerImpl(mContext, new Handler());
+        mCallback = new Callback() {
+            @Override
+            public void onConfigChanged(ZenModeConfig config) {
+                controller.removeCallback(mCallback);
+            }
+        };
+        controller.addCallback(mCallback);
+        Callback mockCallback = mock(Callback.class);
+        controller.addCallback(mockCallback);
+        controller.fireConfigChanged(null);
+        verify(mockCallback).onConfigChanged(eq(null));
+    }
+
+}
\ No newline at end of file
index e6c8815..2dd96b6 100644 (file)
@@ -60,4 +60,12 @@ public class NotificationChildrenContainerTest extends SysuiTestCase {
         Assert.assertTrue(lowPriorityHeaderView.getParent() == null);
         Assert.assertTrue(childrenContainer.getLowPriorityHeaderView() == null);
     }
+
+    @Test
+    public void testRecreateNotificationHeader_hasHeader() {
+        NotificationChildrenContainer childrenContainer = mGroup.getChildrenContainer();
+        childrenContainer.recreateNotificationHeader(null);
+        Assert.assertNotNull("Children container must have a header after recreation",
+                childrenContainer.getCurrentHeaderView());
+    }
 }
index 9b7c597..d925364 100644 (file)
@@ -41,9 +41,7 @@ public class WakeLockTest extends SysuiTestCase {
 
     @Before
     public void setUp() {
-        Context context = InstrumentationRegistry.getContext();
-
-        mInner = WakeLock.createPartialInner(context, WakeLockTest.class.getName());
+        mInner = WakeLock.createPartialInner(mContext, WakeLockTest.class.getName());
         mWakeLock = WakeLock.wrap(mInner);
     }
 
index f37bfac..3dd75bb 100644 (file)
@@ -3962,6 +3962,16 @@ message MetricsEvent {
     // OS: O
     APP_TRANSITION_BIND_APPLICATION_DELAY_MS = 945;
 
+    // FIELD - The group ID of a notification.
+    // Type: string
+    // OS: O
+    FIELD_NOTIFICATION_GROUP_ID = 946;
+
+    // FIELD - If the notification is a group summary: 1.
+    // Type: int encoded boolean
+    // OS: O
+    FIELD_NOTIFICATION_GROUP_SUMMARY = 947;
+
     // ---- End O Constants, all O constants go above this line ----
 
     // Add new aosp constants above this line.
index 93b5ed5..03f25bf 100644 (file)
@@ -711,10 +711,13 @@ public final class AutofillManagerService extends SystemService {
             ContentResolver resolver = mContext.getContentResolver();
             resolver.registerContentObserver(Settings.Secure.getUriFor(
                     Settings.Secure.AUTOFILL_SERVICE), false, this, UserHandle.USER_ALL);
+            resolver.registerContentObserver(Settings.Secure.getUriFor(
+                    Settings.Secure.USER_SETUP_COMPLETE), false, this, UserHandle.USER_ALL);
         }
 
         @Override
         public void onChange(boolean selfChange, Uri uri, int userId) {
+            if (sVerbose) Slog.v(TAG, "onChange(): uri=" + uri + ", userId=" + userId);
             synchronized (mLock) {
                 updateCachedServiceLocked(userId);
             }
index 2cb0bd5..38b796b 100644 (file)
@@ -51,7 +51,7 @@ import android.service.autofill.FillEventHistory.Event;
 import android.service.autofill.FillResponse;
 import android.service.autofill.IAutoFillService;
 import android.text.TextUtils;
-import android.util.ArrayMap;
+import android.util.ArraySet;
 import android.util.LocalLog;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -99,6 +99,12 @@ final class AutofillManagerServiceImpl {
      */
     private boolean mDisabled;
 
+    /**
+     * Caches whether the setup completed for the current user.
+     */
+    @GuardedBy("mLock")
+    private boolean mSetupComplete;
+
     private final HandlerCaller.Callback mHandlerCallback = (msg) -> {
         switch (msg.what) {
             case MSG_SERVICE_SAVE:
@@ -171,6 +177,12 @@ final class AutofillManagerServiceImpl {
         }
     }
 
+    private boolean isSetupCompletedLocked() {
+        final String setupComplete = Settings.Secure.getStringForUser(
+                mContext.getContentResolver(), Settings.Secure.USER_SETUP_COMPLETE, mUserId);
+        return "1".equals(setupComplete);
+    }
+
     private String getComponentNameFromSettings() {
         return Settings.Secure.getStringForUser(
                 mContext.getContentResolver(), Settings.Secure.AUTOFILL_SERVICE, mUserId);
@@ -178,6 +190,12 @@ final class AutofillManagerServiceImpl {
 
     void updateLocked(boolean disabled) {
         final boolean wasEnabled = isEnabled();
+        if (sVerbose) {
+            Slog.v(TAG, "updateLocked(u=" + mUserId + "): wasEnabled=" + wasEnabled
+                    + ", mSetupComplete= " + mSetupComplete
+                    + ", disabled=" + disabled + ", mDisabled=" + mDisabled);
+        }
+        mSetupComplete = isSetupCompletedLocked();
         mDisabled = disabled;
         ComponentName serviceComponent = null;
         ServiceInfo serviceInfo = null;
@@ -199,8 +217,9 @@ final class AutofillManagerServiceImpl {
             } else {
                 mInfo = null;
             }
-            if (wasEnabled != isEnabled()) {
-                if (!isEnabled()) {
+            final boolean isEnabled = isEnabled();
+            if (wasEnabled != isEnabled) {
+                if (!isEnabled) {
                     final int sessionCount = mSessions.size();
                     for (int i = sessionCount - 1; i >= 0; i--) {
                         final Session session = mSessions.valueAt(i);
@@ -447,10 +466,17 @@ final class AutofillManagerServiceImpl {
         if (sVerbose) Slog.v(TAG, "destroyLocked()");
 
         final int numSessions = mSessions.size();
+        final ArraySet<RemoteFillService> remoteFillServices = new ArraySet<>(numSessions);
         for (int i = 0; i < numSessions; i++) {
-            mSessions.valueAt(i).destroyLocked();
+            final RemoteFillService remoteFillService = mSessions.valueAt(i).destroyLocked();
+            if (remoteFillService != null) {
+                remoteFillServices.add(remoteFillService);
+            }
         }
         mSessions.clear();
+        for (int i = 0; i < remoteFillServices.size(); i++) {
+            remoteFillServices.valueAt(i).destroy();
+        }
 
         sendStateToClients(true);
     }
@@ -534,6 +560,7 @@ final class AutofillManagerServiceImpl {
         pw.print(prefix); pw.print("Default component: ");
             pw.println(mContext.getString(R.string.config_defaultAutofillService));
         pw.print(prefix); pw.print("Disabled: "); pw.println(mDisabled);
+        pw.print(prefix); pw.print("Setup complete: "); pw.println(mSetupComplete);
         pw.print(prefix); pw.print("Last prune: "); pw.println(mLastPrune);
 
         final int size = mSessions.size();
@@ -617,7 +644,7 @@ final class AutofillManagerServiceImpl {
     }
 
     boolean isEnabled() {
-        return mInfo != null && !mDisabled;
+        return mSetupComplete && mInfo != null && !mDisabled;
     }
 
     @Override
index bad8dcf..073d7b2 100644 (file)
@@ -419,7 +419,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
             notifyUnavailableToClient();
         }
         synchronized (mLock) {
-            processResponseLocked(response);
+            processResponseLocked(response, requestFlags);
         }
 
         final LogMaker log = (new LogMaker(MetricsEvent.AUTOFILL_REQUEST))
@@ -774,20 +774,29 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                 break;
             }
 
-            final AutofillValue currentValue = viewState.getCurrentValue();
-            if (currentValue == null || currentValue.isEmpty()) {
-                if (sDebug) {
-                    Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+            AutofillValue value = viewState.getCurrentValue();
+            if (value == null || value.isEmpty()) {
+                final AutofillValue initialValue = getValueFromContexts(id);
+                if (initialValue != null) {
+                    if (sDebug) {
+                        Slog.d(TAG, "Value of required field " + id + " didn't change; "
+                                + "using initial value (" + initialValue + ") instead");
+                    }
+                    value = initialValue;
+                } else {
+                    if (sDebug) {
+                        Slog.d(TAG, "showSaveLocked(): empty value for required " + id );
+                    }
+                    allRequiredAreNotEmpty = false;
+                    break;
                 }
-                allRequiredAreNotEmpty = false;
-                break;
             }
             final AutofillValue filledValue = viewState.getAutofilledValue();
 
-            if (!currentValue.equals(filledValue)) {
+            if (!value.equals(filledValue)) {
                 if (sDebug) {
                     Slog.d(TAG, "showSaveLocked(): found a change on required " + id + ": "
-                            + filledValue + " => " + currentValue);
+                            + filledValue + " => " + value);
                 }
                 atLeastOneChanged = true;
             }
@@ -845,6 +854,31 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
     }
 
     /**
+     * Gets the latest non-empty value for the given id in the autofill contexts.
+     */
+    @Nullable
+    private AutofillValue getValueFromContexts(AutofillId id) {
+        AutofillValue value = null;
+        final int numContexts = mContexts.size();
+        for (int i = 0; i < numContexts; i++) {
+            final FillContext context = mContexts.get(i);
+            // TODO: create a function that gets just one node so it doesn't create an array
+            // unnecessarily
+            final ViewNode[] nodes = context.findViewNodesByAutofillIds(id);
+            if (nodes != null) {
+                AutofillValue candidate = nodes[0].getAutofillValue();
+                if (sDebug) {
+                    Slog.d(TAG, "getValueFromContexts(" + id + ") at " + i + ": " + candidate);
+                }
+                if (candidate != null && !candidate.isEmpty()) {
+                    value = candidate;
+                }
+            }
+        }
+        return value;
+    }
+
+    /**
      * Calls service when user requested save.
      */
     void callSaveLocked() {
@@ -1009,7 +1043,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                     || action == ACTION_VIEW_ENTERED) {
                 if (sVerbose) Slog.v(TAG, "Creating viewState for " + id + " on " + action);
                 boolean isIgnored = isIgnoredLocked(id);
-                viewState = new ViewState(this, id, value, this,
+                viewState = new ViewState(this, id, this,
                         isIgnored ? ViewState.STATE_IGNORED : ViewState.STATE_INITIAL);
                 mViewStates.put(id, viewState);
                 if (isIgnored) {
@@ -1026,7 +1060,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
             case ACTION_START_SESSION:
                 // View is triggering autofill.
                 mCurrentViewId = viewState.id;
-                viewState.update(value, virtualBounds);
+                viewState.update(value, virtualBounds, flags);
                 viewState.setState(ViewState.STATE_STARTED_SESSION);
                 requestNewFillResponseLocked(flags);
                 break;
@@ -1065,7 +1099,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                 }
 
                 // If the ViewState is ready to be displayed, onReady() will be called.
-                viewState.update(value, virtualBounds);
+                viewState.update(value, virtualBounds, flags);
                 break;
             case ACTION_VIEW_EXITED:
                 if (mCurrentViewId == viewState.id) {
@@ -1204,10 +1238,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         // Replace the old response
         mResponses.put(newResponse.getRequestId(), newResponse);
         // Now process the new response
-        processResponseLocked(newResponse);
+        processResponseLocked(newResponse, 0);
     }
 
-    private void processResponseLocked(@NonNull FillResponse newResponse) {
+    private void processResponseLocked(@NonNull FillResponse newResponse, int flags) {
         // Make sure we are hiding the UI which will be shown
         // only if handling the current response requires it.
         hideAllUiIfOwnedByMe();
@@ -1215,7 +1249,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         final int requestId = newResponse.getRequestId();
         if (sVerbose) {
             Slog.v(TAG, "processResponseLocked(): mCurrentViewId=" + mCurrentViewId
-                    + ", reqId=" + requestId + ", resp=" + newResponse);
+                    + ",flags=" + flags + ", reqId=" + requestId + ", resp=" + newResponse);
         }
 
         if (mResponses == null) {
@@ -1231,21 +1265,9 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
             return;
         }
 
-        final ArrayList<Dataset> datasets = newResponse.getDatasets();
-
-        if (datasets != null && datasets.size() == 1) {
-            // Check if it its a single response for a manual request, in which case it should
-            // be automatically filled
-            final FillContext context = getFillContextByRequestIdLocked(requestId);
-            if (context != null && (context.getStructure().getFlags() & FLAG_MANUAL_REQUEST) != 0) {
-                Slog.d(TAG, "autofilling manual request directly");
-                autoFill(requestId, 0, datasets.get(0));
-                return;
-            }
-        }
         // Updates the UI, if necessary.
         final ViewState currentView = mViewStates.get(mCurrentViewId);
-        currentView.maybeCallOnFillReady();
+        currentView.maybeCallOnFillReady(flags);
     }
 
     /**
@@ -1319,7 +1341,7 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         if (viewState != null)  {
             viewState.setState(state);
         } else {
-            viewState = new ViewState(this, id, null, this, state);
+            viewState = new ViewState(this, id, this, state);
             if (sVerbose) {
                 Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
             }
@@ -1331,20 +1353,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         return viewState;
     }
 
-    /**
-     * Resets the given state from all existing views in the given dataset.
-     */
-    private void resetViewStatesLocked(@NonNull Dataset dataset, int state) {
-        final ArrayList<AutofillId> ids = dataset.getFieldIds();
-        for (int j = 0; j < ids.size(); j++) {
-            final AutofillId id = ids.get(j);
-            final ViewState viewState = mViewStates.get(id);
-            if (viewState != null)  {
-                viewState.resetState(state);
-            }
-        }
-    }
-
     void autoFill(int requestId, int datasetIndex, Dataset dataset) {
         synchronized (mLock) {
             if (mDestroyed) {
@@ -1396,10 +1404,16 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         }
     }
 
+    @Override
+    public String toString() {
+        return "Session: [id=" + id + ", pkg=" + mPackageName + "]";
+    }
+
     void dumpLocked(String prefix, PrintWriter pw) {
         final String prefix2 = prefix + "  ";
         pw.print(prefix); pw.print("id: "); pw.println(id);
         pw.print(prefix); pw.print("uid: "); pw.println(uid);
+        pw.print(prefix); pw.print("mPackagename: "); pw.println(mPackageName);
         pw.print(prefix); pw.print("mActivityToken: "); pw.println(mActivityToken);
         pw.print(prefix); pw.print("mResponses: ");
         if (mResponses == null) {
@@ -1452,8 +1466,6 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                 return;
             }
             try {
-                if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
-
                 // Skip null values as a null values means no change
                 final int entryCount = dataset.getFieldIds().size();
                 final List<AutofillId> ids = new ArrayList<>(entryCount);
@@ -1480,6 +1492,8 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                     if (waitingDatasetAuth) {
                         hideFillUiIfOwnedByMe();
                     }
+                    if (sDebug) Slog.d(TAG, "autoFillApp(): the buck is on the app: " + dataset);
+
                     mClient.autofill(id, ids, values);
                     setViewStatesLocked(null, dataset, ViewState.STATE_AUTOFILLED, false);
                 }
@@ -1496,15 +1510,15 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
         }
     }
 
-    void destroyLocked() {
+    RemoteFillService destroyLocked() {
         if (mDestroyed) {
-            return;
+            return null;
         }
-        mRemoteFillService.destroy();
         hideAllUiIfOwnedByMe();
         mUi.clearCallback(this);
         mDestroyed = true;
         mMetricsLogger.action(MetricsEvent.AUTOFILL_SESSION_FINISHED, mPackageName);
+        return mRemoteFillService;
     }
 
     private void hideAllUiIfOwnedByMe() {
@@ -1528,8 +1542,11 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
                     + id + " destroyed");
             return;
         }
-        destroyLocked();
+        final RemoteFillService remoteFillService = destroyLocked();
         mService.removeSessionLocked(id);
+        if (remoteFillService != null) {
+            remoteFillService.destroy();
+        }
     }
 
     private int getLastResponseIndex() {
index 8a52c96..51659bb 100644 (file)
@@ -16,6 +16,7 @@
 
 package com.android.server.autofill;
 
+import static android.service.autofill.FillRequest.FLAG_MANUAL_REQUEST;
 import static com.android.server.autofill.Helper.sDebug;
 import static com.android.server.autofill.Helper.sVerbose;
 
@@ -73,16 +74,14 @@ final class ViewState {
     private final Session mSession;
 
     private FillResponse mResponse;
-    private AutofillValue mInitialValue;
     private AutofillValue mCurrentValue;
     private AutofillValue mAutofilledValue;
     private Rect mVirtualBounds;
     private int mState;
 
-    ViewState(Session session, AutofillId id, AutofillValue value, Listener listener, int state) {
+    ViewState(Session session, AutofillId id, Listener listener, int state) {
         mSession = session;
         this.id = id;
-        mInitialValue = value;
         mListener = listener;
         mState = state;
     }
@@ -117,11 +116,6 @@ final class ViewState {
     }
 
     @Nullable
-    AutofillValue getInitialValue() {
-        return mInitialValue;
-    }
-
-    @Nullable
     FillResponse getResponse() {
         return mResponse;
     }
@@ -157,7 +151,7 @@ final class ViewState {
     // TODO: refactor / rename / document this method (and maybeCallOnFillReady) to make it clear
     // that it can change the value and update the UI; similarly, should replace code that
     // directly sets mAutofillValue to use encapsulation.
-    void update(@Nullable AutofillValue autofillValue, @Nullable Rect virtualBounds) {
+    void update(@Nullable AutofillValue autofillValue, @Nullable Rect virtualBounds, int flags) {
         if (autofillValue != null) {
             mCurrentValue = autofillValue;
         }
@@ -165,7 +159,7 @@ final class ViewState {
             mVirtualBounds = virtualBounds;
         }
 
-        maybeCallOnFillReady();
+        maybeCallOnFillReady(flags);
     }
 
     /**
@@ -173,8 +167,8 @@ final class ViewState {
      * Listener#onFillReady(FillResponse, AutofillId, AutofillValue)} if the
      * fill UI is ready to be displayed (i.e. when response and bounds are set).
      */
-    void maybeCallOnFillReady() {
-        if ((mState & STATE_AUTOFILLED) != 0) {
+    void maybeCallOnFillReady(int flags) {
+        if ((mState & STATE_AUTOFILLED) != 0 && (flags & FLAG_MANUAL_REQUEST) == 0) {
             if (sDebug) Slog.d(TAG, "Ignoring UI for " + id + " on " + getStateAsString());
             return;
         }
@@ -188,8 +182,8 @@ final class ViewState {
 
     @Override
     public String toString() {
-        return "ViewState: [id=" + id + ", initialValue=" + mInitialValue
-                + ", currentValue=" + mCurrentValue + ", autofilledValue=" + mAutofilledValue
+        return "ViewState: [id=" + id + ", currentValue=" + mCurrentValue
+                + ", autofilledValue=" + mAutofilledValue
                 + ", bounds=" + mVirtualBounds + ", state=" + getStateAsString() + "]";
     }
 
@@ -206,7 +200,6 @@ final class ViewState {
                 pw.println(mResponse.getRequestId());
             }
         }
-        pw.print(prefix); pw.print("initialValue:" ); pw.println(mInitialValue);
         pw.print(prefix); pw.print("currentValue:" ); pw.println(mCurrentValue);
         pw.print(prefix); pw.print("autofilledValue:" ); pw.println(mAutofilledValue);
         pw.print(prefix); pw.print("virtualBounds:" ); pw.println(mVirtualBounds);
index c3d5505..8ffe8f5 100644 (file)
@@ -332,6 +332,10 @@ public final class AutoFillUI {
 
     @android.annotation.UiThread
     private void hideSaveUiUiThread(@Nullable AutoFillUiCallback callback) {
+        if (sVerbose) {
+            Slog.v(TAG, "hideSaveUiUiThread(): mSaveUi=" + mSaveUi + ", callback=" + callback
+                    + ", mCallback=" + mCallback);
+        }
         if (mSaveUi != null && (callback == null || callback == mCallback)) {
             mSaveUi.destroy();
             mSaveUi = null;
index d315b3d..e9c98e9 100644 (file)
@@ -158,6 +158,7 @@ final class FillUi {
                     final RemoteViews presentation = dataset.getFieldPresentation(index);
                     final View view;
                     try {
+                        if (sVerbose) Slog.v(TAG, "setting remote view for " + focusedViewId);
                         view = presentation.apply(context, null, interceptionHandler);
                     } catch (RuntimeException e) {
                         Slog.e(TAG, "Error inflating remote views", e);
@@ -203,6 +204,7 @@ final class FillUi {
                 return;
             }
             if (count <= 0) {
+                if (sDebug) Slog.d(TAG, "No dataset matches filter: " + mFilterText);
                 mCallback.requestHideFillUi();
             } else {
                 if (updateContentSize()) {
@@ -382,6 +384,7 @@ final class FillUi {
          * Shows the window.
          */
         public void show(WindowManager.LayoutParams params) {
+            if (sVerbose) Slog.v(TAG, "show(): showing=" + mShowing + ", params="+  params);
             try {
                 if (!mShowing) {
                     params.accessibilityTitle = mContentView.getContext()
@@ -395,6 +398,12 @@ final class FillUi {
             } catch (WindowManager.BadTokenException e) {
                 if (sDebug) Slog.d(TAG, "Filed with with token " + params.token + " gone.");
                 mCallback.onDestroy();
+            } catch (IllegalStateException e) {
+                // WM throws an ISE if mContentView was added twice; this should never happen -
+                // since show() and hide() are always called in the UIThread - but when it does,
+                // it should not crash the system.
+                Slog.e(TAG, "Exception showing window " + params, e);
+                mCallback.onDestroy();
             }
         }
 
@@ -402,10 +411,18 @@ final class FillUi {
          * Hides the window.
          */
         void hide() {
-            if (mShowing) {
-                mContentView.setOnTouchListener(null);
-                mWm.removeView(mContentView);
-                mShowing = false;
+            try {
+                if (mShowing) {
+                    mContentView.setOnTouchListener(null);
+                    mWm.removeView(mContentView);
+                    mShowing = false;
+                }
+            } catch (IllegalStateException e) {
+                // WM might thrown an ISE when removing the mContentView; this should never
+                // happen - since show() and hide() are always called in the UIThread - but if it
+                // does, it should not crash the system.
+                Slog.e(TAG, "Exception hiding window ", e);
+                mCallback.onDestroy();
             }
         }
 
@@ -486,7 +503,7 @@ final class FillUi {
                         final String value = item.getValue();
                         // No value, i.e. null, matches any filter
                         if (value == null
-                                || value.toLowerCase().contains(constraintLowerCase)) {
+                                || value.toLowerCase().startsWith(constraintLowerCase)) {
                             filteredItems.add(item);
                         }
                     }
index d25ffce..491af91 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.server.autofill.ui;
 
 import static com.android.server.autofill.Helper.sDebug;
+import static com.android.server.autofill.Helper.sVerbose;
 
 import android.annotation.NonNull;
 import android.app.Dialog;
@@ -63,7 +64,7 @@ final class SaveUi {
 
         @Override
         public void onSave() {
-            if (sDebug) Slog.d(TAG, "onSave(): " + mDone);
+            if (sDebug) Slog.d(TAG, "OneTimeListener.onSave(): " + mDone);
             if (mDone) {
                 return;
             }
@@ -73,7 +74,7 @@ final class SaveUi {
 
         @Override
         public void onCancel(IntentSender listener) {
-            if (sDebug) Slog.d(TAG, "onCancel(): " + mDone);
+            if (sDebug) Slog.d(TAG, "OneTimeListener.onCancel(): " + mDone);
             if (mDone) {
                 return;
             }
@@ -83,7 +84,7 @@ final class SaveUi {
 
         @Override
         public void onDestroy() {
-            if (sDebug) Slog.d(TAG, "onDestroy(): " + mDone);
+            if (sDebug) Slog.d(TAG, "OneTimeListener.onDestroy(): " + mDone);
             if (mDone) {
                 return;
             }
@@ -158,9 +159,8 @@ final class SaveUi {
             subTitleView.setVisibility(View.VISIBLE);
         }
 
-        Slog.i(TAG, "Showing save dialog: " + mTitle);
         if (sDebug) {
-            Slog.d(TAG, "SubTitle: " + mSubTitle);
+            Slog.d(TAG, "on constructor: title=" + mTitle + ", subTitle=" + mSubTitle);
         }
 
         final TextView noButton = view.findViewById(R.id.autofill_save_no);
@@ -169,15 +169,15 @@ final class SaveUi {
         } else {
             noButton.setText(R.string.autofill_save_no);
         }
-        noButton.setOnClickListener((v) -> mListener.onCancel(
-                info.getNegativeActionListener()));
+        View.OnClickListener cancelListener =
+                (v) -> mListener.onCancel(info.getNegativeActionListener());
+        noButton.setOnClickListener(cancelListener);
 
         final View yesButton = view.findViewById(R.id.autofill_save_yes);
         yesButton.setOnClickListener((v) -> mListener.onSave());
 
         final View closeButton = view.findViewById(R.id.autofill_save_close);
-        closeButton.setOnClickListener((v) -> mListener.onCancel(
-                info.getNegativeActionListener()));
+        closeButton.setOnClickListener(cancelListener);
 
         mDialog = new Dialog(context, R.style.Theme_DeviceDefault_Light_Panel);
         mDialog.setContentView(view);
@@ -195,13 +195,16 @@ final class SaveUi {
         params.width = WindowManager.LayoutParams.MATCH_PARENT;
         params.accessibilityTitle = context.getString(R.string.autofill_save_accessibility_title);
 
+        Slog.i(TAG, "Showing save dialog: " + mTitle);
         mDialog.show();
     }
 
     void destroy() {
+        if (sDebug) Slog.d(TAG, "destroy()");
         throwIfDestroyed();
         mListener.onDestroy();
         mHandler.removeCallbacksAndMessages(mListener);
+        if (sVerbose) Slog.v(TAG, "destroy(): dismissing dialog");
         mDialog.dismiss();
         mDestroyed = true;
     }
@@ -212,6 +215,11 @@ final class SaveUi {
         }
     }
 
+    @Override
+    public String toString() {
+        return mTitle == null ? "NO TITLE" : mTitle.toString();
+    }
+
     void dump(PrintWriter pw, String prefix) {
         pw.print(prefix); pw.print("title: "); pw.println(mTitle);
         pw.print(prefix); pw.print("subtitle: "); pw.println(mSubTitle);
index 6502c01..68f8c1b 100644 (file)
@@ -41,14 +41,10 @@ option java_package com.android.server
 # ---------------------------
 # DeviceStorageMonitorService.java
 # ---------------------------
-# The disk space free on the /data partition, in bytes
-2744 free_storage_changed (data|2|2)
-# Device low memory notification and disk space free on the /data partition, in bytes at that time
-2745 low_storage (data|2|2)
-# disk space free on the /data, /system, and /cache partitions in bytes
-2746 free_storage_left (data|2|2),(system|2|2),(cache|2|2)
-# file on cache partition was deleted
+# File on cache partition was deleted
 2748 cache_file_deleted (path|3)
+# Storage volume state and usable space in bytes
+2749 storage_state (uuid|3),(old_state|1),(new_state|1),(usable|2),(total|2)
 
 
 # ---------------------------
index cffb158..35b452a 100644 (file)
@@ -3296,6 +3296,9 @@ class StorageManagerService extends IStorageManager.Stub
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
         final StorageStatsManager stats = mContext.getSystemService(StorageStatsManager.class);
 
+        // Apps can't defy reserved space
+        flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_RESERVED;
+
         final boolean aggressive = (flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0;
         if (aggressive) {
             mContext.enforceCallingOrSelfPermission(
@@ -3306,24 +3309,31 @@ class StorageManagerService extends IStorageManager.Stub
         try {
             // In general, apps can allocate as much space as they want, except
             // we never let them eat into either the minimum cache space or into
-            // the low disk warning space.
+            // the low disk warning space. To avoid user confusion, this logic
+            // should be kept in sync with getFreeBytes().
             final File path = storage.findPathForUuid(volumeUuid);
+
+            final long usable = path.getUsableSpace();
+            final long lowReserved = storage.getStorageLowBytes(path);
+            final long fullReserved = storage.getStorageFullBytes(path);
+
             if (stats.isQuotaSupported(volumeUuid)) {
+                final long cacheTotal = stats.getCacheBytes(volumeUuid);
+                final long cacheReserved = storage.getStorageCacheBytes(path);
+                final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
+
                 if (aggressive) {
-                    return Math.max(0,
-                            stats.getFreeBytes(volumeUuid) - storage.getStorageFullBytes(path));
+                    return Math.max(0, (usable + cacheTotal) - fullReserved);
                 } else {
-                    return Math.max(0,
-                            stats.getFreeBytes(volumeUuid) - storage.getStorageLowBytes(path)
-                                    - storage.getStorageCacheBytes(path));
+                    return Math.max(0, (usable + cacheClearable) - lowReserved);
                 }
             } else {
                 // When we don't have fast quota information, we ignore cached
                 // data and only consider unused bytes.
                 if (aggressive) {
-                    return Math.max(0, path.getUsableSpace() - storage.getStorageFullBytes(path));
+                    return Math.max(0, usable - fullReserved);
                 } else {
-                    return Math.max(0, path.getUsableSpace() - storage.getStorageLowBytes(path));
+                    return Math.max(0, usable - lowReserved);
                 }
             }
         } catch (IOException e) {
@@ -3337,6 +3347,9 @@ class StorageManagerService extends IStorageManager.Stub
     public void allocateBytes(String volumeUuid, long bytes, int flags) {
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
 
+        // Apps can't defy reserved space
+        flags &= ~StorageManager.FLAG_ALLOCATE_DEFY_RESERVED;
+
         // This method call will enforce FLAG_ALLOCATE_AGGRESSIVE permissions so
         // we don't have to enforce them locally
         final long allocatableBytes = getAllocatableBytes(volumeUuid, flags);
@@ -3350,7 +3363,11 @@ class StorageManagerService extends IStorageManager.Stub
             // Free up enough disk space to satisfy both the requested allocation
             // and our low disk warning space.
             final File path = storage.findPathForUuid(volumeUuid);
-            bytes += storage.getStorageLowBytes(path);
+            if ((flags & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0) {
+                bytes += storage.getStorageFullBytes(path);
+            } else {
+                bytes += storage.getStorageLowBytes(path);
+            }
 
             mPms.freeStorage(volumeUuid, bytes, flags);
         } catch (IOException e) {
index 03e9dd2..16e63b3 100644 (file)
@@ -73,6 +73,7 @@ public class VibratorService extends IVibratorService.Stub
 
     private final LinkedList<VibrationInfo> mPreviousVibrations;
     private final int mPreviousVibrationsLimit;
+    private final boolean mAllowPriorityVibrationsInLowPowerMode;
     private final boolean mSupportsAmplitudeControl;
     private final int mDefaultVibrationAmplitude;
     private final VibrationEffect[] mFallbackEffects;
@@ -213,6 +214,9 @@ public class VibratorService extends IVibratorService.Stub
         mDefaultVibrationAmplitude = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_defaultVibrationAmplitude);
 
+        mAllowPriorityVibrationsInLowPowerMode = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_allowPriorityVibrationsInLowPowerMode);
+
         mPreviousVibrations = new LinkedList<>();
 
         IntentFilter filter = new IntentFilter();
@@ -456,7 +460,7 @@ public class VibratorService extends IVibratorService.Stub
     }
 
     private void startVibrationLocked(final Vibration vib) {
-        if (mLowPowerMode && vib.mUsageHint != AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+        if (!isAllowedToVibrate(vib)) {
             if (DEBUG) {
                 Slog.e(TAG, "Vibrate ignored, low power mode");
             }
@@ -505,6 +509,26 @@ public class VibratorService extends IVibratorService.Stub
         }
     }
 
+    private boolean isAllowedToVibrate(Vibration vib) {
+        if (!mLowPowerMode) {
+            return true;
+        }
+        if (vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_RINGTONE) {
+            return true;
+        }
+        if (!mAllowPriorityVibrationsInLowPowerMode) {
+            return false;
+        }
+        if (vib.mUsageHint == AudioAttributes.USAGE_ALARM ||
+            vib.mUsageHint == AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY ||
+            vib.mUsageHint == AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST) {
+
+            return true;
+        }
+
+        return false;
+    }
+
     private boolean shouldVibrateForRingtone() {
         AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
         int ringerMode = audioManager.getRingerModeInternal();
index feb9ce4..b18fa32 100644 (file)
@@ -76,6 +76,7 @@ public class Watchdog extends Thread {
         "/system/bin/sdcard",
         "/system/bin/surfaceflinger",
         "media.extractor", // system/bin/mediaextractor
+        "media.codec", // vendor/bin/hw/android.hardware.media.omx@1.0-service
         "com.android.bluetooth",  // Bluetooth service
     };
 
index 36c3f7d..f0b1b3b 100644 (file)
@@ -23,8 +23,10 @@ import android.accounts.AccountAndUser;
 import android.accounts.AccountAuthenticatorResponse;
 import android.accounts.AccountManager;
 import android.accounts.AccountManagerInternal;
+import android.accounts.AccountManagerResponse;
 import android.accounts.AuthenticatorDescription;
 import android.accounts.CantAddAccountActivity;
+import android.accounts.ChooseAccountActivity;
 import android.accounts.GrantCredentialsPermissionActivity;
 import android.accounts.IAccountAuthenticator;
 import android.accounts.IAccountAuthenticatorResponse;
@@ -71,6 +73,7 @@ import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
 import android.os.Parcel;
+import android.os.Parcelable;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
@@ -748,6 +751,11 @@ public class AccountManagerService
         }
     }
 
+    private boolean isVisible(int visibility) {
+        return visibility == AccountManager.VISIBILITY_VISIBLE ||
+            visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
+    }
+
     /**
      * Updates visibility for given account name and package.
      *
@@ -800,8 +808,10 @@ public class AccountManagerService
                 if (notify) {
                     for (Entry<String, Integer> packageToVisibility : packagesToVisibility
                             .entrySet()) {
-                        if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
-                                resolveAccountVisibility(account, packageName, accounts))) {
+                        int oldVisibility = packageToVisibility.getValue();
+                        int currentVisibility =
+                            resolveAccountVisibility(account, packageName, accounts);
+                        if (isVisible(oldVisibility) != isVisible(currentVisibility)) {
                             notifyPackage(packageToVisibility.getKey(), accounts);
                         }
                     }
@@ -1178,8 +1188,7 @@ public class AccountManagerService
 
                             for (Entry<String, Integer> packageToVisibility :
                                     packagesToVisibility.entrySet()) {
-                                if (shouldNotifyOnVisibilityChange(packageToVisibility.getValue(),
-                                        AccountManager.VISIBILITY_NOT_VISIBLE)) {
+                                if (isVisible(packageToVisibility.getValue())) {
                                     notifyPackage(packageToVisibility.getKey(), accounts);
                                 }
                             }
@@ -1215,14 +1224,6 @@ public class AccountManagerService
         }
     }
 
-    private boolean shouldNotifyOnVisibilityChange(int oldVisibility, int newVisibility) {
-        boolean oldVisible = (oldVisibility == AccountManager.VISIBILITY_VISIBLE) ||
-            (oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
-        boolean newVisible = (newVisibility == AccountManager.VISIBILITY_VISIBLE) ||
-            (newVisibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
-        return oldVisible == newVisible;
-    }
-
     private SparseBooleanArray getUidsOfInstalledOrUpdatedPackagesAsUser(int userId) {
         // Get the UIDs of all apps that might have data on the device. We want
         // to preserve user data if the app might otherwise be storing data.
@@ -4042,6 +4043,7 @@ public class AccountManagerService
         private volatile int mCurrentAccount = 0;
         private final int mCallingUid;
         private final String mPackageName;
+        private final boolean mIncludeManagedNotVisible;
 
         public GetAccountsByTypeAndFeatureSession(
                 UserAccounts accounts,
@@ -4049,19 +4051,21 @@ public class AccountManagerService
                 String type,
                 String[] features,
                 int callingUid,
-                String packageName) {
+                String packageName,
+                boolean includeManagedNotVisible) {
             super(accounts, response, type, false /* expectActivityLaunch */,
                     true /* stripAuthTokenFromResult */, null /* accountName */,
                     false /* authDetailsRequired */);
             mCallingUid = callingUid;
             mFeatures = features;
             mPackageName = packageName;
+            mIncludeManagedNotVisible = includeManagedNotVisible;
         }
 
         @Override
         public void run() throws RemoteException {
             mAccountsOfType = getAccountsFromCache(mAccounts, mAccountType,
-                    mCallingUid, mPackageName, false /* include managed not visible*/);
+                    mCallingUid, mPackageName, mIncludeManagedNotVisible);
             // check whether each account matches the requested features
             mAccountsWithFeatures = new ArrayList<>(mAccountsOfType.length);
             mCurrentAccount = 0;
@@ -4422,10 +4426,120 @@ public class AccountManagerService
                 && (type != null && !isAccountManagedByCaller(type, callingUid, userId))) {
                 return EMPTY_ACCOUNT_ARRAY;
         }
+        if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID) && type == null) {
+            return getAccountsAsUserForPackage(type, userId,
+                packageName, packageUid, opPackageName, false /* includeUserManagedNotVisible */);
+        }
         return getAccountsAsUserForPackage(type, userId,
                 packageName, packageUid, opPackageName, true /* includeUserManagedNotVisible */);
     }
 
+    private boolean needToStartChooseAccountActivity(Account[] accounts, String callingPackage) {
+        if (accounts.length < 1) return false;
+        if (accounts.length > 1) return true;
+        Account account = accounts[0];
+        UserAccounts userAccounts = getUserAccounts(UserHandle.getCallingUserId());
+        int visibility = resolveAccountVisibility(account, callingPackage, userAccounts);
+        if (visibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) return true;
+        return false;
+    }
+
+    private void startChooseAccountActivityWithAccounts(
+        IAccountManagerResponse response, Account[] accounts) {
+        Intent intent = new Intent(mContext, ChooseAccountActivity.class);
+        intent.putExtra(AccountManager.KEY_ACCOUNTS, accounts);
+        intent.putExtra(AccountManager.KEY_ACCOUNT_MANAGER_RESPONSE,
+                new AccountManagerResponse(response));
+
+        mContext.startActivityAsUser(intent, UserHandle.of(UserHandle.getCallingUserId()));
+    }
+
+    private void handleGetAccountsResult(
+        IAccountManagerResponse response,
+        Account[] accounts,
+        String callingPackage) {
+
+        if (needToStartChooseAccountActivity(accounts, callingPackage)) {
+            startChooseAccountActivityWithAccounts(response, accounts);
+            return;
+        }
+        if (accounts.length == 1) {
+            Bundle bundle = new Bundle();
+            bundle.putString(AccountManager.KEY_ACCOUNT_NAME, accounts[0].name);
+            bundle.putString(AccountManager.KEY_ACCOUNT_TYPE, accounts[0].type);
+            onResult(response, bundle);
+            return;
+        }
+        // No qualified account exists, return an empty Bundle.
+        onResult(response, new Bundle());
+    }
+
+    @Override
+    public void getAccountByTypeAndFeatures(
+        IAccountManagerResponse response,
+        String accountType,
+        String[] features,
+        String opPackageName) {
+
+        int callingUid = Binder.getCallingUid();
+        mAppOpsManager.checkPackage(callingUid, opPackageName);
+        if (Log.isLoggable(TAG, Log.VERBOSE)) {
+            Log.v(TAG, "getAccount: accountType " + accountType
+                    + ", response " + response
+                    + ", features " + Arrays.toString(features)
+                    + ", caller's uid " + callingUid
+                    + ", pid " + Binder.getCallingPid());
+        }
+        if (response == null) throw new IllegalArgumentException("response is null");
+        if (accountType == null) throw new IllegalArgumentException("accountType is null");
+
+        int userId = UserHandle.getCallingUserId();
+
+        long identityToken = clearCallingIdentity();
+        try {
+            UserAccounts userAccounts = getUserAccounts(userId);
+            if (ArrayUtils.isEmpty(features)) {
+                Account[] accountsWithManagedNotVisible = getAccountsFromCache(
+                    userAccounts, accountType, callingUid, opPackageName,
+                    true /* include managed not visible */);
+                handleGetAccountsResult(
+                    response, accountsWithManagedNotVisible, opPackageName);
+                return;
+            }
+
+            IAccountManagerResponse retrieveAccountsResponse =
+                new IAccountManagerResponse.Stub() {
+                @Override
+                public void onResult(Bundle value) throws RemoteException {
+                    Parcelable[] parcelables = value.getParcelableArray(
+                        AccountManager.KEY_ACCOUNTS);
+                    Account[] accounts = new Account[parcelables.length];
+                    for (int i = 0; i < parcelables.length; i++) {
+                        accounts[i] = (Account) parcelables[i];
+                    }
+                    handleGetAccountsResult(
+                        response, accounts, opPackageName);
+                }
+
+                @Override
+                public void onError(int errorCode, String errorMessage)
+                        throws RemoteException {
+                    // Will not be called in this case.
+                }
+            };
+            new GetAccountsByTypeAndFeatureSession(
+                    userAccounts,
+                    retrieveAccountsResponse,
+                    accountType,
+                    features,
+                    callingUid,
+                    opPackageName,
+                    true /* include managed not visible */).bind();
+        } finally {
+            restoreCallingIdentity(identityToken);
+        }
+    }
+
     @Override
     public void getAccountsByFeatures(
             IAccountManagerResponse response,
@@ -4458,6 +4572,7 @@ public class AccountManagerService
             }
             return;
         }
+
         long identityToken = clearCallingIdentity();
         try {
             UserAccounts userAccounts = getUserAccounts(userId);
@@ -4475,7 +4590,8 @@ public class AccountManagerService
                     type,
                     features,
                     callingUid,
-                    opPackageName).bind();
+                    opPackageName,
+                    false /* include managed not visible */).bind();
         } finally {
             restoreCallingIdentity(identityToken);
         }
index 2680b42..c417484 100644 (file)
@@ -162,7 +162,7 @@ public final class ActiveServices {
 
     /**
      * Information about an app that is currently running one or more foreground services.
-     * (This mapps directly to the running apps we show in the notification.)
+     * (This maps directly to the running apps we show in the notification.)
      */
     static final class ActiveForegroundApp {
         String mPackageName;
@@ -813,6 +813,8 @@ public final class ActiveServices {
             String title;
             String msg;
             String[] pkgs;
+            final long nowElapsed = SystemClock.elapsedRealtime();
+            long oldestStartTime = nowElapsed;
             if (active.size() == 1) {
                 intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
                 intent.setData(Uri.fromParts("package", active.get(0).mPackageName, null));
@@ -820,11 +822,13 @@ public final class ActiveServices {
                         R.string.foreground_service_app_in_background, active.get(0).mLabel);
                 msg = context.getString(R.string.foreground_service_tap_for_details);
                 pkgs = new String[] { active.get(0).mPackageName };
+                oldestStartTime = active.get(0).mStartTime;
             } else {
                 intent = new Intent(Settings.ACTION_FOREGROUND_SERVICES_SETTINGS);
                 pkgs = new String[active.size()];
                 for (int i = 0; i < active.size(); i++) {
                     pkgs[i] = active.get(i).mPackageName;
+                    oldestStartTime = Math.min(oldestStartTime, active.get(i).mStartTime);
                 }
                 intent.putExtra("packages", pkgs);
                 title = context.getString(
@@ -841,9 +845,10 @@ public final class ActiveServices {
                     new Notification.Builder(context,
                             SystemNotificationChannels.FOREGROUND_SERVICE)
                             .addExtras(notificationBundle)
-                            .setSmallIcon(R.drawable.ic_check_circle_24px)
+                            .setSmallIcon(R.drawable.stat_sys_vitals)
                             .setOngoing(true)
-                            .setShowWhen(false)
+                            .setShowWhen(oldestStartTime < nowElapsed)
+                            .setWhen(System.currentTimeMillis() - (nowElapsed - oldestStartTime))
                             .setColor(context.getColor(
                                     com.android.internal.R.color.system_notification_accent_color))
                             .setContentTitle(title)
index fbab26a..c958313 100644 (file)
@@ -8447,8 +8447,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                         synchronized (mPidsSelfLocked) {
                             proc = mPidsSelfLocked.get(callingPid);
                         }
-                        if (proc != null && proc.curProcState
-                                < ActivityManager.PROCESS_STATE_RECEIVER) {
+                        if (proc != null &&
+                                !ActivityManager.isProcStateBackground(proc.curProcState)) {
                             // Whoever is instigating this is in the foreground, so we will allow it
                             // to go through.
                             return ActivityManager.APP_START_MODE_NORMAL;
@@ -13545,7 +13545,9 @@ public class ActivityManagerService extends IActivityManager.Stub
                         return;
                     }
                     if (pr.hasTopUi != hasTopUi) {
-                        Slog.i(TAG, "Setting hasTopUi=" + hasTopUi + " for pid=" + pid);
+                        if (DEBUG_OOM_ADJ) {
+                            Slog.d(TAG, "Setting hasTopUi=" + hasTopUi + " for pid=" + pid);
+                        }
                         pr.hasTopUi = hasTopUi;
                         changed = true;
                     }
@@ -13922,9 +13924,9 @@ public class ActivityManagerService extends IActivityManager.Stub
         final boolean supportsPictureInPicture =
                 mContext.getPackageManager().hasSystemFeature(FEATURE_PICTURE_IN_PICTURE);
 
-        final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow();
+        final boolean supportsMultiWindow = ActivityManager.supportsMultiWindow(mContext);
         final boolean supportsSplitScreenMultiWindow =
-                ActivityManager.supportsSplitScreenMultiWindow();
+                ActivityManager.supportsSplitScreenMultiWindow(mContext);
         final boolean supportsMultiDisplay = mContext.getPackageManager()
                 .hasSystemFeature(FEATURE_ACTIVITIES_ON_SECONDARY_DISPLAYS);
         final String debugApp = Settings.Global.getString(resolver, DEBUG_APP);
@@ -19156,10 +19158,11 @@ public class ActivityManagerService extends IActivityManager.Stub
                     final Uri data = intent.getData();
                     final String ssp;
                     if (data != null && (ssp = data.getSchemeSpecificPart()) != null) {
-                        final ApplicationInfo aInfo =
-                                getPackageManagerInternalLocked().getApplicationInfo(
-                                        ssp,
-                                        userId);
+                        ApplicationInfo aInfo = null;
+                        try {
+                            aInfo = AppGlobals.getPackageManager()
+                                    .getApplicationInfo(ssp, 0 /*flags*/, userId);
+                        } catch (RemoteException ignore) {}
                         if (aInfo == null) {
                             Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
                                     + " ssp=" + ssp + " data=" + data);
@@ -20178,6 +20181,11 @@ public class ActivityManagerService extends IActivityManager.Stub
         mTempConfig.setTo(getGlobalConfiguration());
         final int changes = mTempConfig.updateFrom(values);
         if (changes == 0) {
+            // Since calling to Activity.setRequestedOrientation leads to freezing the window with
+            // setting WindowManagerService.mWaitingForConfig to true, it is important that we call
+            // performDisplayOverrideConfigUpdate in order to send the new display configuration
+            // (even if there are no actual changes) to unfreeze the window.
+            performDisplayOverrideConfigUpdate(values, deferResume, DEFAULT_DISPLAY);
             return 0;
         }
 
@@ -20366,20 +20374,19 @@ public class ActivityManagerService extends IActivityManager.Stub
             int displayId) {
         mTempConfig.setTo(mStackSupervisor.getDisplayOverrideConfiguration(displayId));
         final int changes = mTempConfig.updateFrom(values);
-        if (changes == 0) {
-            return 0;
-        }
-
-        Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " " + mTempConfig
-                + " for displayId=" + displayId);
-        mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
+        if (changes != 0) {
+            Slog.i(TAG, "Override config changes=" + Integer.toHexString(changes) + " "
+                    + mTempConfig + " for displayId=" + displayId);
+            mStackSupervisor.setDisplayOverrideConfiguration(mTempConfig, displayId);
 
-        final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
-        if (isDensityChange && displayId == DEFAULT_DISPLAY) {
-            // Reset the unsupported display size dialog.
-            mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
+            final boolean isDensityChange = (changes & ActivityInfo.CONFIG_DENSITY) != 0;
+            if (isDensityChange && displayId == DEFAULT_DISPLAY) {
+                // Reset the unsupported display size dialog.
+                mUiHandler.sendEmptyMessage(SHOW_UNSUPPORTED_DISPLAY_SIZE_DIALOG_MSG);
 
-            killAllBackgroundProcessesExcept(N, ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+                killAllBackgroundProcessesExcept(N,
+                        ActivityManager.PROCESS_STATE_FOREGROUND_SERVICE);
+            }
         }
 
         // Update the configuration with WM first and check if any of the stacks need to be resized
@@ -24275,7 +24282,6 @@ public class ActivityManagerService extends IActivityManager.Stub
     }
 
     void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
-        final PackageManagerInternal packageManager = getPackageManagerInternalLocked();
         final boolean updateFrameworkRes = packagesToUpdate.contains("android");
         for (int i = mLruProcesses.size() - 1; i >= 0; i--) {
             final ProcessRecord app = mLruProcesses.get(i);
@@ -24292,8 +24298,8 @@ public class ActivityManagerService extends IActivityManager.Stub
                 final String packageName = app.pkgList.keyAt(j);
                 if (updateFrameworkRes || packagesToUpdate.contains(packageName)) {
                     try {
-                        final ApplicationInfo ai = packageManager.getApplicationInfo(
-                                packageName, app.userId);
+                        final ApplicationInfo ai = AppGlobals.getPackageManager()
+                                .getApplicationInfo(packageName, 0 /*flags*/, app.userId);
                         if (ai != null) {
                             app.thread.scheduleApplicationInfoChanged(ai);
                         }
index 6eae9e6..d768304 100644 (file)
@@ -2382,7 +2382,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
         if (res == null) {
             return -1;
         }
-        pw.println(ActivityManager.supportsMultiWindow());
+        pw.println(ActivityManager.supportsMultiWindow(mInternal.mContext));
         return 0;
     }
 
@@ -2391,7 +2391,7 @@ final class ActivityManagerShellCommand extends ShellCommand {
         if (res == null) {
             return -1;
         }
-        pw.println(ActivityManager.supportsSplitScreenMultiWindow());
+        pw.println(ActivityManager.supportsSplitScreenMultiWindow(mInternal.mContext));
         return 0;
     }
 
index 5636e19..ec6a4f6 100644 (file)
@@ -130,6 +130,7 @@ import android.content.pm.ApplicationInfo;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Build;
 import android.os.Bundle;
@@ -1419,19 +1420,17 @@ final class ActivityRecord extends ConfigurationContainer implements AppWindowCo
                     break;
                 case ANIM_THUMBNAIL_SCALE_UP:
                 case ANIM_THUMBNAIL_SCALE_DOWN:
-                    boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
-                    service.mWindowManager.overridePendingAppTransitionThumb(
-                            pendingOptions.getThumbnail(),
+                    final boolean scaleUp = (animationType == ANIM_THUMBNAIL_SCALE_UP);
+                    final GraphicBuffer buffer = pendingOptions.getThumbnail();
+                    service.mWindowManager.overridePendingAppTransitionThumb(buffer,
                             pendingOptions.getStartX(), pendingOptions.getStartY(),
                             pendingOptions.getOnAnimationStartListener(),
                             scaleUp);
-                    if (intent.getSourceBounds() == null) {
+                    if (intent.getSourceBounds() == null && buffer != null) {
                         intent.setSourceBounds(new Rect(pendingOptions.getStartX(),
                                 pendingOptions.getStartY(),
-                                pendingOptions.getStartX()
-                                        + pendingOptions.getThumbnail().getWidth(),
-                                pendingOptions.getStartY()
-                                        + pendingOptions.getThumbnail().getHeight()));
+                                pendingOptions.getStartX() + buffer.getWidth(),
+                                pendingOptions.getStartY() + buffer.getHeight()));
                     }
                     break;
                 case ANIM_THUMBNAIL_ASPECT_SCALE_UP:
index 93e1ab4..9db957c 100644 (file)
@@ -244,7 +244,7 @@ class ActivityStack<T extends StackWindowController> extends ConfigurationContai
     static final int REMOVE_TASK_MODE_MOVING = 1;
     // Similar to {@link #REMOVE_TASK_MODE_MOVING} and the task will be added to the top of its new
     // stack and the new stack will be on top of all stacks.
-    private static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
+    static final int REMOVE_TASK_MODE_MOVING_TO_TOP = 2;
 
     // The height/width divide used when fitting a task within a bounds with method
     // {@link #fitWithinBounds}.
index e180aef..b55bae9 100644 (file)
@@ -470,7 +470,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
     }
 
     Configuration getDisplayOverrideConfiguration(int displayId) {
-        final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             throw new IllegalArgumentException("No display found with id: " + displayId);
         }
@@ -479,7 +479,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
     }
 
     void setDisplayOverrideConfiguration(Configuration overrideConfiguration, int displayId) {
-        final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             throw new IllegalArgumentException("No display found with id: " + displayId);
         }
@@ -507,7 +507,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
         if (displayId == INVALID_DISPLAY) {
             return false;
         }
-        final ActivityDisplay targetDisplay = mActivityDisplays.get(displayId);
+        final ActivityDisplay targetDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (targetDisplay == null) {
             throw new IllegalArgumentException("No display found with id: " + displayId);
         }
@@ -1672,7 +1672,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
         if (DEBUG_TASKS) Slog.d(TAG, "Launch on display check: displayId=" + launchDisplayId
                 + " callingPid=" + callingPid + " callingUid=" + callingUid);
 
-        final ActivityDisplay activityDisplay = mActivityDisplays.get(launchDisplayId);
+        final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(launchDisplayId);
         if (activityDisplay == null) {
             Slog.w(TAG, "Launch on display check: display not found");
             return false;
@@ -2191,7 +2191,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
      * @return Existing stack if there is a valid one, new dynamic stack if it is valid or null.
      */
     ActivityStack getValidLaunchStackOnDisplay(int displayId, @NonNull ActivityRecord r) {
-        final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             throw new IllegalArgumentException(
                     "Display with displayId=" + displayId + " not found.");
@@ -2242,10 +2242,9 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
 
         for (int i = mTmpOrderedDisplayIds.size() - 1; i >= 0; --i) {
             final int displayId = mTmpOrderedDisplayIds.get(i);
-            final List<ActivityStack> stacks = mActivityDisplays.get(displayId).mStacks;
-            if (stacks == null) {
-                continue;
-            }
+            // If a display is registered in WM, it must also be available in AM.
+            @SuppressWarnings("ConstantConditions")
+            final List<ActivityStack> stacks = getActivityDisplayOrCreateLocked(displayId).mStacks;
             for (int j = stacks.size() - 1; j >= 0; --j) {
                 final ActivityStack stack = stacks.get(j);
                 if (stack != currentFocus && stack.isFocusable()
@@ -2576,7 +2575,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
     }
 
     ActivityStack createStackOnDisplay(int stackId, int displayId, boolean onTop) {
-        final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             return null;
         }
@@ -2808,7 +2807,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
      * @param onTop Indicates whether container should be place on top or on bottom.
      */
     void moveStackToDisplayLocked(int stackId, int displayId, boolean onTop) {
-        final ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
         if (activityDisplay == null) {
             throw new IllegalArgumentException("moveStackToDisplayLocked: Unknown displayId="
                     + displayId);
@@ -2989,8 +2988,8 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
         // Calculate the default bounds (don't use existing stack bounds as we may have just created
         // the stack, and schedule the start of the animation into PiP (the bounds animator that
         // is triggered by this is posted on another thread)
-        final Rect destBounds = stack.getPictureInPictureBounds(aspectRatio,
-                false /* useExistingStackBounds */);
+        final Rect destBounds = stack.getDefaultPictureInPictureBounds(aspectRatio);
+
         stack.animateResizePinnedStack(sourceHintBounds, destBounds, -1 /* animationDuration */,
                 true /* fromFullscreen */);
 
@@ -3915,25 +3914,44 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
     }
 
     private void handleDisplayAdded(int displayId) {
-        boolean newDisplay;
         synchronized (mService) {
-            newDisplay = mActivityDisplays.get(displayId) == null;
-            if (newDisplay) {
-                ActivityDisplay activityDisplay = new ActivityDisplay(displayId);
-                if (activityDisplay.mDisplay == null) {
-                    Slog.w(TAG, "Display " + displayId + " gone before initialization complete");
-                    return;
-                }
-                mActivityDisplays.put(displayId, activityDisplay);
-                calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
-                mWindowManager.onDisplayAdded(displayId);
-            }
+            getActivityDisplayOrCreateLocked(displayId);
         }
     }
 
     /** Check if display with specified id is added to the list. */
     boolean isDisplayAdded(int displayId) {
-        return mActivityDisplays.get(displayId) != null;
+        return getActivityDisplayOrCreateLocked(displayId) != null;
+    }
+
+    /**
+     * Get an existing instance of {@link ActivityDisplay} or create new if there is a
+     * corresponding record in display manager.
+     */
+    private ActivityDisplay getActivityDisplayOrCreateLocked(int displayId) {
+        ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+        if (activityDisplay != null) {
+            return activityDisplay;
+        }
+        if (mDisplayManager == null) {
+            // The system isn't fully initialized yet.
+            return null;
+        }
+        final Display display = mDisplayManager.getDisplay(displayId);
+        if (display == null) {
+            // The display is not registered in DisplayManager.
+            return null;
+        }
+        // The display hasn't been added to ActivityManager yet, create a new record now.
+        activityDisplay = new ActivityDisplay(displayId);
+        if (activityDisplay.mDisplay == null) {
+            Slog.w(TAG, "Display " + displayId + " gone before initialization complete");
+            return null;
+        }
+        mActivityDisplays.put(displayId, activityDisplay);
+        calculateDefaultMinimalSizeOfResizeableTasks(activityDisplay);
+        mWindowManager.onDisplayAdded(displayId);
+        return activityDisplay;
     }
 
     private void calculateDefaultMinimalSizeOfResizeableTasks(ActivityDisplay display) {
@@ -3991,6 +4009,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
         info.stackId = stack.mStackId;
         info.userId = stack.mCurrentUser;
         info.visible = stack.shouldBeVisible(null) == STACK_VISIBLE;
+        // A stack might be not attached to a display.
         info.position = display != null
                 ? display.mStacks.indexOf(stack)
                 : 0;
@@ -4618,7 +4637,7 @@ public class ActivityStackSupervisor extends ConfigurationContainer implements D
         @Override
         public void addToDisplay(int displayId) {
             synchronized (mService) {
-                ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
+                final ActivityDisplay activityDisplay = getActivityDisplayOrCreateLocked(displayId);
                 if (activityDisplay == null) {
                     return;
                 }
index 7ed07e0..07caf9e 100644 (file)
@@ -1432,7 +1432,13 @@ class ActivityStarter {
                     + "; forcing " + "Intent.FLAG_ACTIVITY_NEW_TASK for: " + mIntent);
             mLaunchFlags |= FLAG_ACTIVITY_NEW_TASK;
             mNewTaskInfo = mSourceRecord.info;
-            mNewTaskIntent = mSourceRecord.getTask().intent;
+
+            // It is not guaranteed that the source record will have a task associated with it. For,
+            // example, if this method is being called for processing a pending activity launch, it
+            // is possible that the activity has been removed from the task after the launch was
+            // enqueued.
+            final TaskRecord sourceTask = mSourceRecord.getTask();
+            mNewTaskIntent = sourceTask != null ? sourceTask.intent : null;
         }
         mSourceRecord = null;
         mSourceStack = null;
index 2439062..c20221b 100644 (file)
@@ -17,6 +17,8 @@
 package com.android.server.am;
 
 import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_CPU;
+import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_RADIO;
+import static com.android.internal.os.BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI;
 
 import android.annotation.Nullable;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -87,6 +89,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
         implements PowerManagerInternal.LowPowerModeListener,
         BatteryStatsImpl.PlatformIdleStateCallback {
     static final String TAG = "BatteryStatsService";
+    static final boolean DBG = false;
 
     /**
      * How long to wait on an individual subsystem to return its stats.
@@ -152,11 +155,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
 
                 case MSG_WRITE_TO_DISK:
                     updateExternalStatsSync("write", UPDATE_ALL);
-                    Slog.d(TAG, "begin writeAsyncLocked");
+                    if (DBG) Slog.d(TAG, "begin writeAsyncLocked");
                     synchronized (mStats) {
                         mStats.writeAsyncLocked();
                     }
-                    Slog.d(TAG, "end writeAsyncLocked");
+                    if (DBG) Slog.d(TAG, "end writeAsyncLocked");
                     break;
             }
         }
@@ -196,7 +199,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
 
     @Override
     public String getPlatformLowPowerStats() {
-        Slog.d(TAG, "begin getPlatformLowPowerStats");
+        if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats");
         try {
             mUtf8BufferStat.clear();
             mUtf16BufferStat.clear();
@@ -212,7 +215,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
             mUtf16BufferStat.flip();
             return mUtf16BufferStat.toString();
         } finally {
-            Slog.d(TAG, "end getPlatformLowPowerStats");
+            if (DBG) Slog.d(TAG, "end getPlatformLowPowerStats");
         }
     }
 
@@ -230,10 +233,12 @@ public final class BatteryStatsService extends IBatteryStats.Stub
 
     public void publish(Context context) {
         mContext = context;
-        mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
-                com.android.internal.R.integer.config_radioScanningTimeout)
-                * 1000L);
-        mStats.setPowerProfile(new PowerProfile(context));
+        synchronized (mStats) {
+            mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger(
+                    com.android.internal.R.integer.config_radioScanningTimeout)
+                    * 1000L);
+            mStats.setPowerProfileLocked(new PowerProfile(context));
+        }
         ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
     }
 
@@ -244,9 +249,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
     public void initPowerManagement() {
         final PowerManagerInternal powerMgr = LocalServices.getService(PowerManagerInternal.class);
         powerMgr.registerLowPowerModeObserver(this);
-        mStats.notePowerSaveMode(
-                powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
-                        .batterySaverEnabled);
+        synchronized (mStats) {
+            mStats.notePowerSaveModeLocked(
+                    powerMgr.getLowPowerState(ServiceType.BATTERY_STATS)
+                            .batterySaverEnabled);
+        }
         (new WakeupReasonThread()).start();
     }
 
@@ -279,7 +286,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
     @Override
     public void onLowPowerModeChanged(PowerSaveState result) {
         synchronized (mStats) {
-            mStats.notePowerSaveMode(result.batterySaverEnabled);
+            mStats.notePowerSaveModeLocked(result.batterySaverEnabled);
         }
     }
 
@@ -561,11 +568,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
         
     public void noteScreenState(int state) {
         enforceCallingPermission();
-        Slog.d(TAG, "begin noteScreenState");
+        if (DBG) Slog.d(TAG, "begin noteScreenState");
         synchronized (mStats) {
             mStats.noteScreenStateLocked(state);
         }
-        Slog.d(TAG, "end noteScreenState");
+        if (DBG) Slog.d(TAG, "end noteScreenState");
     }
     
     public void noteScreenBrightness(int brightness) {
@@ -605,8 +612,13 @@ public final class BatteryStatsService extends IBatteryStats.Stub
 
     public void noteMobileRadioPowerState(int powerState, long timestampNs, int uid) {
         enforceCallingPermission();
+        boolean update;
         synchronized (mStats) {
-            mStats.noteMobileRadioPowerState(powerState, timestampNs, uid);
+            update = mStats.noteMobileRadioPowerStateLocked(powerState, timestampNs, uid);
+        }
+
+        if (update) {
+            mHandler.scheduleSync("modem-data", UPDATE_RADIO);
         }
     }
 
@@ -718,11 +730,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
 
     public void noteStartCamera(int uid) {
         enforceCallingPermission();
-        Slog.d(TAG, "begin noteStartCamera");
+        if (DBG) Slog.d(TAG, "begin noteStartCamera");
         synchronized (mStats) {
             mStats.noteCameraOnLocked(uid);
         }
-        Slog.d(TAG, "end noteStartCamera");
+        if (DBG) Slog.d(TAG, "end noteStartCamera");
     }
 
     public void noteStopCamera(int uid) {
@@ -758,7 +770,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                         powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM) ? "active"
                         : "inactive";
                 mHandler.scheduleSync("wifi-data: " + type,
-                        BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI);
+                        UPDATE_WIFI);
             }
             mStats.noteWifiRadioPowerState(powerState, tsNanos, uid);
         }
@@ -916,9 +928,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
     @Override
     public void noteNetworkStatsEnabled() {
         enforceCallingPermission();
-        synchronized (mStats) {
-            mStats.noteNetworkStatsEnabledLocked();
-        }
+        mHandler.scheduleSync("network-stats-enabled", UPDATE_RADIO | UPDATE_WIFI);
     }
 
     @Override
@@ -944,10 +954,10 @@ public final class BatteryStatsService extends IBatteryStats.Stub
     }
 
     @Override
-    public void noteBleScanStarted(WorkSource ws) {
+    public void noteBleScanStarted(WorkSource ws, boolean isUnoptimized) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteBluetoothScanStartedFromSourceLocked(ws);
+            mStats.noteBluetoothScanStartedFromSourceLocked(ws, isUnoptimized);
         }
     }
 
@@ -984,9 +994,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
             return;
         }
 
-        synchronized (mStats) {
-            mStats.updateWifiStateLocked(info);
-        }
+        mStats.updateWifiState(info);
     }
 
     @Override
@@ -1011,9 +1019,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
             return;
         }
 
-        synchronized (mStats) {
-            mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(), info);
-        }
+        mStats.updateMobileRadioState(info);
     }
 
     public boolean isOnBattery() {
@@ -1342,23 +1348,23 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                     }
                 }
             }
-            Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid());
+            if (DBG) Slog.d(TAG, "begin dumpCheckinLocked from UID " + Binder.getCallingUid());
             synchronized (mStats) {
                 mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
                 if (writeData) {
                     mStats.writeAsyncLocked();
                 }
             }
-            Slog.d(TAG, "end dumpCheckinLocked");
+            if (DBG) Slog.d(TAG, "end dumpCheckinLocked");
         } else {
-            Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid());
+            if (DBG) Slog.d(TAG, "begin dumpLocked from UID " + Binder.getCallingUid());
             synchronized (mStats) {
                 mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
                 if (writeData) {
                     mStats.writeAsyncLocked();
                 }
             }
-            Slog.d(TAG, "end dumpLocked");
+            if (DBG) Slog.d(TAG, "end dumpLocked");
         }
     }
 
@@ -1480,15 +1486,15 @@ public final class BatteryStatsService extends IBatteryStats.Stub
         SynchronousResultReceiver bluetoothReceiver = null;
         SynchronousResultReceiver modemReceiver = null;
 
-        Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason);
+        if (DBG) Slog.d(TAG, "begin updateExternalStatsSync reason=" + reason);
         synchronized (mExternalStatsLock) {
             if (mContext == null) {
                 // Don't do any work yet.
-                Slog.d(TAG, "end updateExternalStatsSync");
+                if (DBG) Slog.d(TAG, "end updateExternalStatsSync");
                 return;
             }
 
-            if ((updateFlags & BatteryStatsImpl.ExternalStatsSync.UPDATE_WIFI) != 0) {
+            if ((updateFlags & UPDATE_WIFI) != 0) {
                 if (mWifiManager == null) {
                     mWifiManager = IWifiManager.Stub.asInterface(
                             ServiceManager.getService(Context.WIFI_SERVICE));
@@ -1557,14 +1563,6 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                 mStats.updateKernelWakelocksLocked();
                 mStats.updateKernelMemoryBandwidthLocked();
 
-                if (wifiInfo != null) {
-                    if (wifiInfo.isValid()) {
-                        mStats.updateWifiStateLocked(extractDelta(wifiInfo));
-                    } else {
-                        Slog.e(TAG, "wifi info is invalid: " + wifiInfo);
-                    }
-                }
-
                 if (bluetoothInfo != null) {
                     if (bluetoothInfo.isValid()) {
                         mStats.updateBluetoothStateLocked(bluetoothInfo);
@@ -1572,18 +1570,25 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                         Slog.e(TAG, "bluetooth info is invalid: " + bluetoothInfo);
                     }
                 }
+            }
 
-                if (modemInfo != null) {
-                    if (modemInfo.isValid()) {
-                        mStats.updateMobileRadioStateLocked(SystemClock.elapsedRealtime(),
-                                modemInfo);
-                    } else {
-                        Slog.e(TAG, "modem info is invalid: " + modemInfo);
-                    }
+            if (wifiInfo != null) {
+                if (wifiInfo.isValid()) {
+                    mStats.updateWifiState(extractDelta(wifiInfo));
+                } else {
+                    Slog.e(TAG, "wifi info is invalid: " + wifiInfo);
+                }
+            }
+
+            if (modemInfo != null) {
+                if (modemInfo.isValid()) {
+                    mStats.updateMobileRadioState(modemInfo);
+                } else {
+                    Slog.e(TAG, "modem info is invalid: " + modemInfo);
                 }
             }
         }
-        Slog.d(TAG, "end updateExternalStatsSync");
+        if (DBG) Slog.d(TAG, "end updateExternalStatsSync");
     }
 
     /**
@@ -1603,7 +1608,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                 return getHealthStatsForUidLocked(requestUid);
             }
         } catch (Exception ex) {
-            Slog.d(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex);
+            Slog.w(TAG, "Crashed while writing for takeUidSnapshot(" + requestUid + ")", ex);
             throw ex;
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -1633,7 +1638,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
                 return results;
             }
         } catch (Exception ex) {
-            Slog.d(TAG, "Crashed while writing for takeUidSnapshots("
+            if (DBG) Slog.d(TAG, "Crashed while writing for takeUidSnapshots("
                     + Arrays.toString(requestUids) + ") i=" + i, ex);
             throw ex;
         } finally {
index 144eb11..2e0ec0b 100644 (file)
@@ -97,7 +97,7 @@ class KeyguardController {
         mKeyguardShowing = showing;
         dismissDockedStackIfNeeded();
         if (showing) {
-            mKeyguardGoingAway = false;
+            setKeyguardGoingAway(false);
             mDismissalRequested = false;
         }
         mStackSupervisor.ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
@@ -114,7 +114,7 @@ class KeyguardController {
         if (mKeyguardShowing) {
             mWindowManager.deferSurfaceLayout();
             try {
-                mKeyguardGoingAway = true;
+                setKeyguardGoingAway(true);
                 mWindowManager.prepareAppTransition(TRANSIT_KEYGUARD_GOING_AWAY,
                         false /* alwaysKeepCurrent */, convertTransitFlags(flags),
                         false /* forceOverride */);
@@ -139,6 +139,11 @@ class KeyguardController {
         mWindowManager.dismissKeyguard(callback);
     }
 
+    private void setKeyguardGoingAway(boolean keyguardGoingAway) {
+        mKeyguardGoingAway = keyguardGoingAway;
+        mWindowManager.setKeyguardGoingAway(keyguardGoingAway);
+    }
+
     private void failCallback(IKeyguardDismissCallback callback) {
         try {
             callback.onDismissError();
index 702bf92..2010c24 100644 (file)
@@ -44,9 +44,9 @@ class PinnedActivityStack extends ActivityStack<PinnedStackWindowController>
         return new PinnedStackWindowController(mStackId, this, displayId, onTop, outBounds);
     }
 
-    Rect getPictureInPictureBounds(float aspectRatio, boolean useExistingStackBounds) {
+    Rect getDefaultPictureInPictureBounds(float aspectRatio) {
         return getWindowContainerController().getPictureInPictureBounds(aspectRatio,
-                useExistingStackBounds);
+                null /* currentStackBounds */);
     }
 
     void animateResizePinnedStack(Rect sourceHintBounds, Rect toBounds, int animationDuration,
index deb3b28..39aed7c 100644 (file)
@@ -233,7 +233,8 @@ public final class ProcessStatsService extends IProcessStats.Stub {
                 updateFile();
             }
             mLastWriteTime = SystemClock.uptimeMillis();
-            Slog.i(TAG, "Prepared write state in " + (SystemClock.uptimeMillis()-now) + "ms");
+            if (DEBUG) Slog.d(TAG, "Prepared write state in "
+                    + (SystemClock.uptimeMillis()-now) + "ms");
             if (!sync) {
                 BackgroundThread.getHandler().post(new Runnable() {
                     @Override public void run() {
index a6997f9..32d03da 100644 (file)
@@ -382,18 +382,29 @@ public final class ProviderMap {
     }
 
     /**
-     * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider if
-     * there is a thread associated with the provider.
+     * Before invoking IApplicationThread.dumpProvider(), print meta information to the print
+     * writer and handle passed flags.
      */
     private void dumpProvider(String prefix, FileDescriptor fd, PrintWriter pw,
             final ContentProviderRecord r, String[] args, boolean dumpAll) {
+        for (String s: args) {
+            if (!dumpAll && s.contains("--proto")) {
+                if (r.proc != null && r.proc.thread != null) {
+                    dumpToTransferPipe(null , fd, pw, r, args);
+                }
+                return;
+            }
+        }
         String innerPrefix = prefix + "  ";
         synchronized (mAm) {
             pw.print(prefix); pw.print("PROVIDER ");
-                    pw.print(r);
-                    pw.print(" pid=");
-                    if (r.proc != null) pw.println(r.proc.pid);
-                    else pw.println("(not running)");
+            pw.print(r);
+            pw.print(" pid=");
+            if (r.proc != null) {
+                pw.println(r.proc.pid);
+            } else {
+                pw.println("(not running)");
+            }
             if (dumpAll) {
                 r.dump(pw, innerPrefix, true);
             }
@@ -401,23 +412,32 @@ public final class ProviderMap {
         if (r.proc != null && r.proc.thread != null) {
             pw.println("    Client:");
             pw.flush();
+            dumpToTransferPipe("      ", fd, pw, r, args);
+        }
+    }
+
+    /**
+     * Invokes IApplicationThread.dumpProvider() on the thread of the specified provider without
+     * any meta string (e.g., provider info, indentation) written to the file descriptor.
+     */
+    private void dumpToTransferPipe(String prefix, FileDescriptor fd, PrintWriter pw,
+            final ContentProviderRecord r, String[] args) {
+        try {
+            TransferPipe tp = new TransferPipe();
             try {
-                TransferPipe tp = new TransferPipe();
-                try {
-                    r.proc.thread.dumpProvider(
-                            tp.getWriteFd(), r.provider.asBinder(), args);
-                    tp.setBufferPrefix("      ");
-                    // Short timeout, since blocking here can
-                    // deadlock with the application.
-                    tp.go(fd, 2000);
-                } finally {
-                    tp.kill();
-                }
-            } catch (IOException ex) {
-                pw.println("      Failure while dumping the provider: " + ex);
-            } catch (RemoteException ex) {
-                pw.println("      Got a RemoteException while dumping the service");
+                r.proc.thread.dumpProvider(
+                    tp.getWriteFd(), r.provider.asBinder(), args);
+                tp.setBufferPrefix(prefix);
+                // Short timeout, since blocking here can
+                // deadlock with the application.
+                tp.go(fd, 2000);
+            } finally {
+                tp.kill();
             }
+        } catch (IOException ex) {
+            pw.println("      Failure while dumping the provider: " + ex);
+        } catch (RemoteException ex) {
+            pw.println("      Got a RemoteException while dumping the service");
         }
     }
 }
index ea9ff59..8297169 100644 (file)
@@ -16,7 +16,6 @@
 
 package com.android.server.am;
 
-import android.app.ActivityManager;
 import android.app.ActivityManager.TaskSnapshot;
 import android.app.ITaskStackListener;
 import android.app.ActivityManager.TaskDescription;
@@ -31,27 +30,27 @@ import android.os.RemoteException;
 import java.util.ArrayList;
 
 class TaskChangeNotificationController {
-    static final int LOG_STACK_STATE_MSG = 1;
-    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
-    static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
-    static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
-    static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
-    static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
-    static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
-    static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
-    static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
-    static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
-    static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
-    static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
-    static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
-    static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
-    static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
-    static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
-    static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
-    static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
+    private static final int LOG_STACK_STATE_MSG = 1;
+    private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_MSG = 2;
+    private static final int NOTIFY_ACTIVITY_PINNED_LISTENERS_MSG = 3;
+    private static final int NOTIFY_PINNED_ACTIVITY_RESTART_ATTEMPT_LISTENERS_MSG = 4;
+    private static final int NOTIFY_PINNED_STACK_ANIMATION_ENDED_LISTENERS_MSG = 5;
+    private static final int NOTIFY_FORCED_RESIZABLE_MSG = 6;
+    private static final int NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG = 7;
+    private static final int NOTIFY_TASK_ADDED_LISTENERS_MSG = 8;
+    private static final int NOTIFY_TASK_REMOVED_LISTENERS_MSG = 9;
+    private static final int NOTIFY_TASK_MOVED_TO_FRONT_LISTENERS_MSG = 10;
+    private static final int NOTIFY_TASK_DESCRIPTION_CHANGED_LISTENERS_MSG = 11;
+    private static final int NOTIFY_ACTIVITY_REQUESTED_ORIENTATION_CHANGED_LISTENERS = 12;
+    private static final int NOTIFY_TASK_REMOVAL_STARTED_LISTENERS = 13;
+    private static final int NOTIFY_TASK_PROFILE_LOCKED_LISTENERS_MSG = 14;
+    private static final int NOTIFY_TASK_SNAPSHOT_CHANGED_LISTENERS_MSG = 15;
+    private static final int NOTIFY_PINNED_STACK_ANIMATION_STARTED_LISTENERS_MSG = 16;
+    private static final int NOTIFY_ACTIVITY_UNPINNED_LISTENERS_MSG = 17;
+    private static final int NOTIFY_ACTIVITY_LAUNCH_ON_SECONDARY_DISPLAY_FAILED_MSG = 18;
 
     // Delay in notifying task stack change listeners (in millis)
-    static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
+    private static final int NOTIFY_TASK_STACK_CHANGE_LISTENERS_DELAY = 100;
 
     private final ActivityManagerService mService;
     private final ActivityStackSupervisor mStackSupervisor;
@@ -242,7 +241,7 @@ class TaskChangeNotificationController {
         }
     }
 
-    void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
+    private void forAllRemoteListeners(TaskStackConsumer callback, Message message) {
         synchronized (mService) {
             for (int i = mRemoteTaskStackListeners.beginBroadcast() - 1; i >= 0; i--) {
                 try {
@@ -256,7 +255,7 @@ class TaskChangeNotificationController {
         }
     }
 
-    void forAllLocalListeners(TaskStackConsumer callback, Message message) {
+    private void forAllLocalListeners(TaskStackConsumer callback, Message message) {
         synchronized (mService) {
             for (int i = mLocalTaskStackListeners.size() - 1; i >= 0; i--) {
                 try {
@@ -329,8 +328,9 @@ class TaskChangeNotificationController {
 
     void notifyActivityDismissingDockedStack() {
         mHandler.removeMessages(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
-        final Message message = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
-        forAllLocalListeners(mNotifyActivityDismissingDockedStack, message);
+        final Message msg = mHandler.obtainMessage(NOTIFY_ACTIVITY_DISMISSING_DOCKED_STACK_MSG);
+        forAllLocalListeners(mNotifyActivityDismissingDockedStack, msg);
+        msg.sendToTarget();
     }
 
     void notifyActivityForcedResizable(int taskId, int reason, String packageName) {
index 7eec945..e81e6d7 100644 (file)
@@ -115,6 +115,7 @@ import static com.android.server.am.ActivityRecord.HOME_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.RECENTS_ACTIVITY_TYPE;
 import static com.android.server.am.ActivityRecord.STARTING_WINDOW_SHOWN;
 import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING;
+import static com.android.server.am.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
 import static com.android.server.am.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.am.ActivityStackSupervisor.PRESERVE_WINDOWS;
 
@@ -673,8 +674,11 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
             mWindowContainerController.reparent(toStack.getWindowContainerController(), position,
                     moveStackMode == REPARENT_MOVE_STACK_TO_FRONT);
 
+            final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
+                    || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
             // Move the task
-            sourceStack.removeTask(this, reason, REMOVE_TASK_MODE_MOVING);
+            sourceStack.removeTask(this, reason, moveStackToFront
+                    ? REMOVE_TASK_MODE_MOVING_TO_TOP : REMOVE_TASK_MODE_MOVING);
             toStack.addTask(this, position, false /* schedulePictureInPictureModeChange */, reason);
 
             if (schedulePictureInPictureModeChange) {
@@ -693,8 +697,6 @@ final class TaskRecord extends ConfigurationContainer implements TaskWindowConta
 
             // If the task had focus before (or we're requested to move focus), move focus to the
             // new stack by moving the stack to the front.
-            final boolean moveStackToFront = moveStackMode == REPARENT_MOVE_STACK_TO_FRONT
-                    || (moveStackMode == REPARENT_KEEP_STACK_AT_FRONT && (wasFocused || wasFront));
             if (r != null) {
                 toStack.moveToFrontAndResumeStateIfNeeded(r, moveStackToFront, wasResumed,
                         wasPaused, reason);
index 901092e..3f825c5 100644 (file)
@@ -18,7 +18,13 @@ package com.android.server.connectivity;
 
 import static android.hardware.usb.UsbManager.USB_CONNECTED;
 import static android.hardware.usb.UsbManager.USB_FUNCTION_RNDIS;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
 import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_UNSPECIFIED;
 import static android.net.wifi.WifiManager.WIFI_AP_STATE_DISABLED;
 import static com.android.server.ConnectivityService.SHORT_ARG;
 
@@ -799,48 +805,73 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
         }
 
         private void handleWifiApAction(Intent intent) {
-            final int curState =  intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+            final int curState = intent.getIntExtra(EXTRA_WIFI_AP_STATE, WIFI_AP_STATE_DISABLED);
+            final String ifname = intent.getStringExtra(EXTRA_WIFI_AP_INTERFACE_NAME);
+            final int ipmode = intent.getIntExtra(EXTRA_WIFI_AP_MODE, IFACE_IP_MODE_UNSPECIFIED);
+
             synchronized (Tethering.this.mPublicSync) {
                 switch (curState) {
                     case WifiManager.WIFI_AP_STATE_ENABLING:
                         // We can see this state on the way to both enabled and failure states.
                         break;
                     case WifiManager.WIFI_AP_STATE_ENABLED:
-                        // When the AP comes up and we've been requested to tether it, do so.
-                        // Otherwise, assume it's a local-only hotspot request.
-                        final int state = mWifiTetherRequested
-                                ? IControlsTethering.STATE_TETHERED
-                                : IControlsTethering.STATE_LOCAL_ONLY;
-                        tetherMatchingInterfaces(state, ConnectivityManager.TETHERING_WIFI);
+                        enableWifiIpServingLocked(ifname, ipmode);
                         break;
                     case WifiManager.WIFI_AP_STATE_DISABLED:
                     case WifiManager.WIFI_AP_STATE_DISABLING:
                     case WifiManager.WIFI_AP_STATE_FAILED:
                     default:
-                        if (DBG) {
-                            Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" +
-                                curState);
-                        }
-                        // Tell appropriate interface state machines that they should tear
-                        // themselves down.
-                        for (int i = 0; i < mTetherStates.size(); i++) {
-                            TetherInterfaceStateMachine tism =
-                                    mTetherStates.valueAt(i).stateMachine;
-                            if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
-                                tism.sendMessage(
-                                        TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
-                                break;  // There should be at most one of these.
-                            }
-                        }
-                        // Regardless of whether we requested this transition, the AP has gone
-                        // down.  Don't try to tether again unless we're requested to do so.
-                        mWifiTetherRequested = false;
-                    break;
+                        disableWifiIpServingLocked(curState);
+                        break;
                 }
             }
         }
     }
 
+    // TODO: Pass in the interface name and, if non-empty, only turn down IP
+    // serving on that one interface.
+    private void disableWifiIpServingLocked(int apState) {
+        if (DBG) Log.d(TAG, "Canceling WiFi tethering request - AP_STATE=" + apState);
+
+        // Tell appropriate interface state machines that they should tear
+        // themselves down.
+        for (int i = 0; i < mTetherStates.size(); i++) {
+            TetherInterfaceStateMachine tism = mTetherStates.valueAt(i).stateMachine;
+            if (tism.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
+                tism.sendMessage(TetherInterfaceStateMachine.CMD_TETHER_UNREQUESTED);
+                break;  // There should be at most one of these.
+            }
+        }
+        // Regardless of whether we requested this transition, the AP has gone
+        // down.  Don't try to tether again unless we're requested to do so.
+        mWifiTetherRequested = false;
+    }
+
+    private void enableWifiIpServingLocked(String ifname, int wifiIpMode) {
+        // Map wifiIpMode values to IControlsTethering serving states, inferring
+        // from mWifiTetherRequested as a final "best guess".
+        final int ipServingMode;
+        switch (wifiIpMode) {
+            case IFACE_IP_MODE_TETHERED:
+                ipServingMode = IControlsTethering.STATE_TETHERED;
+                break;
+            case IFACE_IP_MODE_LOCAL_ONLY:
+                ipServingMode = IControlsTethering.STATE_LOCAL_ONLY;
+                break;
+            default:
+                mLog.e("Cannot enable IP serving in unknown WiFi mode: " + wifiIpMode);
+                return;
+        }
+
+        if (!TextUtils.isEmpty(ifname)) {
+            changeInterfaceState(ifname, ipServingMode);
+        } else {
+            mLog.e(String.format(
+                   "Cannot enable IP serving in mode %s on missing interface name",
+                   ipServingMode));
+        }
+    }
+
     // TODO: Consider renaming to something more accurate in its description.
     // This method:
     //     - allows requesting either tethering or local hotspot serving states
@@ -873,22 +904,26 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
             return;
         }
 
+        changeInterfaceState(chosenIface, requestedState);
+    }
+
+    private void changeInterfaceState(String ifname, int requestedState) {
         final int result;
         switch (requestedState) {
             case IControlsTethering.STATE_UNAVAILABLE:
             case IControlsTethering.STATE_AVAILABLE:
-                result = untether(chosenIface);
+                result = untether(ifname);
                 break;
             case IControlsTethering.STATE_TETHERED:
             case IControlsTethering.STATE_LOCAL_ONLY:
-                result = tether(chosenIface, requestedState);
+                result = tether(ifname, requestedState);
                 break;
             default:
                 Log.wtf(TAG, "Unknown interface state: " + requestedState);
                 return;
         }
         if (result != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
-            Log.e(TAG, "unable start or stop tethering on iface " + chosenIface);
+            Log.e(TAG, "unable start or stop tethering on iface " + ifname);
             return;
         }
     }
@@ -1470,10 +1505,10 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
                 final String iface = who.interfaceName();
                 switch (mode) {
                     case IControlsTethering.STATE_TETHERED:
-                        mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_TETHERED);
+                        mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_TETHERED);
                         break;
                     case IControlsTethering.STATE_LOCAL_ONLY:
-                        mgr.updateInterfaceIpState(iface, WifiManager.IFACE_IP_MODE_LOCAL_ONLY);
+                        mgr.updateInterfaceIpState(iface, IFACE_IP_MODE_LOCAL_ONLY);
                         break;
                     default:
                         Log.wtf(TAG, "Unknown active serving mode: " + mode);
@@ -1491,7 +1526,7 @@ public class Tethering extends BaseNetworkObserver implements IControlsTethering
             if (who.interfaceType() == ConnectivityManager.TETHERING_WIFI) {
                 if (who.lastError() != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
                     getWifiManager().updateInterfaceIpState(
-                            who.interfaceName(), WifiManager.IFACE_IP_MODE_CONFIGURATION_ERROR);
+                            who.interfaceName(), IFACE_IP_MODE_CONFIGURATION_ERROR);
                 }
             }
         }
index 6941193..e87d860 100644 (file)
@@ -77,6 +77,9 @@ public class TetheringConfiguration {
     public TetheringConfiguration(Context ctx) {
         tetherableUsbRegexs = ctx.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_usb_regexs);
+        // TODO: Evaluate deleting this altogether now that Wi-Fi always passes
+        // us an interface name. Careful consideration needs to be given to
+        // implications for Settings and for provisioning checks.
         tetherableWifiRegexs = ctx.getResources().getStringArray(
                 com.android.internal.R.array.config_tether_wifi_regexs);
         tetherableBluetoothRegexs = ctx.getResources().getStringArray(
index 1504538..3ca65cd 100644 (file)
@@ -1858,7 +1858,7 @@ public class SyncManager {
                     account.account.name, account.userId, account.account.type);
 
             pw.println("=======================================================================");
-            final PrintTable table = new PrintTable(12);
+            final PrintTable table = new PrintTable(13);
             table.set(0, 0,
                     "Authority", // 0
                     "Syncable",  // 1
@@ -1871,7 +1871,8 @@ public class SyncManager {
                     "User",      // 8
                     "Tot",       // 9
                     "Time",      // 10
-                    "Last Sync" // 11
+                    "Last Sync", // 11
+                    "Etc"        // 12
             );
 
             final List<RegisteredServicesCache.ServiceInfo<SyncAdapterType>> sorted =
@@ -1921,6 +1922,7 @@ public class SyncManager {
                     }
                 }
 
+                row1 = row;
                 if (status.lastSuccessTime != 0) {
                     table.set(row1++, 11, SyncStorageEngine.SOURCES[status.lastSuccessSource]
                             + " " + "SUCCESS");
index 9dc317a..e82724d 100644 (file)
@@ -104,6 +104,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
     // Trigger proximity if distance is less than 5 cm.
     private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
 
+    // State machine constants for tracking initial brightness ramp skipping when enabled.
+    private static final int RAMP_STATE_SKIP_NONE = 0;
+    private static final int RAMP_STATE_SKIP_INITIAL = 1;
+    private static final int RAMP_STATE_SKIP_AUTOBRIGHT = 2;
+
     private static final int REPORTED_TO_POLICY_SCREEN_OFF = 0;
     private static final int REPORTED_TO_POLICY_SCREEN_TURNING_ON = 1;
     private static final int REPORTED_TO_POLICY_SCREEN_ON = 2;
@@ -239,6 +244,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
     // Screen state we reported to policy. Must be one of REPORTED_TO_POLICY_SCREEN_* fields.
     private int mReportedScreenStateToPolicy;
 
+    // If the last recorded screen state was dozing or not.
+    private boolean mDozing;
+
     // Remembers whether certain kinds of brightness adjustments
     // were recently applied so that we can decide how to transition.
     private boolean mAppliedAutoBrightness;
@@ -249,6 +257,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
     private final int mBrightnessRampRateFast;
     private final int mBrightnessRampRateSlow;
 
+    // Whether or not to skip the initial brightness ramps into STATE_ON.
+    private final boolean mSkipScreenOnBrightnessRamp;
+
+    // A record of state for skipping brightness ramps.
+    private int mSkipRampState = RAMP_STATE_SKIP_NONE;
+
+    // The first autobrightness value set when entering RAMP_STATE_SKIP_INITIAL.
+    private int mInitialAutoBrightness;
+
     // The controller for the automatic brightness level.
     private AutomaticBrightnessController mAutomaticBrightnessController;
 
@@ -312,6 +329,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
                 com.android.internal.R.integer.config_brightness_ramp_rate_fast);
         mBrightnessRampRateSlow = resources.getInteger(
                 com.android.internal.R.integer.config_brightness_ramp_rate_slow);
+        mSkipScreenOnBrightnessRamp = resources.getBoolean(
+                com.android.internal.R.bool.config_skipScreenOnBrightnessRamp);
 
         int lightSensorRate = resources.getInteger(
                 com.android.internal.R.integer.config_autoBrightnessLightSensorRate);
@@ -731,8 +750,29 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
         // Animate the screen brightness when the screen is on or dozing.
         // Skip the animation when the screen is off or suspended or transition to/from VR.
         if (!mPendingScreenOff) {
+            if (mSkipScreenOnBrightnessRamp) {
+
+                if (state == Display.STATE_ON) {
+                    if (mSkipRampState == RAMP_STATE_SKIP_NONE && mDozing) {
+                        mInitialAutoBrightness = brightness;
+                        mSkipRampState = RAMP_STATE_SKIP_INITIAL;
+                    } else if (mSkipRampState == RAMP_STATE_SKIP_INITIAL
+                            && mUseSoftwareAutoBrightnessConfig
+                            && brightness != mInitialAutoBrightness) {
+                        mSkipRampState = RAMP_STATE_SKIP_AUTOBRIGHT;
+                    } else if (mSkipRampState == RAMP_STATE_SKIP_AUTOBRIGHT) {
+                        mSkipRampState = RAMP_STATE_SKIP_NONE;
+                    }
+                } else {
+                    mSkipRampState = RAMP_STATE_SKIP_NONE;
+                }
+            }
+
             boolean wasOrWillBeInVr = (state == Display.STATE_VR || oldState == Display.STATE_VR);
-            if ((state == Display.STATE_ON || state == Display.STATE_DOZE) && !wasOrWillBeInVr) {
+            if ((state == Display.STATE_ON
+                    && mSkipRampState == RAMP_STATE_SKIP_NONE
+                    || state == Display.STATE_DOZE)
+                    && !wasOrWillBeInVr) {
                 animateScreenBrightness(brightness,
                         slowChange ? mBrightnessRampRateSlow : mBrightnessRampRateFast);
             } else {
@@ -790,6 +830,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
             mUnfinishedBusiness = false;
             mCallbacks.releaseSuspendBlocker();
         }
+
+        // Record if dozing for future comparison.
+        mDozing = state != Display.STATE_ON;
     }
 
     @Override
index 9862516..e2fd0ac 100644 (file)
@@ -369,8 +369,8 @@ final class DisplayPowerState {
                     mPendingBacklight = backlight;
 
                     boolean changeInProgress = mStateChangeInProgress || mBacklightChangeInProgress;
-                    mStateChangeInProgress = stateChanged;
-                    mBacklightChangeInProgress = backlightChanged;
+                    mStateChangeInProgress = stateChanged || mStateChangeInProgress;
+                    mBacklightChangeInProgress = backlightChanged || mBacklightChangeInProgress;
 
                     if (!changeInProgress) {
                         mLock.notifyAll();
index d574265..b3cf57b 100644 (file)
@@ -285,12 +285,6 @@ public final class NightDisplayService extends SystemService
         if (mIsActivated == null || mIsActivated != activated) {
             Slog.i(TAG, activated ? "Turning on night display" : "Turning off night display");
 
-            if (mIsActivated != null) {
-                Secure.putLongForUser(getContext().getContentResolver(),
-                        Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(),
-                        mCurrentUser);
-            }
-
             mIsActivated = activated;
 
             if (mAutoMode != null) {
@@ -430,19 +424,6 @@ public final class NightDisplayService extends SystemService
         outTemp[10] = blue;
     }
 
-    private Calendar getLastActivatedTime() {
-        final ContentResolver cr = getContext().getContentResolver();
-        final long lastActivatedTimeMillis = Secure.getLongForUser(
-                cr, Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, -1, mCurrentUser);
-        if (lastActivatedTimeMillis < 0) {
-            return null;
-        }
-
-        final Calendar lastActivatedTime = Calendar.getInstance();
-        lastActivatedTime.setTimeInMillis(lastActivatedTimeMillis);
-        return lastActivatedTime;
-    }
-
     private abstract class AutoMode implements NightDisplayController.Callback {
         public abstract void onStart();
 
@@ -522,7 +503,7 @@ public final class NightDisplayService extends SystemService
             mStartTime = mController.getCustomStartTime();
             mEndTime = mController.getCustomEndTime();
 
-            mLastActivatedTime = getLastActivatedTime();
+            mLastActivatedTime = mController.getLastActivatedTime();
 
             // Force an update to initialize state.
             updateActivated();
@@ -538,7 +519,7 @@ public final class NightDisplayService extends SystemService
 
         @Override
         public void onActivated(boolean activated) {
-            mLastActivatedTime = getLastActivatedTime();
+            mLastActivatedTime = mController.getLastActivatedTime();
             updateNextAlarm(activated, Calendar.getInstance());
         }
 
@@ -579,7 +560,7 @@ public final class NightDisplayService extends SystemService
             }
 
             boolean activate = state.isNight();
-            final Calendar lastActivatedTime = getLastActivatedTime();
+            final Calendar lastActivatedTime = mController.getLastActivatedTime();
             if (lastActivatedTime != null) {
                 final Calendar now = Calendar.getInstance();
                 final Calendar sunrise = state.sunrise();
index 1b984a4..dbccc07 100644 (file)
@@ -86,7 +86,6 @@ public final class DreamManagerService extends SystemService {
     private boolean mCurrentDreamCanDoze;
     private boolean mCurrentDreamIsDozing;
     private boolean mCurrentDreamIsWaking;
-    private Runnable mStopDreamRunnable;
     private int mCurrentDreamDozeScreenState = Display.STATE_UNKNOWN;
     private int mCurrentDreamDozeScreenBrightness = PowerManager.BRIGHTNESS_DEFAULT;
 
@@ -350,11 +349,6 @@ public final class DreamManagerService extends SystemService {
 
     private void startDreamLocked(final ComponentName name,
             final boolean isTest, final boolean canDoze, final int userId) {
-        if (mStopDreamRunnable != null) {
-            mHandler.removeCallbacks(mStopDreamRunnable);
-            mStopDreamRunnable = null;
-        }
-
         if (Objects.equal(mCurrentDreamName, name)
                 && mCurrentDreamIsTest == isTest
                 && mCurrentDreamCanDoze == canDoze
@@ -392,15 +386,13 @@ public final class DreamManagerService extends SystemService {
                 mCurrentDreamIsWaking = true;
             }
 
-            mStopDreamRunnable = new Runnable() {
+            mHandler.post(new Runnable() {
                 @Override
                 public void run() {
                     Slog.i(TAG, "Performing gentle wake from dream.");
                     mController.stopDream(immediate);
-                    mStopDreamRunnable = null;
                 }
-            };
-            mHandler.post(mStopDreamRunnable);
+            });
         }
     }
 
index b8d633f..73a365b 100644 (file)
@@ -221,7 +221,9 @@ abstract public class ManagedServices {
                         restoredSettingName(element),
                         newValue,
                         userid);
-                updateSettingsAccordingToInstalledServices(element, userid);
+                if (mConfig.secureSettingName.equals(element)) {
+                    updateSettingsAccordingToInstalledServices(element, userid);
+                }
                 rebuildRestoredPackages();
             }
         }
index e377d57..19d5f3c 100644 (file)
@@ -149,6 +149,7 @@ import android.view.accessibility.AccessibilityManager;
 import android.widget.Toast;
 
 import com.android.internal.R;
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
@@ -231,7 +232,6 @@ public class NotificationManagerService extends SystemService {
 
     static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_NOTIFICATION;
 
-    static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
     static final boolean ENABLE_BLOCKED_TOASTS = true;
 
     // When #matchesCallFilter is called from the ringer, wait at most
@@ -689,6 +689,7 @@ public class NotificationManagerService extends SystemService {
         }
     };
 
+    @GuardedBy("mNotificationLock")
     private void clearSoundLocked() {
         mSoundNotificationKey = null;
         long identity = Binder.clearCallingIdentity();
@@ -703,6 +704,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mNotificationLock")
     private void clearVibrateLocked() {
         mVibrateNotificationKey = null;
         long identity = Binder.clearCallingIdentity();
@@ -713,6 +715,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mNotificationLock")
     private void clearLightsLocked() {
         // light
         mLights.clear();
@@ -1051,7 +1054,8 @@ public class NotificationManagerService extends SystemService {
     @VisibleForTesting
     void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
             LightsManager lightsManager, NotificationListeners notificationListeners,
-            ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper) {
+            ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,
+            NotificationUsageStats usageStats) {
         Resources resources = getContext().getResources();
         mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
                 Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1074,7 +1078,7 @@ public class NotificationManagerService extends SystemService {
         } catch (Resources.NotFoundException e) {
             extractorNames = new String[0];
         }
-        mUsageStats = new NotificationUsageStats(getContext());
+        mUsageStats = usageStats;
         mRankingHandler = new RankingHandlerWorker(mRankingThread.getLooper());
         mRankingHelper = new RankingHelper(getContext(),
                 getContext().getPackageManager(),
@@ -1243,7 +1247,7 @@ public class NotificationManagerService extends SystemService {
 
         init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
                 getLocalService(LightsManager.class), new NotificationListeners(),
-                null, snoozeHelper);
+                null, snoozeHelper, new NotificationUsageStats(getContext()));
         publishBinderService(Context.NOTIFICATION_SERVICE, mService);
         publishLocalService(NotificationManagerInternal.class, mInternalService);
     }
@@ -1274,6 +1278,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mNotificationLock")
     private void updateListenerHintsLocked() {
         final int hints = calculateHints();
         if (hints == mListenerHints) return;
@@ -1282,6 +1287,7 @@ public class NotificationManagerService extends SystemService {
         scheduleListenerHintsChanged(hints);
     }
 
+    @GuardedBy("mNotificationLock")
     private void updateEffectsSuppressorLocked() {
         final long updatedSuppressedEffects = calculateSuppressedEffects();
         if (updatedSuppressedEffects == mZenModeHelper.getSuppressedEffects()) return;
@@ -1416,6 +1422,7 @@ public class NotificationManagerService extends SystemService {
         return suppressedEffects;
     }
 
+    @GuardedBy("mNotificationLock")
     private void updateInterruptionFilterLocked() {
         int interruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
         if (interruptionFilter == mInterruptionFilter) return;
@@ -1579,7 +1586,7 @@ public class NotificationManagerService extends SystemService {
 
             mRankingHelper.setEnabled(pkg, uid, enabled);
             // Now, cancel any outstanding notifications that are part of a just-disabled app
-            if (ENABLE_BLOCKED_NOTIFICATIONS && !enabled) {
+            if (!enabled) {
                 cancelAllNotificationsInt(MY_UID, MY_PID, pkg, null, 0, 0, true,
                         UserHandle.getUserId(uid), REASON_PACKAGE_BANNED, null);
             }
@@ -2074,6 +2081,7 @@ public class NotificationManagerService extends SystemService {
          *
          * @param info The binder for the listener, to check that the caller is allowed
          */
+        @GuardedBy("mNotificationLock")
         private void cancelNotificationFromListenerLocked(ManagedServiceInfo info,
                 int callingUid, int callingPid, String pkg, String tag, int id, int userId) {
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
@@ -2770,25 +2778,28 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mNotificationLock")
     private void addAutogroupKeyLocked(String key) {
         NotificationRecord n = mNotificationsByKey.get(key);
         if (n == null) {
             return;
         }
-        n.sbn.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
+        n.setOverrideGroupKey(GroupHelper.AUTOGROUP_KEY);
         EventLogTags.writeNotificationAutogrouped(key);
     }
 
+    @GuardedBy("mNotificationLock")
     private void removeAutogroupKeyLocked(String key) {
         NotificationRecord n = mNotificationsByKey.get(key);
         if (n == null) {
             return;
         }
-        n.sbn.setOverrideGroupKey(null);
+        n.setOverrideGroupKey(null);
         EventLogTags.writeNotificationUnautogrouped(key);
     }
 
     // Clears the 'fake' auto-group summary.
+    @GuardedBy("mNotificationLock")
     private void clearAutogroupSummaryLocked(int userId, String pkg) {
         ArrayMap<String, String> summaries = mAutobundledSummaries.get(userId);
         if (summaries != null && summaries.containsKey(pkg)) {
@@ -3109,10 +3120,12 @@ public class NotificationManagerService extends SystemService {
             });
         }
 
+        @GuardedBy("mNotificationLock")
         private void removeForegroundServiceFlagByListLocked(
-                ArrayList<NotificationRecord> notificationList, String pkg, int notificationId, int userId) {
-            NotificationRecord r =
-                    findNotificationByListLocked(notificationList, pkg, null, notificationId, userId);
+                ArrayList<NotificationRecord> notificationList, String pkg, int notificationId,
+                int userId) {
+            NotificationRecord r = findNotificationByListLocked(
+                    notificationList, pkg, null, notificationId, userId);
             if (r == null) {
                 return;
             }
@@ -3194,7 +3207,7 @@ public class NotificationManagerService extends SystemService {
                 user, null, System.currentTimeMillis());
         final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
 
-        if (!checkDisqualifyingFeatures(userId, notificationUid, id,tag, r)) {
+        if (!checkDisqualifyingFeatures(userId, notificationUid, id, tag, r)) {
             return;
         }
 
@@ -3225,7 +3238,7 @@ public class NotificationManagerService extends SystemService {
                 Settings.Global.SHOW_NOTIFICATION_CHANNEL_WARNINGS, defaultWarningEnabled) != 0;
         if (warningEnabled) {
             Toast toast = Toast.makeText(getContext(), mHandler.getLooper(), toastText,
-                    Toast.LENGTH_LONG);
+                    Toast.LENGTH_SHORT);
             toast.show();
         }
     }
@@ -3337,7 +3350,8 @@ public class NotificationManagerService extends SystemService {
             return isPackageSuspended;
         }
 
-        final boolean isBlocked = r.getImportance() == NotificationManager.IMPORTANCE_NONE
+        final boolean isBlocked =
+                mRankingHelper.getImportance(pkg, callingUid) == NotificationManager.IMPORTANCE_NONE
                 || r.getChannel().getImportance() == NotificationManager.IMPORTANCE_NONE;
         if (isBlocked) {
             Slog.e(TAG, "Suppressing notification from package by user request.");
@@ -3367,6 +3381,7 @@ public class NotificationManagerService extends SystemService {
             }
         }
 
+        @GuardedBy("mNotificationLock")
         void snoozeLocked(NotificationRecord r) {
             if (r.sbn.isGroup()) {
                 final List<NotificationRecord> groupNotifications = findGroupNotificationsLocked(
@@ -3398,6 +3413,7 @@ public class NotificationManagerService extends SystemService {
             }
         }
 
+        @GuardedBy("mNotificationLock")
         void snoozeNotificationLocked(NotificationRecord r) {
             MetricsLogger.action(r.getLogMaker()
                     .setCategory(MetricsEvent.NOTIFICATION_SNOOZED)
@@ -3586,6 +3602,7 @@ public class NotificationManagerService extends SystemService {
      *
      * <p>Updates mSummaryByGroupKey.</p>
      */
+    @GuardedBy("mNotificationLock")
     private void handleGroupedNotificationLocked(NotificationRecord r, NotificationRecord old,
             int callingUid, int callingPid) {
         StatusBarNotification sbn = r.sbn;
@@ -3626,6 +3643,7 @@ public class NotificationManagerService extends SystemService {
     }
 
     @VisibleForTesting
+    @GuardedBy("mNotificationLock")
     void scheduleTimeoutLocked(NotificationRecord record) {
         if (record.getNotification().getTimeoutAfter() > 0) {
             final PendingIntent pi = PendingIntent.getBroadcast(getContext(),
@@ -3642,6 +3660,7 @@ public class NotificationManagerService extends SystemService {
     }
 
     @VisibleForTesting
+    @GuardedBy("mNotificationLock")
     void buzzBeepBlinkLocked(NotificationRecord record) {
         boolean buzz = false;
         boolean beep = false;
@@ -3714,7 +3733,7 @@ public class NotificationManagerService extends SystemService {
                     if (!mInCall && hasValidVibrate && !ringerModeSilent) {
                         mVibrateNotificationKey = key;
 
-                        buzz = playVibration(record, vibration);
+                        buzz = playVibration(record, vibration, hasValidSound);
                     }
                 }
             }
@@ -3752,6 +3771,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mNotificationLock")
     boolean shouldMuteNotificationLocked(final NotificationRecord record) {
         final Notification notification = record.getNotification();
         if(record.isUpdate
@@ -3759,13 +3779,7 @@ public class NotificationManagerService extends SystemService {
             return true;
         }
         if (record.sbn.isGroup()) {
-            if (notification.isGroupSummary()
-                    && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_CHILDREN) {
-                return true;
-            } else if (notification.isGroupChild()
-                    && notification.getGroupAlertBehavior() == Notification.GROUP_ALERT_SUMMARY) {
-                return true;
-            }
+            return notification.suppressAlertingDueToGrouping();
         }
         return false;
     }
@@ -3794,22 +3808,41 @@ public class NotificationManagerService extends SystemService {
         return false;
     }
 
-    private boolean playVibration(final NotificationRecord record, long[] vibration) {
+    private boolean playVibration(final NotificationRecord record, long[] vibration,
+            boolean delayVibForSound) {
         // Escalate privileges so we can use the vibrator even if the
         // notifying app does not have the VIBRATE permission.
         long identity = Binder.clearCallingIdentity();
         try {
-            final boolean insistent =
-                (record.getNotification().flags & Notification.FLAG_INSISTENT) != 0;
-            final VibrationEffect effect = VibrationEffect.createWaveform(
-                    vibration, insistent ? 0 : -1 /*repeatIndex*/);
-            mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
-                    effect, record.getAudioAttributes());
+            final VibrationEffect effect;
+            try {
+                final boolean insistent =
+                        (record.getNotification().flags & Notification.FLAG_INSISTENT) != 0;
+                effect = VibrationEffect.createWaveform(
+                        vibration, insistent ? 0 : -1 /*repeatIndex*/);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Error creating vibration waveform with pattern: " +
+                        Arrays.toString(vibration));
+                return false;
+            }
+            if (delayVibForSound) {
+                new Thread(() -> {
+                    // delay the vibration by the same amount as the notification sound
+                    final int waitMs = mAudioManager.getFocusRampTimeMs(
+                            AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
+                            record.getAudioAttributes());
+                    if (DBG) Slog.v(TAG, "Delaying vibration by " + waitMs + "ms");
+                    try {
+                        Thread.sleep(waitMs);
+                    } catch (InterruptedException e) { }
+                    mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                            effect, record.getAudioAttributes());
+                }).start();
+            } else {
+                mVibrator.vibrate(record.sbn.getUid(), record.sbn.getOpPkg(),
+                        effect, record.getAudioAttributes());
+            }
             return true;
-        } catch (IllegalArgumentException e) {
-            Slog.e(TAG, "Error creating vibration waveform with pattern: " +
-                    Arrays.toString(vibration));
-            return false;
         } finally{
             Binder.restoreCallingIdentity(identity);
         }
@@ -3848,6 +3881,7 @@ public class NotificationManagerService extends SystemService {
         }.start();
     }
 
+    @GuardedBy("mToastQueue")
     void showNextToastLocked() {
         ToastRecord record = mToastQueue.get(0);
         while (record != null) {
@@ -3874,6 +3908,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mToastQueue")
     void cancelToastLocked(int index) {
         ToastRecord record = mToastQueue.get(index);
         try {
@@ -3897,6 +3932,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mToastQueue")
     private void scheduleTimeoutLocked(ToastRecord r)
     {
         mHandler.removeCallbacksAndMessages(r);
@@ -3916,7 +3952,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
-    // lock on mToastQueue
+    @GuardedBy("mToastQueue")
     int indexOfToastLocked(String pkg, ITransientNotification callback)
     {
         IBinder cbak = callback.asBinder();
@@ -3931,7 +3967,7 @@ public class NotificationManagerService extends SystemService {
         return -1;
     }
 
-    // lock on mToastQueue
+    @GuardedBy("mToastQueue")
     void keepProcessAliveIfNeededLocked(int pid)
     {
         int toastCount = 0; // toasts from this pid
@@ -4015,6 +4051,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mNotificationLock")
     private void recordCallerLocked(NotificationRecord record) {
         if (mZenModeHelper.isCall(record)) {
             mZenModeHelper.recordCaller(record);
@@ -4022,6 +4059,7 @@ public class NotificationManagerService extends SystemService {
     }
 
     // let zen mode evaluate this record
+    @GuardedBy("mNotificationLock")
     private void applyZenModeLocked(NotificationRecord record) {
         record.setIntercepted(mZenModeHelper.shouldIntercept(record));
         if (record.isIntercepted()) {
@@ -4035,7 +4073,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
-    // lock on mNotificationList
+    @GuardedBy("mNotificationLock")
     private int findNotificationRecordIndexLocked(NotificationRecord target) {
         return mRankingHelper.indexOf(mNotificationList, target);
     }
@@ -4168,6 +4206,7 @@ public class NotificationManagerService extends SystemService {
         manager.sendAccessibilityEvent(event);
     }
 
+    @GuardedBy("mNotificationLock")
     private void cancelNotificationLocked(NotificationRecord r, boolean sendDelete, int reason) {
         final String canceledKey = r.getKey();
 
@@ -4417,6 +4456,7 @@ public class NotificationManagerService extends SystemService {
         public boolean apply(int flags);
     }
 
+    @GuardedBy("mNotificationLock")
     private void cancelAllNotificationsByListLocked(ArrayList<NotificationRecord> notificationList,
             int callingUid, int callingPid, String pkg, boolean nullPkgIndicatesUserSwitch,
             String channelId, FlagChecker flagChecker, boolean includeCurrentProfiles, int userId,
@@ -4485,6 +4525,7 @@ public class NotificationManagerService extends SystemService {
         savePolicyFile();
     }
 
+    @GuardedBy("mNotificationLock")
     void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
             ManagedServiceInfo listener, boolean includeCurrentProfiles) {
         mHandler.post(new Runnable() {
@@ -4519,6 +4560,7 @@ public class NotificationManagerService extends SystemService {
     }
 
     // Warning: The caller is responsible for invoking updateLightsLocked().
+    @GuardedBy("mNotificationLock")
     private void cancelGroupChildrenLocked(NotificationRecord r, int callingUid, int callingPid,
             String listenerName, boolean sendDelete) {
         Notification n = r.getNotification();
@@ -4540,6 +4582,7 @@ public class NotificationManagerService extends SystemService {
                 listenerName, sendDelete);
     }
 
+    @GuardedBy("mNotificationLock")
     private void cancelGroupChildrenByListLocked(ArrayList<NotificationRecord> notificationList,
             NotificationRecord parentNotification, int callingUid, int callingPid,
             String listenerName, boolean sendDelete) {
@@ -4559,7 +4602,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
-    // lock on mNotificationList
+    @GuardedBy("mNotificationLock")
     void updateLightsLocked()
     {
         // handle notification lights
@@ -4586,6 +4629,7 @@ public class NotificationManagerService extends SystemService {
         }
     }
 
+    @GuardedBy("mNotificationLock")
     @NonNull List<NotificationRecord> findGroupNotificationsLocked(String pkg,
             String groupKey, int userId) {
         List<NotificationRecord> records = new ArrayList<>();
@@ -4596,6 +4640,7 @@ public class NotificationManagerService extends SystemService {
     }
 
 
+    @GuardedBy("mNotificationLock")
     private @NonNull List<NotificationRecord> findGroupNotificationByListLocked(
             ArrayList<NotificationRecord> list, String pkg, String groupKey, int userId) {
         List<NotificationRecord> records = new ArrayList<>();
@@ -4613,6 +4658,7 @@ public class NotificationManagerService extends SystemService {
     // Searches both enqueued and posted notifications by key.
     // TODO: need to combine a bunch of these getters with slightly different behavior.
     // TODO: Should enqueuing just add to mNotificationsByKey instead?
+    @GuardedBy("mNotificationLock")
     private NotificationRecord findNotificationByKeyLocked(String key) {
         NotificationRecord r;
         if ((r = findNotificationByListLocked(mNotificationList, key)) != null) {
@@ -4624,6 +4670,7 @@ public class NotificationManagerService extends SystemService {
         return null;
     }
 
+    @GuardedBy("mNotificationLock")
     NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) {
         NotificationRecord r;
         if ((r = findNotificationByListLocked(mNotificationList, pkg, tag, id, userId)) != null) {
@@ -4636,6 +4683,7 @@ public class NotificationManagerService extends SystemService {
         return null;
     }
 
+    @GuardedBy("mNotificationLock")
     private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
             String pkg, String tag, int id, int userId) {
         final int len = list.size();
@@ -4649,9 +4697,9 @@ public class NotificationManagerService extends SystemService {
         return null;
     }
 
+    @GuardedBy("mNotificationLock")
     private NotificationRecord findNotificationByListLocked(ArrayList<NotificationRecord> list,
-            String key)
-    {
+            String key) {
         final int N = list.size();
         for (int i = 0; i < N; i++) {
             if (key.equals(list.get(i).getKey())) {
@@ -4661,7 +4709,7 @@ public class NotificationManagerService extends SystemService {
         return null;
     }
 
-    // lock on mNotificationList
+    @GuardedBy("mNotificationLock")
     int indexOfNotificationLocked(String key) {
         final int N = mNotificationList.size();
         for (int i = 0; i < N; i++) {
@@ -4768,9 +4816,8 @@ public class NotificationManagerService extends SystemService {
     /**
      * Generates a NotificationRankingUpdate from 'sbns', considering only
      * notifications visible to the given listener.
-     *
-     * <p>Caller must hold a lock on mNotificationList.</p>
      */
+    @GuardedBy("mNotificationLock")
     private NotificationRankingUpdate makeRankingUpdateLocked(ManagedServiceInfo info) {
         final int N = mNotificationList.size();
         ArrayList<String> keys = new ArrayList<String>(N);
@@ -4901,7 +4948,7 @@ public class NotificationManagerService extends SystemService {
     public class NotificationAssistants extends ManagedServices {
 
         public NotificationAssistants() {
-            super(getContext(), mHandler, mNotificationList, mUserProfiles);
+            super(getContext(), mHandler, mNotificationLock, mUserProfiles);
         }
 
         @Override
@@ -4932,6 +4979,7 @@ public class NotificationManagerService extends SystemService {
         }
 
         @Override
+        @GuardedBy("mNotificationLock")
         protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
             mListeners.unregisterService(removed.service, removed.userid);
         }
@@ -4975,6 +5023,7 @@ public class NotificationManagerService extends SystemService {
          * asynchronously notify the assistant that a notification has been snoozed until a
          * context
          */
+        @GuardedBy("mNotificationLock")
         public void notifyAssistantSnoozedLocked(final StatusBarNotification sbn,
                 final String snoozeCriterionId) {
             TrimCache trimCache = new TrimCache(sbn);
@@ -5008,7 +5057,7 @@ public class NotificationManagerService extends SystemService {
         private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
 
         public NotificationListeners() {
-            super(getContext(), mHandler, mNotificationList, mUserProfiles);
+            super(getContext(), mHandler, mNotificationLock, mUserProfiles);
         }
 
         @Override
@@ -5048,6 +5097,7 @@ public class NotificationManagerService extends SystemService {
         }
 
         @Override
+        @GuardedBy("mNotificationLock")
         protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
             if (removeDisabledHints(removed)) {
                 updateListenerHintsLocked();
@@ -5056,6 +5106,7 @@ public class NotificationManagerService extends SystemService {
             mLightTrimListeners.remove(removed);
         }
 
+        @GuardedBy("mNotificationLock")
         public void setOnNotificationPostedTrimLocked(ManagedServiceInfo info, int trim) {
             if (trim == TRIM_LIGHT) {
                 mLightTrimListeners.add(info);
@@ -5075,6 +5126,7 @@ public class NotificationManagerService extends SystemService {
          * Also takes care of removing a notification that has been visible to a listener before,
          * but isn't anymore.
          */
+        @GuardedBy("mNotificationLock")
         public void notifyPostedLocked(StatusBarNotification sbn, StatusBarNotification oldSbn) {
             // Lazily initialized snapshots of the notification.
             TrimCache trimCache = new TrimCache(sbn);
@@ -5113,6 +5165,7 @@ public class NotificationManagerService extends SystemService {
         /**
          * asynchronously notify all listeners about a removed notification
          */
+        @GuardedBy("mNotificationLock")
         public void notifyRemovedLocked(StatusBarNotification sbn, int reason) {
             // make a copy in case changes are made to the underlying Notification object
             // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
@@ -5135,6 +5188,7 @@ public class NotificationManagerService extends SystemService {
         /**
          * asynchronously notify all listeners about a reordering of notifications
          */
+        @GuardedBy("mNotificationLock")
         public void notifyRankingUpdateLocked() {
             for (final ManagedServiceInfo serviceInfo : getServices()) {
                 if (!serviceInfo.isEnabledForCurrentProfiles()) {
@@ -5150,6 +5204,7 @@ public class NotificationManagerService extends SystemService {
             }
         }
 
+        @GuardedBy("mNotificationLock")
         public void notifyListenerHintsChangedLocked(final int hints) {
             for (final ManagedServiceInfo serviceInfo : getServices()) {
                 if (!serviceInfo.isEnabledForCurrentProfiles()) {
index 803b0dc..8952870 100644 (file)
@@ -45,6 +45,7 @@ import android.util.Log;
 import android.util.Slog;
 import android.util.TimeUtils;
 import android.util.proto.ProtoOutputStream;
+import android.widget.RemoteViews;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
@@ -62,7 +63,7 @@ import java.util.Objects;
  * {@link android.service.notification.NotificationListenerService}s.
  *
  * <p>These objects should not be mutated unless the code is synchronized
- * on {@link NotificationManagerService#mNotificationList}, and any
+ * on {@link NotificationManagerService#mNotificationLock}, and any
  * modification should be followed by a sorting of that list.</p>
  *
  * <p>Is sortable by {@link NotificationComparator}.</p>
@@ -72,6 +73,7 @@ import java.util.Objects;
 public final class NotificationRecord {
     static final String TAG = "NotificationRecord";
     static final boolean DBG = Log.isLoggable(TAG, Log.DEBUG);
+    private static final int MAX_LOGTAG_LENGTH = 35;
     final StatusBarNotification sbn;
     final int mOriginalFlags;
     private final Context mContext;
@@ -126,6 +128,8 @@ public final class NotificationRecord {
     private boolean mShowBadge;
     private LogMaker mLogMaker;
     private Light mLight;
+    private String mGroupLogTag;
+    private String mChannelIdLogTag;
 
     @VisibleForTesting
     public NotificationRecord(Context context, StatusBarNotification sbn,
@@ -359,8 +363,13 @@ public final class NotificationRecord {
         }
     }
 
+    String formatRemoteViews(RemoteViews rv) {
+        if (rv == null) return "null";
+        return String.format("%s/0x%08x (%d bytes): %s",
+            rv.getPackage(), rv.getLayoutId(), rv.estimateMemoryUsage(), rv.toString());
+    }
+
     void dump(PrintWriter pw, String prefix, Context baseContext, boolean redact) {
-        prefix = prefix + "  ";
         final Notification notification = sbn.getNotification();
         final Icon icon = notification.getSmallIcon();
         String iconStr = String.valueOf(icon);
@@ -368,6 +377,7 @@ public final class NotificationRecord {
             iconStr += " / " + idDebugString(baseContext, icon.getResPackage(), icon.getResId());
         }
         pw.println(prefix + this);
+        prefix = prefix + "  ";
         pw.println(prefix + "uid=" + sbn.getUid() + " userId=" + sbn.getUserId());
         pw.println(prefix + "icon=" + iconStr);
         pw.println(prefix + "pri=" + notification.priority);
@@ -391,8 +401,11 @@ public final class NotificationRecord {
         } else {
             pw.println("null");
         }
-        pw.println(prefix + "contentView=" + notification.contentView);
-        pw.println(prefix + String.format("color=0x%08x", notification.color));
+        pw.println(prefix + "contentView=" + formatRemoteViews(notification.contentView));
+        pw.println(prefix + "bigContentView=" + formatRemoteViews(notification.bigContentView));
+        pw.println(prefix + "headsUpContentView="
+                + formatRemoteViews(notification.headsUpContentView));
+        pw.print(prefix + String.format("color=0x%08x", notification.color));
         pw.println(prefix + "timeout="
                 + TimeUtils.formatForLogging(notification.getTimeoutAfter()));
         if (notification.actions != null && notification.actions.length > 0) {
@@ -739,6 +752,37 @@ public final class NotificationRecord {
         return sbn.getGroupKey();
     }
 
+    public void setOverrideGroupKey(String overrideGroupKey) {
+        sbn.setOverrideGroupKey(overrideGroupKey);
+        mGroupLogTag = null;
+    }
+
+    private String getGroupLogTag() {
+        if (mGroupLogTag == null) {
+            mGroupLogTag = shortenTag(sbn.getGroup());
+        }
+        return mGroupLogTag;
+    }
+
+    private String getChannelIdLogTag() {
+        if (mChannelIdLogTag == null) {
+            mChannelIdLogTag = shortenTag(mChannel.getId());
+        }
+        return mChannelIdLogTag;
+    }
+
+    private String shortenTag(String longTag) {
+        if (longTag == null) {
+            return null;
+        }
+        if (longTag.length() < MAX_LOGTAG_LENGTH) {
+            return longTag;
+        } else {
+            return longTag.substring(0, MAX_LOGTAG_LENGTH - 8) + "-" +
+                    Integer.toHexString(longTag.hashCode());
+        }
+    }
+
     public boolean isImportanceFromUser() {
         return mImportance == mUserImportance;
     }
@@ -796,16 +840,23 @@ public final class NotificationRecord {
 
     public LogMaker getLogMaker(long now) {
         if (mLogMaker == null) {
+            // initialize fields that only change on update (so a new record)
             mLogMaker = new LogMaker(MetricsEvent.VIEW_UNKNOWN)
                     .setPackageName(sbn.getPackageName())
                     .addTaggedData(MetricsEvent.NOTIFICATION_ID, sbn.getId())
-                    .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag());
+                    .addTaggedData(MetricsEvent.NOTIFICATION_TAG, sbn.getTag())
+                    .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID, getChannelIdLogTag());
         }
+        // reset fields that can change between updates, or are used by multiple logs
         return mLogMaker
                 .clearCategory()
                 .clearType()
                 .clearSubtype()
                 .clearTaggedData(MetricsEvent.NOTIFICATION_SHADE_INDEX)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE, mImportance)
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID, getGroupLogTag())
+                .addTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_SUMMARY,
+                        sbn.getNotification().isGroupSummary() ? 1 : 0)
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_CREATE_MILLIS, getLifespanMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_UPDATE_MILLIS, getFreshnessMs(now))
                 .addTaggedData(MetricsEvent.NOTIFICATION_SINCE_VISIBLE_MILLIS, getExposureMs(now));
index 4c3efce..2c0cc95 100644 (file)
@@ -447,7 +447,9 @@ public class RankingHelper implements RankingConfig {
                 boolean isGroupSummary = record.getNotification().isGroupSummary();
                 record.setGlobalSortKey(
                         String.format("intrsv=%c:grnk=0x%04x:gsmry=%c:%s:rnk=0x%04x",
-                        record.isRecentlyIntrusive() ? '0' : '1',
+                        record.isRecentlyIntrusive()
+                                && record.getImportance() > NotificationManager.IMPORTANCE_MIN
+                                ? '0' : '1',
                         groupProxy.getAuthoritativeRank(),
                         isGroupSummary ? '0' : '1',
                         groupSortKeyPortion,
index ac7b763..d1aecb1 100644 (file)
@@ -936,7 +936,7 @@ final class DefaultPermissionGrantPolicy {
         // permissions if the version on the system image does not declare them.
         if (!isDefaultPhoneOrSms && pkg.isUpdatedSystemApp()) {
             PackageSetting sysPs = mService.mSettings.getDisabledSystemPkgLPr(pkg.packageName);
-            if (sysPs != null) {
+            if (sysPs != null && sysPs.pkg != null) {
                 if (sysPs.pkg.requestedPermissions.isEmpty()) {
                     return;
                 }
index e6e4617..c95b5c5 100644 (file)
@@ -395,10 +395,11 @@ public class Installer extends SystemService {
         }
     }
 
-    public void freeCache(String uuid, long freeStorageSize, int flags) throws InstallerException {
+    public void freeCache(String uuid, long targetFreeBytes, long cacheReservedBytes, int flags)
+            throws InstallerException {
         if (!checkBeforeRemote()) return;
         try {
-            mInstalld.freeCache(uuid, freeStorageSize, flags);
+            mInstalld.freeCache(uuid, targetFreeBytes, cacheReservedBytes, flags);
         } catch (Exception e) {
             throw InstallerException.from(e);
         }
index b165984..211a1c9 100644 (file)
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
 import android.annotation.UserIdInt;
 import android.content.Intent;
 import android.content.pm.InstantAppInfo;
+import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
@@ -32,6 +33,8 @@ import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
+import android.os.UserHandle;
+import android.os.storage.StorageManager;
 import android.provider.Settings;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
@@ -76,7 +79,16 @@ class InstantAppRegistry {
 
     private static final String LOG_TAG = "InstantAppRegistry";
 
-    private static final long DEFAULT_UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS =
+    static final long DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD =
+            DEBUG ? 30 * 1000L /* thirty seconds */ : 7 * 24 * 60 * 60 * 1000L; /* one week */
+
+    private static final long DEFAULT_INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD =
+            DEBUG ? 60 * 1000L /* one min */ : 6 * 30 * 24 * 60 * 60 * 1000L; /* six months */
+
+    static final long DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD =
+            DEBUG ? 30 * 1000L /* thirty seconds */ : 7 * 24 * 60 * 60 * 1000L; /* one week */
+
+    private static final long DEFAULT_UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD =
             DEBUG ? 60 * 1000L /* one min */ : 6 * 30 * 24 * 60 * 60 * 1000L; /* six months */
 
     private static final String INSTANT_APPS_FOLDER = "instant";
@@ -535,46 +547,195 @@ class InstantAppRegistry {
         }
     }
 
-    public void pruneInstantAppsLPw() {
-        // For now we prune only state for uninstalled instant apps
-        final long maxCacheDurationMillis = Settings.Global.getLong(
+    void pruneInstantApps() {
+        final long maxInstalledCacheDuration = Settings.Global.getLong(
                 mService.mContext.getContentResolver(),
-                Settings.Global.UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS,
-                DEFAULT_UNINSTALLED_INSTANT_APP_CACHE_DURATION_MILLIS);
-
-        for (int userId : UserManagerService.getInstance().getUserIds()) {
-            // Prune in-memory state
-            removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> {
-                final long elapsedCachingMillis = System.currentTimeMillis() - state.mTimestamp;
-                return (elapsedCachingMillis > maxCacheDurationMillis);
-            }, userId);
-
-            // Prune on-disk state
-            File instantAppsDir = getInstantApplicationsDir(userId);
-            if (!instantAppsDir.exists()) {
-                continue;
+                Settings.Global.INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
+                DEFAULT_INSTALLED_INSTANT_APP_MAX_CACHE_PERIOD);
+
+        final long maxUninstalledCacheDuration = Settings.Global.getLong(
+                mService.mContext.getContentResolver(),
+                Settings.Global.UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD,
+                DEFAULT_UNINSTALLED_INSTANT_APP_MAX_CACHE_PERIOD);
+
+        try {
+            pruneInstantApps(Long.MAX_VALUE,
+                    maxInstalledCacheDuration, maxUninstalledCacheDuration);
+        } catch (IOException e) {
+            Slog.e(LOG_TAG, "Error pruning installed and uninstalled instant apps", e);
+        }
+    }
+
+    boolean pruneInstalledInstantApps(long neededSpace, long maxInstalledCacheDuration) {
+        try {
+            return pruneInstantApps(neededSpace, maxInstalledCacheDuration, Long.MAX_VALUE);
+        } catch (IOException e) {
+            Slog.e(LOG_TAG, "Error pruning installed instant apps", e);
+            return false;
+        }
+    }
+
+    boolean pruneUninstalledInstantApps(long neededSpace, long maxUninstalledCacheDuration) {
+        try {
+            return pruneInstantApps(neededSpace, Long.MAX_VALUE, maxUninstalledCacheDuration);
+        } catch (IOException e) {
+            Slog.e(LOG_TAG, "Error pruning uninstalled instant apps", e);
+            return false;
+        }
+    }
+
+    /**
+     * Prunes instant apps until there is enough <code>neededSpace</code>. Both
+     * installed and uninstalled instant apps are pruned that are older than
+     * <code>maxInstalledCacheDuration</code> and <code>maxUninstalledCacheDuration</code>
+     * respectively. All times are in milliseconds.
+     *
+     * @param neededSpace The space to ensure is free.
+     * @param maxInstalledCacheDuration The max duration for caching installed apps in millis.
+     * @param maxUninstalledCacheDuration The max duration for caching uninstalled apps in millis.
+     * @return Whether enough space was freed.
+     *
+     * @throws IOException
+     */
+    private boolean pruneInstantApps(long neededSpace, long maxInstalledCacheDuration,
+            long maxUninstalledCacheDuration) throws IOException {
+        final StorageManager storage = mService.mContext.getSystemService(StorageManager.class);
+        final File file = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL);
+
+        if (file.getUsableSpace() >= neededSpace) {
+            return true;
+        }
+
+        List<String> packagesToDelete = null;
+
+        final int[] allUsers;
+        final long now = System.currentTimeMillis();
+
+        // Prune first installed instant apps
+        synchronized (mService.mPackages) {
+            allUsers = PackageManagerService.sUserManager.getUserIds();
+
+            final int packageCount = mService.mPackages.size();
+            for (int i = 0; i < packageCount; i++) {
+                final PackageParser.Package pkg = mService.mPackages.valueAt(i);
+                if (now - pkg.getLatestPackageUseTimeInMills() < maxInstalledCacheDuration) {
+                    continue;
+                }
+                if (!(pkg.mExtras instanceof PackageSetting)) {
+                    continue;
+                }
+                final PackageSetting  ps = (PackageSetting) pkg.mExtras;
+                boolean installedOnlyAsInstantApp = false;
+                for (int userId : allUsers) {
+                    if (ps.getInstalled(userId)) {
+                        if (ps.getInstantApp(userId)) {
+                            installedOnlyAsInstantApp = true;
+                        } else {
+                            installedOnlyAsInstantApp = false;
+                            break;
+                        }
+                    }
+                }
+                if (installedOnlyAsInstantApp) {
+                    if (packagesToDelete == null) {
+                        packagesToDelete = new ArrayList<>();
+                    }
+                    packagesToDelete.add(pkg.packageName);
+                }
             }
-            File[] files = instantAppsDir.listFiles();
-            if (files == null) {
-                continue;
+
+            if (packagesToDelete != null) {
+                packagesToDelete.sort((String lhs, String rhs) -> {
+                    final PackageParser.Package lhsPkg = mService.mPackages.get(lhs);
+                    final PackageParser.Package rhsPkg = mService.mPackages.get(rhs);
+                    if (lhsPkg == null && rhsPkg == null) {
+                        return 0;
+                    } else if (lhsPkg == null) {
+                        return -1;
+                    } else if (rhsPkg == null) {
+                        return 1;
+                    } else {
+                        if (lhsPkg.getLatestPackageUseTimeInMills() >
+                                rhsPkg.getLatestPackageUseTimeInMills()) {
+                            return 1;
+                        } else if (lhsPkg.getLatestPackageUseTimeInMills() <
+                                rhsPkg.getLatestPackageUseTimeInMills()) {
+                            return -1;
+                        } else {
+                            if (lhsPkg.mExtras instanceof PackageSetting
+                                    && rhsPkg.mExtras instanceof PackageSetting) {
+                                final PackageSetting lhsPs = (PackageSetting) lhsPkg.mExtras;
+                                final PackageSetting rhsPs = (PackageSetting) rhsPkg.mExtras;
+                                if (lhsPs.firstInstallTime > rhsPs.firstInstallTime) {
+                                    return 1;
+                                } else {
+                                    return -1;
+                                }
+                            } else {
+                                return 0;
+                            }
+                        }
+                    }
+                });
             }
-            for (File instantDir : files) {
-                if (!instantDir.isDirectory()) {
-                    continue;
+        }
+
+        if (packagesToDelete != null) {
+            final int packageCount = packagesToDelete.size();
+            for (int i = 0; i < packageCount; i++) {
+                final String packageToDelete = packagesToDelete.get(i);
+                if (mService.deletePackageX(packageToDelete, PackageManager.VERSION_CODE_HIGHEST,
+                        UserHandle.USER_SYSTEM, PackageManager.DELETE_ALL_USERS)
+                                == PackageManager.DELETE_SUCCEEDED) {
+                    if (file.getUsableSpace() >= neededSpace) {
+                        return true;
+                    }
                 }
+            }
+        }
 
-                File metadataFile = new File(instantDir, INSTANT_APP_METADATA_FILE);
-                if (!metadataFile.exists()) {
+        // Prune uninstalled instant apps
+        synchronized (mService.mPackages) {
+            // TODO: Track last used time for uninstalled instant apps for better pruning
+            for (int userId : UserManagerService.getInstance().getUserIds()) {
+                // Prune in-memory state
+                removeUninstalledInstantAppStateLPw((UninstalledInstantAppState state) -> {
+                    final long elapsedCachingMillis = System.currentTimeMillis() - state.mTimestamp;
+                    return (elapsedCachingMillis > maxUninstalledCacheDuration);
+                }, userId);
+
+                // Prune on-disk state
+                File instantAppsDir = getInstantApplicationsDir(userId);
+                if (!instantAppsDir.exists()) {
+                    continue;
+                }
+                File[] files = instantAppsDir.listFiles();
+                if (files == null) {
                     continue;
                 }
+                for (File instantDir : files) {
+                    if (!instantDir.isDirectory()) {
+                        continue;
+                    }
+
+                    File metadataFile = new File(instantDir, INSTANT_APP_METADATA_FILE);
+                    if (!metadataFile.exists()) {
+                        continue;
+                    }
 
-                final long elapsedCachingMillis = System.currentTimeMillis()
-                        - metadataFile.lastModified();
-                if (elapsedCachingMillis > maxCacheDurationMillis) {
-                    deleteDir(instantDir);
+                    final long elapsedCachingMillis = System.currentTimeMillis()
+                            - metadataFile.lastModified();
+                    if (elapsedCachingMillis > maxUninstalledCacheDuration) {
+                        deleteDir(instantDir);
+                        if (file.getUsableSpace() >= neededSpace) {
+                            return true;
+                        }
+                    }
                 }
             }
         }
+
+        return false;
     }
 
     private @Nullable List<InstantAppInfo> getInstalledInstantApplicationsLPr(
index 29f9f7c..4a5ce12 100644 (file)
@@ -34,6 +34,7 @@ import android.content.pm.IPackageManager;
 import android.content.pm.LauncherApps.ShortcutQuery;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.ResolveInfo;
@@ -100,7 +101,6 @@ public class LauncherAppsService extends SystemService {
         private static final boolean DEBUG = false;
         private static final String TAG = "LauncherAppsService";
         private final Context mContext;
-        private final PackageManager mPm;
         private final UserManager mUm;
         private final ActivityManagerInternal mActivityManagerInternal;
         private final ShortcutServiceInternal mShortcutServiceInternal;
@@ -113,7 +113,6 @@ public class LauncherAppsService extends SystemService {
 
         public LauncherAppsImpl(Context context) {
             mContext = context;
-            mPm = mContext.getPackageManager();
             mUm = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
             mActivityManagerInternal = Preconditions.checkNotNull(
                     LocalServices.getService(ActivityManagerInternal.class));
@@ -263,15 +262,17 @@ public class LauncherAppsService extends SystemService {
         void verifyCallingPackage(String callingPackage) {
             int packageUid = -1;
             try {
-                packageUid = mPm.getPackageUidAsUser(callingPackage,
+                packageUid = AppGlobals.getPackageManager().getPackageUid(callingPackage,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE
                                 | PackageManager.MATCH_UNINSTALLED_PACKAGES,
                         UserHandle.getUserId(getCallingUid()));
-            } catch (NameNotFoundException e) {
+            } catch (RemoteException ignore) {
+            }
+            if (packageUid < 0) {
                 Log.e(TAG, "Package not found: " + callingPackage);
             }
-            if (packageUid != Binder.getCallingUid()) {
+            if (packageUid != injectBinderCallingUid()) {
                 throw new SecurityException("Calling package name mismatch");
             }
         }
@@ -315,13 +316,15 @@ public class LauncherAppsService extends SystemService {
                 return null;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                return pm.getActivityInfo(component,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                return pmInt.getActivityInfo(component,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -344,12 +347,15 @@ public class LauncherAppsService extends SystemService {
                 return null;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = injectClearCallingIdentity();
             try {
-                List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(intent,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                List<ResolveInfo> apps = pmInt.queryIntentActivities(intent,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 return new ParceledListSlice<>(apps);
             } finally {
                 injectRestoreCallingIdentity(ident);
@@ -390,13 +396,15 @@ public class LauncherAppsService extends SystemService {
                 return false;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                PackageInfo info = pm.getPackageInfo(packageName,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                PackageInfo info = pmInt.getPackageInfo(packageName,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 return info != null && info.applicationInfo.enabled;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -414,11 +422,13 @@ public class LauncherAppsService extends SystemService {
                 return null;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                ApplicationInfo info = pm.getApplicationInfo(packageName, flags,
-                        user.getIdentifier());
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                ApplicationInfo info = pmInt.getApplicationInfo(packageName, flags,
+                        callingUid, user.getIdentifier());
                 return info;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -573,13 +583,15 @@ public class LauncherAppsService extends SystemService {
                 return false;
             }
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                ActivityInfo info = pm.getActivityInfo(component,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                ActivityInfo info = pmInt.getActivityInfo(component,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 return info != null;
             } finally {
                 Binder.restoreCallingIdentity(ident);
@@ -604,13 +616,15 @@ public class LauncherAppsService extends SystemService {
                     | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
             launchIntent.setPackage(component.getPackageName());
 
+            final int callingUid = injectBinderCallingUid();
             long ident = Binder.clearCallingIdentity();
             try {
-                IPackageManager pm = AppGlobals.getPackageManager();
-                ActivityInfo info = pm.getActivityInfo(component,
+                final PackageManagerInternal pmInt =
+                        LocalServices.getService(PackageManagerInternal.class);
+                ActivityInfo info = pmInt.getActivityInfo(component,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 if (!info.exported) {
                     throw new SecurityException("Cannot launch non-exported components "
                             + component);
@@ -619,10 +633,10 @@ public class LauncherAppsService extends SystemService {
                 // Check that the component actually has Intent.CATEGORY_LAUCNCHER
                 // as calling startActivityAsUser ignores the category and just
                 // resolves based on the component if present.
-                List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(launchIntent,
+                List<ResolveInfo> apps = pmInt.queryIntentActivities(launchIntent,
                         PackageManager.MATCH_DIRECT_BOOT_AWARE
                                 | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                        user.getIdentifier());
+                        callingUid, user.getIdentifier());
                 final int size = apps.size();
                 for (int i = 0; i < size; ++i) {
                     ActivityInfo activityInfo = apps.get(i).activityInfo;
index 782325a..e62b107 100644 (file)
@@ -875,9 +875,9 @@ public class PackageManagerService extends IPackageManager.Stub
             new ParallelPackageParserCallback();
 
     public static final class SharedLibraryEntry {
-        public final String path;
-        public final String apk;
-        public final SharedLibraryInfo info;
+        public final @Nullable String path;
+        public final @Nullable String apk;
+        public final @NonNull SharedLibraryInfo info;
 
         SharedLibraryEntry(String _path, String _apk, String name, int version, int type,
                 String declaringPackageName, int declaringPackageVersionCode) {
@@ -1312,6 +1312,9 @@ public class PackageManagerService extends IPackageManager.Stub
     // Delay time in millisecs
     static final int BROADCAST_DELAY = 10 * 1000;
 
+    private static final long DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD =
+            2 * 60 * 60 * 1000L; /* two hours */
+
     static UserManagerService sUserManager;
 
     // Stores a list of users whose package restrictions file needs to be updated
@@ -2183,12 +2186,12 @@ public class PackageManagerService extends IPackageManager.Stub
 
     private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
             String[] grantedPermissions) {
-        SettingBase sb = (SettingBase) pkg.mExtras;
-        if (sb == null) {
+        PackageSetting ps = (PackageSetting) pkg.mExtras;
+        if (ps == null) {
             return;
         }
 
-        PermissionsState permissionsState = sb.getPermissionsState();
+        PermissionsState permissionsState = ps.getPermissionsState();
 
         final int immutableFlags = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
                 | PackageManager.FLAG_PERMISSION_POLICY_FIXED;
@@ -3513,7 +3516,7 @@ public class PackageManagerService extends IPackageManager.Stub
      *     and {@code 0}</li>
      * <li>The calling application has the permission
      *     {@link android.Manifest.permission#ACCESS_INSTANT_APPS}</li>
-     * <li>[TODO] The calling application is the default launcher on the
+     * <li>The calling application is the default launcher on the
      *     system partition.</li>
      * </ol>
      */
@@ -3590,13 +3593,14 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public void checkPackageStartable(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             throw new SecurityException("Instant applications don't have access to this method");
         }
         final boolean userKeyUnlocked = StorageManager.isUserKeyUnlocked(userId);
         synchronized (mPackages) {
             final PackageSetting ps = mSettings.mPackages.get(packageName);
-            if (ps == null) {
+            if (ps == null || filterAppAccessLPr(ps, callingUid, userId)) {
                 throw new SecurityException("Package " + packageName + " was not found!");
             }
 
@@ -3647,22 +3651,27 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public PackageInfo getPackageInfo(String packageName, int flags, int userId) {
         return getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
-                flags, userId);
+                flags, Binder.getCallingUid(), userId);
     }
 
     @Override
     public PackageInfo getPackageInfoVersioned(VersionedPackage versionedPackage,
             int flags, int userId) {
         return getPackageInfoInternal(versionedPackage.getPackageName(),
-                versionedPackage.getVersionCode(), flags, userId);
+                versionedPackage.getVersionCode(), flags, Binder.getCallingUid(), userId);
     }
 
+    /**
+     * Important: The provided filterCallingUid is used exclusively to filter out packages
+     * that can be seen based on user state. It's typically the original caller uid prior
+     * to clearing. Because it can only be provided by trusted code, it's value can be
+     * trusted and will be used as-is; unlike userId which will be validated by this method.
+     */
     private PackageInfo getPackageInfoInternal(String packageName, int versionCode,
-            int flags, int userId) {
+            int flags, int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForPackage(flags, userId, packageName);
-        enforceCrossUserPermission(callingUid, userId,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */, "get package info");
 
         // reader
@@ -3674,10 +3683,10 @@ public class PackageManagerService extends IPackageManager.Stub
             if (matchFactoryOnly) {
                 final PackageSetting ps = mSettings.getDisabledSystemPkgLPr(packageName);
                 if (ps != null) {
-                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                    if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                         return null;
                     }
-                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                         return null;
                     }
                     return generatePackageInfo(ps, flags, userId);
@@ -3692,10 +3701,10 @@ public class PackageManagerService extends IPackageManager.Stub
                 Log.v(TAG, "getPackageInfo " + packageName + ": " + p);
             if (p != null) {
                 final PackageSetting ps = (PackageSetting) p.mExtras;
-                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                     return null;
                 }
-                if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
+                if (ps != null && filterAppAccessLPr(ps, filterCallingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo((PackageSetting)p.mExtras, flags, userId);
@@ -3703,10 +3712,10 @@ public class PackageManagerService extends IPackageManager.Stub
             if (!matchFactoryOnly && (flags & MATCH_KNOWN_PACKAGES) != 0) {
                 final PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
-                if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
+                if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                     return null;
                 }
-                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                     return null;
                 }
                 return generatePackageInfo(ps, flags, userId);
@@ -3865,15 +3874,26 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public String[] currentToCanonicalPackageNames(String[] names) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return names;
         }
-        String[] out = new String[names.length];
+        final String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
             for (int i=names.length-1; i>=0; i--) {
-                PackageSetting ps = mSettings.mPackages.get(names[i]);
-                out[i] = ps != null && ps.realName != null ? ps.realName : names[i];
+                final PackageSetting ps = mSettings.mPackages.get(names[i]);
+                boolean translateName = false;
+                if (ps != null && ps.realName != null) {
+                    final boolean targetIsInstantApp = ps.getInstantApp(callingUserId);
+                    translateName = !targetIsInstantApp
+                            || canViewInstantApps
+                            || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+                                    UserHandle.getAppId(callingUid), ps.appId);
+                }
+                out[i] = translateName ? ps.realName : names[i];
             }
         }
         return out;
@@ -3881,15 +3901,28 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public String[] canonicalToCurrentPackageNames(String[] names) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return names;
         }
-        String[] out = new String[names.length];
+        final String[] out = new String[names.length];
         // reader
         synchronized (mPackages) {
+            final int callingUserId = UserHandle.getUserId(callingUid);
+            final boolean canViewInstantApps = canViewInstantApps(callingUid, callingUserId);
             for (int i=names.length-1; i>=0; i--) {
-                String cur = mSettings.getRenamedPackageLPr(names[i]);
-                out[i] = cur != null ? cur : names[i];
+                final String cur = mSettings.getRenamedPackageLPr(names[i]);
+                boolean translateName = false;
+                if (cur != null) {
+                    final PackageSetting ps = mSettings.mPackages.get(names[i]);
+                    final boolean targetIsInstantApp =
+                            ps != null && ps.getInstantApp(callingUserId);
+                    translateName = !targetIsInstantApp
+                            || canViewInstantApps
+                            || mInstantAppRegistry.isInstantAccessGranted(callingUserId,
+                                    UserHandle.getAppId(callingUid), ps.appId);
+                }
+                out[i] = translateName ? cur : names[i];
             }
         }
         return out;
@@ -4043,14 +4076,14 @@ public class PackageManagerService extends IPackageManager.Stub
     }
 
     private ApplicationInfo generateApplicationInfoFromSettingsLPw(String packageName, int flags,
-            int uid, int userId) {
+            int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
         PackageSetting ps = mSettings.mPackages.get(packageName);
         if (ps != null) {
-            if (filterSharedLibPackageLPr(ps, uid, userId, flags)) {
+            if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                 return null;
             }
-            if (filterAppAccessLPr(ps, uid, userId)) {
+            if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                 return null;
             }
             if (ps.pkg == null) {
@@ -4073,6 +4106,17 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public ApplicationInfo getApplicationInfo(String packageName, int flags, int userId) {
+        return getApplicationInfoInternal(packageName, flags, Binder.getCallingUid(), userId);
+    }
+
+    /**
+     * Important: The provided filterCallingUid is used exclusively to filter out applications
+     * that can be seen based on user state. It's typically the original caller uid prior
+     * to clearing. Because it can only be provided by trusted code, it's value can be
+     * trusted and will be used as-is; unlike userId which will be validated by this method.
+     */
+    private ApplicationInfo getApplicationInfoInternal(String packageName, int flags,
+            int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForApplication(flags, userId, packageName);
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
@@ -4091,10 +4135,10 @@ public class PackageManagerService extends IPackageManager.Stub
             if (p != null) {
                 PackageSetting ps = mSettings.mPackages.get(packageName);
                 if (ps == null) return null;
-                if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                if (filterSharedLibPackageLPr(ps, filterCallingUid, userId, flags)) {
                     return null;
                 }
-                if (filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                if (filterAppAccessLPr(ps, filterCallingUid, userId)) {
                     return null;
                 }
                 // Note: isEnabledLP() does not apply here - always return info
@@ -4112,7 +4156,7 @@ public class PackageManagerService extends IPackageManager.Stub
             if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
                 // Already generates the external package name
                 return generateApplicationInfoFromSettingsLPw(packageName,
-                        Binder.getCallingUid(), flags, userId);
+                        flags, filterCallingUid, userId);
             }
         }
         return null;
@@ -4155,13 +4199,13 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public void freeStorageAndNotify(final String volumeUuid, final long freeStorageSize,
-            final IPackageDataObserver observer) {
+            final int storageFlags, final IPackageDataObserver observer) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_CACHE, null);
         mHandler.post(() -> {
             boolean success = false;
             try {
-                freeStorage(volumeUuid, freeStorageSize, 0);
+                freeStorage(volumeUuid, freeStorageSize, storageFlags);
                 success = true;
             } catch (IOException e) {
                 Slog.w(TAG, e);
@@ -4178,13 +4222,13 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public void freeStorage(final String volumeUuid, final long freeStorageSize,
-            final IntentSender pi) {
+            final int storageFlags, final IntentSender pi) {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_CACHE, TAG);
         mHandler.post(() -> {
             boolean success = false;
             try {
-                freeStorage(volumeUuid, freeStorageSize, 0);
+                freeStorage(volumeUuid, freeStorageSize, storageFlags);
                 success = true;
             } catch (IOException e) {
                 Slog.w(TAG, e);
@@ -4209,10 +4253,14 @@ public class PackageManagerService extends IPackageManager.Stub
         if (file.getUsableSpace() >= bytes) return;
 
         if (ENABLE_FREE_CACHE_V2) {
-            final boolean aggressive = (storageFlags
-                    & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0;
             final boolean internalVolume = Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL,
                     volumeUuid);
+            final boolean aggressive = (storageFlags
+                    & StorageManager.FLAG_ALLOCATE_AGGRESSIVE) != 0;
+            final boolean defyReserved = (storageFlags
+                    & StorageManager.FLAG_ALLOCATE_DEFY_RESERVED) != 0;
+            final long reservedBytes = (aggressive || defyReserved) ? 0
+                    : storage.getStorageCacheBytes(file);
 
             // 1. Pre-flight to determine if we have any chance to succeed
             // 2. Consider preloaded data (after 1w honeymoon, unless aggressive)
@@ -4230,29 +4278,52 @@ public class PackageManagerService extends IPackageManager.Stub
 
             // 4. Consider cached app data (above quotas)
             try {
-                mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2);
+                mInstaller.freeCache(volumeUuid, bytes, reservedBytes,
+                        Installer.FLAG_FREE_CACHE_V2);
             } catch (InstallerException ignored) {
             }
             if (file.getUsableSpace() >= bytes) return;
 
-            // 5. Consider shared libraries with refcount=0 and age>2h
+            // 5. Consider shared libraries with refcount=0 and age>min cache period
+            if (internalVolume && pruneUnusedStaticSharedLibraries(bytes,
+                    android.provider.Settings.Global.getLong(mContext.getContentResolver(),
+                            Global.UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD,
+                            DEFAULT_UNUSED_STATIC_SHARED_LIB_MIN_CACHE_PERIOD))) {
+                return;
+            }
+
             // 6. Consider dexopt output (aggressive only)
-            // 7. Consider ephemeral apps not used in last week
+            // TODO: Implement
+
+            // 7. Consider installed instant apps unused longer than min cache period
+            if (internalVolume && mInstantAppRegistry.pruneInstalledInstantApps(bytes,
+                    android.provider.Settings.Global.getLong(mContext.getContentResolver(),
+                            Global.INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                            InstantAppRegistry.DEFAULT_INSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
+                return;
+            }
 
             // 8. Consider cached app data (below quotas)
             try {
-                mInstaller.freeCache(volumeUuid, bytes, Installer.FLAG_FREE_CACHE_V2
-                        | Installer.FLAG_FREE_CACHE_V2_DEFY_QUOTA);
+                mInstaller.freeCache(volumeUuid, bytes, reservedBytes,
+                        Installer.FLAG_FREE_CACHE_V2 | Installer.FLAG_FREE_CACHE_V2_DEFY_QUOTA);
             } catch (InstallerException ignored) {
             }
             if (file.getUsableSpace() >= bytes) return;
 
             // 9. Consider DropBox entries
-            // 10. Consider ephemeral cookies
+            // TODO: Implement
 
+            // 10. Consider instant meta-data (uninstalled apps) older that min cache period
+            if (internalVolume && mInstantAppRegistry.pruneUninstalledInstantApps(bytes,
+                    android.provider.Settings.Global.getLong(mContext.getContentResolver(),
+                            Global.UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD,
+                            InstantAppRegistry.DEFAULT_UNINSTALLED_INSTANT_APP_MIN_CACHE_PERIOD))) {
+                return;
+            }
         } else {
             try {
-                mInstaller.freeCache(volumeUuid, bytes, 0);
+                mInstaller.freeCache(volumeUuid, bytes, 0, 0);
             } catch (InstallerException ignored) {
             }
             if (file.getUsableSpace() >= bytes) return;
@@ -4261,6 +4332,69 @@ public class PackageManagerService extends IPackageManager.Stub
         throw new IOException("Failed to free " + bytes + " on storage device at " + file);
     }
 
+    private boolean pruneUnusedStaticSharedLibraries(long neededSpace, long maxCachePeriod)
+            throws IOException {
+        final StorageManager storage = mContext.getSystemService(StorageManager.class);
+        final File volume = storage.findPathForUuid(StorageManager.UUID_PRIVATE_INTERNAL);
+
+        List<VersionedPackage> packagesToDelete = null;
+        final long now = System.currentTimeMillis();
+
+        synchronized (mPackages) {
+            final int[] allUsers = sUserManager.getUserIds();
+            final int libCount = mSharedLibraries.size();
+            for (int i = 0; i < libCount; i++) {
+                final SparseArray<SharedLibraryEntry> versionedLib = mSharedLibraries.valueAt(i);
+                if (versionedLib == null) {
+                    continue;
+                }
+                final int versionCount = versionedLib.size();
+                for (int j = 0; j < versionCount; j++) {
+                    SharedLibraryInfo libInfo = versionedLib.valueAt(j).info;
+                    // Skip packages that are not static shared libs.
+                    if (!libInfo.isStatic()) {
+                        break;
+                    }
+                    // Important: We skip static shared libs used for some user since
+                    // in such a case we need to keep the APK on the device. The check for
+                    // a lib being used for any user is performed by the uninstall call.
+                    final VersionedPackage declaringPackage = libInfo.getDeclaringPackage();
+                    // Resolve the package name - we use synthetic package names internally
+                    final String internalPackageName = resolveInternalPackageNameLPr(
+                            declaringPackage.getPackageName(), declaringPackage.getVersionCode());
+                    final PackageSetting ps = mSettings.getPackageLPr(internalPackageName);
+                    // Skip unused static shared libs cached less than the min period
+                    // to prevent pruning a lib needed by a subsequently installed package.
+                    if (ps == null || now - ps.lastUpdateTime < maxCachePeriod) {
+                        continue;
+                    }
+                    if (packagesToDelete == null) {
+                        packagesToDelete = new ArrayList<>();
+                    }
+                    packagesToDelete.add(new VersionedPackage(internalPackageName,
+                            declaringPackage.getVersionCode()));
+                }
+            }
+        }
+
+        if (packagesToDelete != null) {
+            final int packageCount = packagesToDelete.size();
+            for (int i = 0; i < packageCount; i++) {
+                final VersionedPackage pkgToDelete = packagesToDelete.get(i);
+                // Delete the package synchronously (will fail of the lib used for any user).
+                if (deletePackageX(pkgToDelete.getPackageName(), pkgToDelete.getVersionCode(),
+                        UserHandle.USER_SYSTEM, PackageManager.DELETE_ALL_USERS)
+                                == PackageManager.DELETE_SUCCEEDED) {
+                    if (volume.getUsableSpace() >= neededSpace) {
+                        return true;
+                    }
+                }
+            }
+        }
+
+        return false;
+    }
+
     /**
      * Update given flags based on encryption status of current user.
      */
@@ -4452,10 +4586,20 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public ActivityInfo getActivityInfo(ComponentName component, int flags, int userId) {
+        return getActivityInfoInternal(component, flags, Binder.getCallingUid(), userId);
+    }
+
+    /**
+     * Important: The provided filterCallingUid is used exclusively to filter out activities
+     * that can be seen based on user state. It's typically the original caller uid prior
+     * to clearing. Because it can only be provided by trusted code, it's value can be
+     * trusted and will be used as-is; unlike userId which will be validated by this method.
+     */
+    private ActivityInfo getActivityInfoInternal(ComponentName component, int flags,
+            int filterCallingUid, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        final int callingUid = Binder.getCallingUid();
         flags = updateFlagsForComponent(flags, userId, component);
-        enforceCrossUserPermission(callingUid, userId,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */, "get activity info");
         synchronized (mPackages) {
             PackageParser.Activity a = mActivities.mActivities.get(component);
@@ -4464,7 +4608,7 @@ public class PackageManagerService extends IPackageManager.Stub
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
                 PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
                 if (ps == null) return null;
-                if (filterAppAccessLPr(ps, callingUid, component, TYPE_ACTIVITY, userId)) {
+                if (filterAppAccessLPr(ps, filterCallingUid, component, TYPE_ACTIVITY, userId)) {
                     return null;
                 }
                 return generateActivityInfo(a, flags, ps.readUserState(userId), userId);
@@ -4760,9 +4904,13 @@ public class PackageManagerService extends IPackageManager.Stub
         }
     }
 
-    private void updateSequenceNumberLP(String packageName, int[] userList) {
+    private void updateSequenceNumberLP(PackageSetting pkgSetting, int[] userList) {
         for (int i = userList.length - 1; i >= 0; --i) {
             final int userId = userList[i];
+            // don't add instant app to the list of updates
+            if (pkgSetting.getInstantApp(userId)) {
+                continue;
+            }
             SparseArray<String> changedPackages = mChangedPackages.get(userId);
             if (changedPackages == null) {
                 changedPackages = new SparseArray<>();
@@ -4773,12 +4921,12 @@ public class PackageManagerService extends IPackageManager.Stub
                 sequenceNumbers = new HashMap<>();
                 mChangedPackagesSequenceNumbers.put(userId, sequenceNumbers);
             }
-            final Integer sequenceNumber = sequenceNumbers.get(packageName);
+            final Integer sequenceNumber = sequenceNumbers.get(pkgSetting.name);
             if (sequenceNumber != null) {
                 changedPackages.remove(sequenceNumber);
             }
-            changedPackages.put(mChangedPackagesSequenceNumber, packageName);
-            sequenceNumbers.put(packageName, mChangedPackagesSequenceNumber);
+            changedPackages.put(mChangedPackagesSequenceNumber, pkgSetting.name);
+            sequenceNumbers.put(pkgSetting.name, mChangedPackagesSequenceNumber);
         }
         mChangedPackagesSequenceNumber++;
     }
@@ -5209,28 +5357,33 @@ public class PackageManagerService extends IPackageManager.Stub
             Log.e(TAG, "No such user:" + userId);
             return;
         }
+        final int callingUid = Binder.getCallingUid();
 
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
                 "grantRuntimePermission");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "grantRuntimePermission");
 
         final int uid;
-        final SettingBase sb;
+        final PackageSetting ps;
 
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
-
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + name);
             }
+            ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, userId)) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
 
             enforceDeclaredAsUsedAndRuntimeOrDevelopmentPermission(pkg, bp);
 
@@ -5245,12 +5398,8 @@ public class PackageManagerService extends IPackageManager.Stub
             }
 
             uid = UserHandle.getUid(userId, pkg.applicationInfo.uid);
-            sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
-                throw new IllegalArgumentException("Unknown package: " + packageName);
-            }
 
-            final PermissionsState permissionsState = sb.getPermissionsState();
+            final PermissionsState permissionsState = ps.getPermissionsState();
 
             final int flags = permissionsState.getPermissionFlags(name, userId);
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
@@ -5272,7 +5421,6 @@ public class PackageManagerService extends IPackageManager.Stub
                 return;
             }
 
-            final PackageSetting ps = mSettings.mPackages.get(packageName);
             if (ps.getInstantApp(userId) && !bp.isInstant()) {
                 throw new SecurityException("Cannot grant non-ephemeral permission"
                         + name + " for package " + packageName);
@@ -5356,7 +5504,11 @@ public class PackageManagerService extends IPackageManager.Stub
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
-
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + name);
@@ -5374,12 +5526,7 @@ public class PackageManagerService extends IPackageManager.Stub
                 return;
             }
 
-            SettingBase sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
-                throw new IllegalArgumentException("Unknown package: " + packageName);
-            }
-
-            final PermissionsState permissionsState = sb.getPermissionsState();
+            final PermissionsState permissionsState = ps.getPermissionsState();
 
             final int flags = permissionsState.getPermissionFlags(name, userId);
             if ((flags & PackageManager.FLAG_PERMISSION_SYSTEM_FIXED) != 0) {
@@ -5518,7 +5665,8 @@ public class PackageManagerService extends IPackageManager.Stub
 
         enforceGrantRevokeRuntimePermissionPermissions("getPermissionFlags");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "getPermissionFlags");
 
@@ -5527,18 +5675,16 @@ public class PackageManagerService extends IPackageManager.Stub
             if (pkg == null) {
                 return 0;
             }
-
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 return 0;
             }
-
-            SettingBase sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, userId)) {
                 return 0;
             }
-
-            PermissionsState permissionsState = sb.getPermissionsState();
+            PermissionsState permissionsState = ps.getPermissionsState();
             return permissionsState.getPermissionFlags(name, userId);
         }
     }
@@ -5552,7 +5698,8 @@ public class PackageManagerService extends IPackageManager.Stub
 
         enforceGrantRevokeRuntimePermissionPermissions("updatePermissionFlags");
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "updatePermissionFlags");
 
@@ -5570,18 +5717,18 @@ public class PackageManagerService extends IPackageManager.Stub
             if (pkg == null) {
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, userId)) {
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
 
             final BasePermission bp = mSettings.mPermissions.get(name);
             if (bp == null) {
                 throw new IllegalArgumentException("Unknown permission: " + name);
             }
 
-            SettingBase sb = (SettingBase) pkg.mExtras;
-            if (sb == null) {
-                throw new IllegalArgumentException("Unknown package: " + packageName);
-            }
-
-            PermissionsState permissionsState = sb.getPermissionsState();
+            PermissionsState permissionsState = ps.getPermissionsState();
 
             boolean hadState = permissionsState.getRuntimePermissionState(name, userId) != null;
 
@@ -5625,11 +5772,11 @@ public class PackageManagerService extends IPackageManager.Stub
             final int packageCount = mPackages.size();
             for (int pkgIndex = 0; pkgIndex < packageCount; pkgIndex++) {
                 final PackageParser.Package pkg = mPackages.valueAt(pkgIndex);
-                SettingBase sb = (SettingBase) pkg.mExtras;
-                if (sb == null) {
+                final PackageSetting ps = (PackageSetting) pkg.mExtras;
+                if (ps == null) {
                     continue;
                 }
-                PermissionsState permissionsState = sb.getPermissionsState();
+                PermissionsState permissionsState = ps.getPermissionsState();
                 changed |= permissionsState.updatePermissionFlagsForAllPermissions(
                         userId, flagMask, flagValues);
             }
@@ -6078,7 +6225,8 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public int getFlagsForUid(int uid) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
         synchronized (mPackages) {
@@ -6088,6 +6236,9 @@ public class PackageManagerService extends IPackageManager.Stub
                 return sus.pkgFlags;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
+                if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                    return 0;
+                }
                 return ps.pkgFlags;
             }
         }
@@ -6096,7 +6247,8 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public int getPrivateFlagsForUid(int uid) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return 0;
         }
         synchronized (mPackages) {
@@ -6106,6 +6258,9 @@ public class PackageManagerService extends IPackageManager.Stub
                 return sus.pkgPrivateFlags;
             } else if (obj instanceof PackageSetting) {
                 final PackageSetting ps = (PackageSetting) obj;
+                if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                    return 0;
+                }
                 return ps.pkgPrivateFlags;
             }
         }
@@ -6171,7 +6326,7 @@ public class PackageManagerService extends IPackageManager.Stub
 
             Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "queryIntentActivities");
             final List<ResolveInfo> query = queryIntentActivitiesInternal(intent, resolvedType,
-                    flags, userId, resolveForStart);
+                    flags, callingUid, userId, resolveForStart);
             Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
 
             final ResolveInfo bestChoice =
@@ -6715,15 +6870,16 @@ public class PackageManagerService extends IPackageManager.Stub
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
             String resolvedType, int flags, int userId) {
-        return queryIntentActivitiesInternal(intent, resolvedType, flags, userId, false);
+        return queryIntentActivitiesInternal(
+                intent, resolvedType, flags, Binder.getCallingUid(), userId, false);
     }
 
     private @NonNull List<ResolveInfo> queryIntentActivitiesInternal(Intent intent,
-            String resolvedType, int flags, int userId, boolean resolveForStart) {
+            String resolvedType, int flags, int filterCallingUid, int userId,
+            boolean resolveForStart) {
         if (!sUserManager.exists(userId)) return Collections.emptyList();
-        final int callingUid = Binder.getCallingUid();
-        final String instantAppPkgName = getInstantAppPackageName(callingUid);
-        enforceCrossUserPermission(callingUid, userId,
+        final String instantAppPkgName = getInstantAppPackageName(filterCallingUid);
+        enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 false /* requireFullPermission */, false /* checkShell */,
                 "query intent activities");
         final String pkgName = intent.getPackage();
@@ -6735,7 +6891,7 @@ public class PackageManagerService extends IPackageManager.Stub
             }
         }
 
-        flags = updateFlagsForResolve(flags, userId, intent, callingUid, resolveForStart,
+        flags = updateFlagsForResolve(flags, userId, intent, filterCallingUid, resolveForStart,
                 comp != null || pkgName != null /*onlyExposedExplicitly*/);
         if (comp != null) {
             final List<ResolveInfo> list = new ArrayList<ResolveInfo>(1);
@@ -7955,13 +8111,14 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public ParceledListSlice<PackageInfo> getInstalledPackages(int flags, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForPackage(flags, userId, null);
         final boolean listUninstalled = (flags & MATCH_KNOWN_PACKAGES) != 0;
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "get installed packages");
 
@@ -7971,9 +8128,12 @@ public class PackageManagerService extends IPackageManager.Stub
             if (listUninstalled) {
                 list = new ArrayList<>(mSettings.mPackages.size());
                 for (PackageSetting ps : mSettings.mPackages.values()) {
-                    if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                         continue;
                     }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                        return null;
+                    }
                     final PackageInfo pi = generatePackageInfo(ps, flags, userId);
                     if (pi != null) {
                         list.add(pi);
@@ -7982,10 +8142,13 @@ public class PackageManagerService extends IPackageManager.Stub
             } else {
                 list = new ArrayList<>(mPackages.size());
                 for (PackageParser.Package p : mPackages.values()) {
-                    if (filterSharedLibPackageLPr((PackageSetting) p.mExtras,
-                            Binder.getCallingUid(), userId, flags)) {
+                    final PackageSetting ps = (PackageSetting) p.mExtras;
+                    if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                         continue;
                     }
+                    if (filterAppAccessLPr(ps, callingUid, userId)) {
+                        return null;
+                    }
                     final PackageInfo pi = generatePackageInfo((PackageSetting)
                             p.mExtras, flags, userId);
                     if (pi != null) {
@@ -8072,7 +8235,8 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public ParceledListSlice<ApplicationInfo> getInstalledApplications(int flags, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
@@ -8091,9 +8255,12 @@ public class PackageManagerService extends IPackageManager.Stub
                         effectiveFlags |= PackageManager.MATCH_ANY_USER;
                     }
                     if (ps.pkg != null) {
-                        if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
+                        if (filterSharedLibPackageLPr(ps, callingUid, userId, flags)) {
                             continue;
                         }
+                        if (filterAppAccessLPr(ps, callingUid, userId)) {
+                            return null;
+                        }
                         ai = PackageParser.generateApplicationInfo(ps.pkg, effectiveFlags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
@@ -8104,7 +8271,7 @@ public class PackageManagerService extends IPackageManager.Stub
                         // Shared lib filtering done in generateApplicationInfoFromSettingsLPw
                         // and already converts to externally visible package name
                         ai = generateApplicationInfoFromSettingsLPw(ps.name,
-                                Binder.getCallingUid(), effectiveFlags, userId);
+                                callingUid, effectiveFlags, userId);
                     }
                     if (ai != null) {
                         list.add(ai);
@@ -8118,6 +8285,9 @@ public class PackageManagerService extends IPackageManager.Stub
                         if (filterSharedLibPackageLPr(ps, Binder.getCallingUid(), userId, flags)) {
                             continue;
                         }
+                        if (filterAppAccessLPr(ps, callingUid, userId)) {
+                            return null;
+                        }
                         ApplicationInfo ai = PackageParser.generateApplicationInfo(p, flags,
                                 ps.readUserState(userId), userId);
                         if (ai != null) {
@@ -9255,6 +9425,11 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public boolean performDexOpt(String packageName,
             boolean checkProfiles, int compileReason, boolean force) {
+        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+            return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
+        }
         return performDexOptWithStatus(packageName, checkProfiles, compileReason, force) !=
                 PackageDexOptimizer.DEX_OPT_FAILED;
     }
@@ -9276,6 +9451,8 @@ public class PackageManagerService extends IPackageManager.Stub
             boolean checkProfiles, String targetCompilerFilter, boolean force) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
         }
         int dexOptStatus = performDexOptTraced(packageName, checkProfiles,
                 targetCompilerFilter, force);
@@ -9372,6 +9549,8 @@ public class PackageManagerService extends IPackageManager.Stub
             boolean force) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return false;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return false;
         }
         mDexManager.reconcileSecondaryDexFiles(packageName);
         return mDexManager.dexoptSecondaryDex(packageName, compilerFilter, force);
@@ -9391,6 +9570,8 @@ public class PackageManagerService extends IPackageManager.Stub
     public void reconcileSecondaryDexFiles(String packageName) {
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return;
+        } else if (isInstantApp(packageName, UserHandle.getCallingUserId())) {
+            return;
         }
         mDexManager.reconcileSecondaryDexFiles(packageName);
     }
@@ -10650,8 +10831,7 @@ public class PackageManagerService extends IPackageManager.Stub
                     final int versionCount = versionedLib.size();
                     for (int i = 0; i < versionCount; i++) {
                         SharedLibraryInfo libInfo = versionedLib.valueAt(i).info;
-                        // TODO: We will change version code to long, so in the new API it is long
-                        final int libVersionCode = (int) libInfo.getDeclaringPackage()
+                        final int libVersionCode = libInfo.getDeclaringPackage()
                                 .getVersionCode();
                         if (libInfo.getVersion() <  pkg.staticSharedLibVersion) {
                             minVersionCode = Math.max(minVersionCode, libVersionCode + 1);
@@ -14169,8 +14349,8 @@ public class PackageManagerService extends IPackageManager.Stub
             int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
         PackageSetting pkgSetting;
-        final int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "setApplicationHiddenSetting for user " + userId);
 
@@ -14189,6 +14369,9 @@ public class PackageManagerService extends IPackageManager.Stub
                 if (pkgSetting == null) {
                     return false;
                 }
+                if (filterAppAccessLPr(pkgSetting, callingUid, userId)) {
+                    return false;
+                }
                 // Do not allow "android" is being disabled
                 if ("android".equals(packageName)) {
                     Slog.w(TAG, "Cannot hide package: android");
@@ -14205,7 +14388,7 @@ public class PackageManagerService extends IPackageManager.Stub
                     return false;
                 }
                 // Only allow protected packages to hide themselves.
-                if (hidden && !UserHandle.isSameApp(uid, pkgSetting.appId)
+                if (hidden && !UserHandle.isSameApp(callingUid, pkgSetting.appId)
                         && mProtectedPackages.isPackageStateProtected(userId, packageName)) {
                     Slog.w(TAG, "Not hiding protected package: " + packageName);
                     return false;
@@ -14268,19 +14451,23 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public boolean getApplicationHiddenSettingAsUser(String packageName, int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */,
                 "getApplicationHidden for user " + userId);
-        PackageSetting pkgSetting;
+        PackageSetting ps;
         long callingId = Binder.clearCallingIdentity();
         try {
             // writer
             synchronized (mPackages) {
-                pkgSetting = mSettings.mPackages.get(packageName);
-                if (pkgSetting == null) {
+                ps = mSettings.mPackages.get(packageName);
+                if (ps == null) {
                     return true;
                 }
-                return pkgSetting.getHidden(userId);
+                if (filterAppAccessLPr(ps, callingUid, userId)) {
+                    return true;
+                }
+                return ps.getHidden(userId);
             }
         } finally {
             Binder.restoreCallingIdentity(callingId);
@@ -14296,8 +14483,8 @@ public class PackageManagerService extends IPackageManager.Stub
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
                 null);
         PackageSetting pkgSetting;
-        final int uid = Binder.getCallingUid();
-        enforceCrossUserPermission(uid, userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "installExistingPackage for user " + userId);
         if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
@@ -14318,6 +14505,20 @@ public class PackageManagerService extends IPackageManager.Stub
                 if (pkgSetting == null) {
                     return PackageManager.INSTALL_FAILED_INVALID_URI;
                 }
+                if (!canViewInstantApps(callingUid, UserHandle.getUserId(callingUid))) {
+                    // only allow the existing package to be used if it's installed as a full
+                    // application for at least one user
+                    boolean installAllowed = false;
+                    for (int checkUserId : sUserManager.getUserIds()) {
+                        installAllowed = !pkgSetting.getInstantApp(checkUserId);
+                        if (installAllowed) {
+                            break;
+                        }
+                    }
+                    if (!installAllowed) {
+                        return PackageManager.INSTALL_FAILED_INVALID_URI;
+                    }
+                }
                 if (!pkgSetting.getInstalled(userId)) {
                     pkgSetting.setInstalled(true, userId);
                     pkgSetting.setHidden(false, userId);
@@ -14341,7 +14542,7 @@ public class PackageManagerService extends IPackageManager.Stub
                 }
                 sendPackageAddedForUser(packageName, pkgSetting, userId);
                 synchronized (mPackages) {
-                    updateSequenceNumberLP(packageName, new int[]{ userId });
+                    updateSequenceNumberLP(pkgSetting, new int[]{ userId });
                 }
             }
         } finally {
@@ -14387,7 +14588,8 @@ public class PackageManagerService extends IPackageManager.Stub
     public String[] setPackagesSuspendedAsUser(String[] packageNames, boolean suspended,
             int userId) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MANAGE_USERS, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, true /* checkShell */,
                 "setPackagesSuspended for user " + userId);
 
@@ -14408,7 +14610,8 @@ public class PackageManagerService extends IPackageManager.Stub
                 final int appId;
                 synchronized (mPackages) {
                     final PackageSetting pkgSetting = mSettings.mPackages.get(packageName);
-                    if (pkgSetting == null) {
+                    if (pkgSetting == null
+                            || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
                         Slog.w(TAG, "Could not find package setting for package \"" + packageName
                                 + "\". Skipping suspending/un-suspending.");
                         unactionedPackages.add(packageName);
@@ -14732,7 +14935,7 @@ public class PackageManagerService extends IPackageManager.Stub
      *
      * @return true if verification should be performed
      */
-    private boolean isVerificationEnabled(int userId, int installFlags) {
+    private boolean isVerificationEnabled(int userId, int installFlags, int installerUid) {
         if (!DEFAULT_VERIFY_ENABLE) {
             return false;
         }
@@ -14753,6 +14956,23 @@ public class PackageManagerService extends IPackageManager.Stub
                     android.provider.Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) == 0) {
                 return false;
             }
+        } else {
+            // only when not installed from ADB, skip verification for instant apps when
+            // the installer and verifier are the same.
+            if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
+                if (mInstantAppInstallerActivity != null
+                        && mInstantAppInstallerActivity.packageName.equals(
+                                mRequiredVerifierPackage)) {
+                    try {
+                        mContext.getSystemService(AppOpsManager.class)
+                                .checkPackage(installerUid, mRequiredVerifierPackage);
+                        if (DEBUG_VERIFY) {
+                            Slog.i(TAG, "disable verification for instant app");
+                        }
+                        return false;
+                    } catch (SecurityException ignore) { }
+                }
+            }
         }
 
         if (ensureVerifyAppsEnabled) {
@@ -14780,10 +15000,16 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public int getIntentVerificationStatus(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
         }
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null
+                    || filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return INTENT_FILTER_DOMAIN_VERIFICATION_STATUS_UNDEFINED;
+            }
             return mSettings.getIntentFilterVerificationStatusLPr(packageName, userId);
         }
     }
@@ -14795,6 +15021,10 @@ public class PackageManagerService extends IPackageManager.Stub
 
         boolean result = false;
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+                return false;
+            }
             result = mSettings.updateIntentFilterVerificationStatusLPw(packageName, status, userId);
         }
         if (result) {
@@ -14806,10 +15036,15 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public @NonNull ParceledListSlice<IntentFilterVerificationInfo> getIntentFilterVerifications(
             String packageName) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return ParceledListSlice.emptyList();
         }
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return ParceledListSlice.emptyList();
+            }
             return new ParceledListSlice<>(mSettings.getIntentFilterVerificationsLPr(packageName));
         }
     }
@@ -14890,7 +15125,9 @@ public class PackageManagerService extends IPackageManager.Stub
         // writer
         synchronized (mPackages) {
             PackageSetting targetPackageSetting = mSettings.mPackages.get(targetPackage);
-            if (targetPackageSetting == null) {
+            if (targetPackageSetting == null
+                    || filterAppAccessLPr(
+                            targetPackageSetting, callingUid, UserHandle.getUserId(callingUid))) {
                 throw new IllegalArgumentException("Unknown target package: " + targetPackage);
             }
 
@@ -14971,7 +15208,9 @@ public class PackageManagerService extends IPackageManager.Stub
             if (ps == null) {
                 throw new IllegalArgumentException("Unknown target package " + packageName);
             }
-
+            if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+                throw new IllegalArgumentException("Unknown target package " + packageName);
+            }
             if (!Objects.equals(callerPackageName, ps.installerPackageName)) {
                 throw new IllegalArgumentException("Calling package " + callerPackageName
                         + " is not installer for " + packageName);
@@ -15494,7 +15733,7 @@ public class PackageManagerService extends IPackageManager.Stub
                             origin.resolvedPath, isForwardLocked(), packageAbiOverride);
 
                     try {
-                        mInstaller.freeCache(null, sizeBytes + lowThreshold, 0);
+                        mInstaller.freeCache(null, sizeBytes + lowThreshold, 0, 0);
                         pkgLite = mContainerService.getMinimalPackageInfo(origin.resolvedPath,
                                 installFlags, packageAbiOverride);
                     } catch (InstallerException e) {
@@ -15576,8 +15815,11 @@ public class PackageManagerService extends IPackageManager.Stub
                 final int requiredUid = mRequiredVerifierPackage == null ? -1
                         : getPackageUid(mRequiredVerifierPackage, MATCH_DEBUG_TRIAGED_MISSING,
                                 verifierUser.getIdentifier());
+                final int installerUid =
+                        verificationInfo == null ? -1 : verificationInfo.installerUid;
                 if (!origin.existing && requiredUid != -1
-                        && isVerificationEnabled(verifierUser.getIdentifier(), installFlags)) {
+                        && isVerificationEnabled(
+                                verifierUser.getIdentifier(), installFlags, installerUid)) {
                     final Intent verification = new Intent(
                             Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
                     verification.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
@@ -16975,12 +17217,15 @@ public class PackageManagerService extends IPackageManager.Stub
 
     @Override
     public List<String> getPreviousCodePaths(String packageName) {
+        final int callingUid = Binder.getCallingUid();
         final List<String> result = new ArrayList<>();
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        if (getInstantAppPackageName(callingUid) != null) {
             return result;
         }
         final PackageSetting ps = mSettings.mPackages.get(packageName);
-        if (ps != null && ps.oldCodePaths != null) {
+        if (ps != null
+                && ps.oldCodePaths != null
+                && !filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
             result.addAll(ps.oldCodePaths);
         }
         return result;
@@ -17986,7 +18231,7 @@ public class PackageManagerService extends IPackageManager.Stub
             }
 
             if (res.returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                updateSequenceNumberLP(pkgName, res.newUsers);
+                updateSequenceNumberLP(ps, res.newUsers);
                 updateInstantAppInstallerLocked(pkgName);
             }
         }
@@ -18209,8 +18454,10 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public void deletePackageVersioned(VersionedPackage versionedPackage,
             final IPackageDeleteObserver2 observer, final int userId, final int deleteFlags) {
+        final int callingUid = Binder.getCallingUid();
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_PACKAGES, null);
+        final boolean canViewInstantApps = canViewInstantApps(callingUid, userId);
         Preconditions.checkNotNull(versionedPackage);
         Preconditions.checkNotNull(observer);
         Preconditions.checkArgumentInRange(versionedPackage.getVersionCode(),
@@ -18275,33 +18522,45 @@ public class PackageManagerService extends IPackageManager.Stub
             public void run() {
                 mHandler.removeCallbacks(this);
                 int returnCode;
-                if (!deleteAllUsers) {
-                    returnCode = deletePackageX(internalPackageName, versionCode,
-                            userId, deleteFlags);
-                } else {
-                    int[] blockUninstallUserIds = getBlockUninstallForUsers(
-                            internalPackageName, users);
-                    // If nobody is blocking uninstall, proceed with delete for all users
-                    if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+                final PackageSetting ps = mSettings.mPackages.get(internalPackageName);
+                boolean doDeletePackage = true;
+                if (ps != null) {
+                    final boolean targetIsInstantApp =
+                            ps.getInstantApp(UserHandle.getUserId(callingUid));
+                    doDeletePackage = !targetIsInstantApp
+                            || canViewInstantApps;
+                }
+                if (doDeletePackage) {
+                    if (!deleteAllUsers) {
                         returnCode = deletePackageX(internalPackageName, versionCode,
                                 userId, deleteFlags);
                     } else {
-                        // Otherwise uninstall individually for users with blockUninstalls=false
-                        final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
-                        for (int userId : users) {
-                            if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
-                                returnCode = deletePackageX(internalPackageName, versionCode,
-                                        userId, userFlags);
-                                if (returnCode != PackageManager.DELETE_SUCCEEDED) {
-                                    Slog.w(TAG, "Package delete failed for user " + userId
-                                            + ", returnCode " + returnCode);
+                        int[] blockUninstallUserIds = getBlockUninstallForUsers(
+                                internalPackageName, users);
+                        // If nobody is blocking uninstall, proceed with delete for all users
+                        if (ArrayUtils.isEmpty(blockUninstallUserIds)) {
+                            returnCode = deletePackageX(internalPackageName, versionCode,
+                                    userId, deleteFlags);
+                        } else {
+                            // Otherwise uninstall individually for users with blockUninstalls=false
+                            final int userFlags = deleteFlags & ~PackageManager.DELETE_ALL_USERS;
+                            for (int userId : users) {
+                                if (!ArrayUtils.contains(blockUninstallUserIds, userId)) {
+                                    returnCode = deletePackageX(internalPackageName, versionCode,
+                                            userId, userFlags);
+                                    if (returnCode != PackageManager.DELETE_SUCCEEDED) {
+                                        Slog.w(TAG, "Package delete failed for user " + userId
+                                                + ", returnCode " + returnCode);
+                                    }
                                 }
                             }
+                            // The app has only been marked uninstalled for certain users.
+                            // We still need to report that delete was blocked
+                            returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
                         }
-                        // The app has only been marked uninstalled for certain users.
-                        // We still need to report that delete was blocked
-                        returnCode = PackageManager.DELETE_FAILED_OWNER_BLOCKED;
                     }
+                } else {
+                    returnCode = PackageManager.DELETE_FAILED_INTERNAL_ERROR;
                 }
                 try {
                     observer.onPackageDeleted(packageName, returnCode, null);
@@ -18488,7 +18747,7 @@ public class PackageManagerService extends IPackageManager.Stub
      *  persisting settings for later use
      *  sending a broadcast if necessary
      */
-    private int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) {
+    int deletePackageX(String packageName, int versionCode, int userId, int deleteFlags) {
         final PackageRemovedInfo info = new PackageRemovedInfo(this);
         final boolean res;
 
@@ -18531,7 +18790,7 @@ public class PackageManagerService extends IPackageManager.Stub
                         pkg.staticSharedLibVersion);
                 if (libEntry != null) {
                     for (int currUserId : allUsers) {
-                        if (userId != UserHandle.USER_ALL && userId != currUserId) {
+                        if (removeUser != UserHandle.USER_ALL && removeUser != currUserId) {
                             continue;
                         }
                         List<VersionedPackage> libClientPackages = getPackagesUsingSharedLibraryLPr(
@@ -18572,7 +18831,7 @@ public class PackageManagerService extends IPackageManager.Stub
                     if (pkg != null) {
                         mInstantAppRegistry.onPackageUninstalledLPw(pkg, info.removedUsers);
                     }
-                    updateSequenceNumberLP(packageName, info.removedUsers);
+                    updateSequenceNumberLP(uninstalledPs, info.removedUsers);
                     updateInstantAppInstallerLocked(packageName);
                 }
             }
@@ -19103,6 +19362,10 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public boolean getBlockUninstallForUser(String packageName, int userId) {
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (ps == null || filterAppAccessLPr(ps, Binder.getCallingUid(), userId)) {
+                return true;
+            }
             return mSettings.getBlockUninstallLPr(userId, packageName);
         }
     }
@@ -19452,9 +19715,14 @@ public class PackageManagerService extends IPackageManager.Stub
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.CLEAR_APP_USER_DATA, null);
 
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        final int callingUid = Binder.getCallingUid();
+        enforceCrossUserPermission(callingUid, userId,
                 true /* requireFullPermission */, false /* checkShell */, "clear application data");
 
+        final PackageSetting ps = mSettings.getPackageLPr(packageName);
+        if (ps != null && filterAppAccessLPr(ps, callingUid, userId)) {
+            return;
+        }
         if (mProtectedPackages.isPackageDataProtected(userId, packageName)) {
             throw new SecurityException("Cannot clear data for a protected package: "
                     + packageName);
@@ -19712,11 +19980,14 @@ public class PackageManagerService extends IPackageManager.Stub
     @Override
     public void deleteApplicationCacheFilesAsUser(final String packageName, final int userId,
             final IPackageDataObserver observer) {
+        final int callingUid = Binder.getCallingUid();
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.DELETE_CACHE_FILES, null);
-        enforceCrossUserPermission(Binder.getCallingUid(), userId,
+        enforceCrossUserPermission(callingUid, userId,
                 /* requireFullPermission= */ true, /* checkShell= */ false,
                 "delete application cache files");
+        final int hasAccessInstantApps = mContext.checkCallingOrSelfPermission(
+                android.Manifest.permission.ACCESS_INSTANT_APPS);
 
         final PackageParser.Package pkg;
         synchronized (mPackages) {
@@ -19726,15 +19997,25 @@ public class PackageManagerService extends IPackageManager.Stub
         // Queue up an async operation since the package deletion may take a little while.
         mHandler.post(new Runnable() {
             public void run() {
-                synchronized (mInstallLock) {
-                    final int flags = StorageManager.FLAG_STORAGE_DE
-                            | StorageManager.FLAG_STORAGE_CE;
-                    // We're only clearing cache files, so we don't care if the
-                    // app is unfrozen and still able to run
-                    clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
-                    clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
-                }
-                clearExternalStorageDataSync(packageName, userId, false);
+                final PackageSetting ps = (PackageSetting) pkg.mExtras;
+                boolean doClearData = true;
+                if (ps != null) {
+                    final boolean targetIsInstantApp =
+                            ps.getInstantApp(UserHandle.getUserId(callingUid));
+                    doClearData = !targetIsInstantApp
+                            || hasAccessInstantApps == PackageManager.PERMISSION_GRANTED;
+                }
+                if (doClearData) {
+                    synchronized (mInstallLock) {
+                        final int flags = StorageManager.FLAG_STORAGE_DE
+                                | StorageManager.FLAG_STORAGE_CE;
+                        // We're only clearing cache files, so we don't care if the
+                        // app is unfrozen and still able to run
+                        clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CACHE_ONLY);
+                        clearAppDataLIF(pkg, userId, flags | Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
+                    }
+                    clearExternalStorageDataSync(packageName, userId, false);
+                }
                 if (observer != null) {
                     try {
                         observer.onRemoveCompleted(packageName, true);
@@ -19984,7 +20265,11 @@ public class PackageManagerService extends IPackageManager.Stub
                             android.Manifest.permission.SET_PREFERRED_APPLICATIONS, null);
                 }
             }
-
+            final PackageSetting ps = mSettings.getPackageLPr(packageName);
+            if (ps != null
+                    && filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return;
+            }
             int user = UserHandle.getCallingUserId();
             if (clearPackagePreferredActivitiesLPw(packageName, user)) {
                 scheduleWritePackageRestrictionsLocked(user);
@@ -20634,7 +20919,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
     public void clearCrossProfileIntentFilters(int sourceUserId, String ownerPackage) {
         mContext.enforceCallingOrSelfPermission(
                         android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
-        int callingUid = Binder.getCallingUid();
+        final int callingUid = Binder.getCallingUid();
         enforceOwnerRights(ownerPackage, callingUid);
         enforceShellRestriction(UserManager.DISALLOW_DEBUGGING_FEATURES, callingUid, sourceUserId);
         synchronized (mPackages) {
@@ -20657,7 +20942,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         if (UserHandle.getAppId(callingUid) == Process.SYSTEM_UID) {
             return;
         }
-        int callingUserId = UserHandle.getUserId(callingUid);
+        final int callingUserId = UserHandle.getUserId(callingUid);
         PackageInfo pi = getPackageInfo(pkg, 0, callingUserId);
         if (pi == null) {
             throw new IllegalArgumentException("Unknown package " + pkg + " on user "
@@ -20902,7 +21187,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         // Limit who can change which apps
         if (!UserHandle.isSameApp(callingUid, pkgSetting.appId)) {
             // Don't allow apps that don't have permission to modify other apps
-            if (!allowedByPermission) {
+            if (!allowedByPermission
+                    || filterAppAccessLPr(pkgSetting, callingUid, userId)) {
                 throw new SecurityException(
                         "Attempt to change component state; "
                         + "pid=" + Binder.getCallingPid()
@@ -20989,7 +21275,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                 }
             }
             scheduleWritePackageRestrictionsLocked(userId);
-            updateSequenceNumberLP(packageName, new int[] { userId });
+            updateSequenceNumberLP(pkgSetting, new int[] { userId });
             final long callingId = Binder.clearCallingIdentity();
             try {
                 updateInstantAppInstallerLocked(packageName);
@@ -21086,8 +21372,10 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                 true /* requireFullPermission */, true /* checkShell */, "stop package");
         // writer
         synchronized (mPackages) {
-            if (mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
-                    allowedByPermission, callingUid, userId)) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (!filterAppAccessLPr(ps, callingUid, userId)
+                    && mSettings.setPackageStoppedStateLPw(this, packageName, stopped,
+                            allowedByPermission, callingUid, userId)) {
                 scheduleWritePackageRestrictionsLocked(userId);
             }
         }
@@ -21095,11 +21383,16 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
 
     @Override
     public String getInstallerPackageName(String packageName) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return null;
         }
         // reader
         synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(packageName);
+            if (filterAppAccessLPr(ps, callingUid, UserHandle.getUserId(callingUid))) {
+                return null;
+            }
             return mSettings.getInstallerPackageNameLPr(packageName);
         }
     }
@@ -23293,13 +23586,14 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
     public int movePackage(final String packageName, final String volumeUuid) {
         mContext.enforceCallingOrSelfPermission(android.Manifest.permission.MOVE_PACKAGE, null);
 
-        final UserHandle user = new UserHandle(UserHandle.getCallingUserId());
+        final int callingUid = Binder.getCallingUid();
+        final UserHandle user = new UserHandle(UserHandle.getUserId(callingUid));
         final int moveId = mNextMoveId.getAndIncrement();
         mHandler.post(new Runnable() {
             @Override
             public void run() {
                 try {
-                    movePackageInternal(packageName, volumeUuid, moveId, user);
+                    movePackageInternal(packageName, volumeUuid, moveId, callingUid, user);
                 } catch (PackageManagerException e) {
                     Slog.w(TAG, "Failed to move " + packageName, e);
                     mMoveCallbacks.notifyStatusChanged(moveId,
@@ -23311,7 +23605,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
     }
 
     private void movePackageInternal(final String packageName, final String volumeUuid,
-            final int moveId, UserHandle user) throws PackageManagerException {
+            final int moveId, final int callingUid, UserHandle user)
+                    throws PackageManagerException {
         final StorageManager storage = mContext.getSystemService(StorageManager.class);
         final PackageManager pm = mContext.getPackageManager();
 
@@ -23331,10 +23626,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         synchronized (mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
             final PackageSetting ps = mSettings.mPackages.get(packageName);
-            if (pkg == null || ps == null) {
+            if (pkg == null
+                    || ps == null
+                    || filterAppAccessLPr(ps, callingUid, user.getIdentifier())) {
                 throw new PackageManagerException(MOVE_FAILED_DOESNT_EXIST, "Missing package");
             }
-
             if (pkg.applicationInfo.isSystemApp()) {
                 throw new PackageManagerException(MOVE_FAILED_SYSTEM_PACKAGE,
                         "Cannot move system application");
@@ -23804,6 +24100,11 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
+            final PackageSetting ps = (PackageSetting) pkg.mExtras;
+            if (filterAppAccessLPr(ps, Binder.getCallingUid(), UserHandle.getCallingUserId())) {
+                Slog.w(TAG, "KeySet requested for filtered package: " + packageName);
+                throw new IllegalArgumentException("Unknown package: " + packageName);
+            }
             KeySetManagerService ksms = mSettings.mKeySetManagerService;
             return new KeySet(ksms.getKeySetByAliasAndPackageNameLPr(packageName, alias));
         }
@@ -23840,7 +24141,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
 
     @Override
     public boolean isPackageSignedByKeySet(String packageName, KeySet ks) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return false;
         }
         if (packageName == null || ks == null) {
@@ -23848,7 +24150,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         }
         synchronized(mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg == null) {
+            if (pkg == null
+                    || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid,
+                            UserHandle.getUserId(callingUid))) {
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -23863,7 +24167,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
 
     @Override
     public boolean isPackageSignedByKeySetExactly(String packageName, KeySet ks) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
+        final int callingUid = Binder.getCallingUid();
+        if (getInstantAppPackageName(callingUid) != null) {
             return false;
         }
         if (packageName == null || ks == null) {
@@ -23871,7 +24176,9 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         }
         synchronized(mPackages) {
             final PackageParser.Package pkg = mPackages.get(packageName);
-            if (pkg == null) {
+            if (pkg == null
+                    || filterAppAccessLPr((PackageSetting) pkg.mExtras, callingUid,
+                            UserHandle.getUserId(callingUid))) {
                 Slog.w(TAG, "KeySet requested for unknown package: " + packageName);
                 throw new IllegalArgumentException("Unknown package: " + packageName);
             }
@@ -24188,8 +24495,34 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
         }
 
         @Override
-        public ApplicationInfo getApplicationInfo(String packageName, int userId) {
-            return PackageManagerService.this.getApplicationInfo(packageName, 0 /*flags*/, userId);
+        public PackageInfo getPackageInfo(
+                String packageName, int flags, int filterCallingUid, int userId) {
+            return PackageManagerService.this
+                    .getPackageInfoInternal(packageName, PackageManager.VERSION_CODE_HIGHEST,
+                            flags, filterCallingUid, userId);
+        }
+
+        @Override
+        public ApplicationInfo getApplicationInfo(
+                String packageName, int flags, int filterCallingUid, int userId) {
+            return PackageManagerService.this
+                    .getApplicationInfoInternal(packageName, flags, filterCallingUid, userId);
+        }
+
+        @Override
+        public ActivityInfo getActivityInfo(
+                ComponentName component, int flags, int filterCallingUid, int userId) {
+            return PackageManagerService.this
+                    .getActivityInfoInternal(component, flags, filterCallingUid, userId);
+        }
+
+        @Override
+        public List<ResolveInfo> queryIntentActivities(
+                Intent intent, int flags, int filterCallingUid, int userId) {
+            final String resolvedType = intent.resolveTypeIfNeeded(mContext.getContentResolver());
+            return PackageManagerService.this
+                    .queryIntentActivitiesInternal(intent, resolvedType, flags, filterCallingUid,
+                            userId, false /*resolveForStart*/);
         }
 
         @Override
@@ -24273,9 +24606,7 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
 
         @Override
         public void pruneInstantApps() {
-            synchronized (mPackages) {
-                mInstantAppRegistry.pruneInstantAppsLPw();
-            }
+            mInstantAppRegistry.pruneInstantApps();
         }
 
         @Override
@@ -24522,9 +24853,6 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName());
 
     @Override
     public boolean canRequestPackageInstalls(String packageName, int userId) {
-        if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
-            return false;
-        }
         return canRequestPackageInstallsInternal(packageName, 0, userId,
                 true /* throwIfPermNotDeclared*/);
     }
index 7d53310..3e5e57b 100644 (file)
@@ -233,7 +233,7 @@ public class AccessibilityShortcutController {
 
     private AccessibilityServiceInfo getInfoForTargetService() {
         final String currentShortcutServiceString = getTargetServiceComponentNameString(
-                mContext, UserHandle.myUserId());
+                mContext, UserHandle.USER_CURRENT);
         if (currentShortcutServiceString == null) {
             return null;
         }
index 908e517..6d46fda 100644 (file)
@@ -60,7 +60,6 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_ST
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TASK_SNAPSHOT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SYSTEM_ERROR;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_CROSSFADE;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_JUMPCUT;
@@ -1128,16 +1127,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                 + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
                 + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
                 + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+        final boolean keyguardGoingAway = mWindowManagerInternal.isKeyguardGoingAway();
+
         boolean disable = true;
         // Note: We postpone the rotating of the screen until the keyguard as well as the
-        // window manager have reported a draw complete.
-        if (mScreenOnEarly && mAwake &&
-                mKeyguardDrawComplete && mWindowManagerDrawComplete) {
+        // window manager have reported a draw complete or the keyguard is going away in dismiss
+        // mode.
+        if (mScreenOnEarly && mAwake && ((mKeyguardDrawComplete && mWindowManagerDrawComplete)
+                || keyguardGoingAway)) {
             if (needSensorRunningLp()) {
                 disable = false;
                 //enable listener if not already enabled
                 if (!mOrientationSensorEnabled) {
-                    mOrientationListener.enable();
+                    // Don't clear the current sensor orientation if the keyguard is going away in
+                    // dismiss mode. This allows window manager to use the last sensor reading to
+                    // determine the orientation vs. falling back to the last known orientation if
+                    // the sensor reading was cleared which can cause it to relaunch the app that
+                    // will show in the wrong orientation first before correcting leading to app
+                    // launch delays.
+                    mOrientationListener.enable(!keyguardGoingAway /* clearCurrentRotation */);
                     if(localLOGV) Slog.v(TAG, "Enabling listeners");
                     mOrientationSensorEnabled = true;
                 }
@@ -1410,7 +1418,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                     launchHomeFromHotKey();
                     break;
                 case SHORT_PRESS_POWER_GO_HOME:
-                    launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+                    shortPressPowerGoHome();
                     break;
                 case SHORT_PRESS_POWER_CLOSE_IME_OR_GO_HOME: {
                     if (mDismissImeOnBackKeyPressed) {
@@ -1422,8 +1430,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                             mInputMethodManagerInternal.hideCurrentInputMethod();
                         }
                     } else {
-                        launchHomeFromHotKey(true /* awakenFromDreams */,
-                                false /*respectKeyguard*/);
+                        shortPressPowerGoHome();
                     }
                     break;
                 }
@@ -1431,6 +1438,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         }
     }
 
+    private void shortPressPowerGoHome() {
+        launchHomeFromHotKey(true /* awakenFromDreams */, false /*respectKeyguard*/);
+        if (isKeyguardShowingAndNotOccluded()) {
+            // Notify keyguard so it can do any special handling for the power button since the
+            // device will not power off and only launch home.
+            mKeyguardDelegate.onShortPowerPressedGoHome();
+        }
+    }
+
     private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
         switch (behavior) {
             case MULTI_PRESS_POWER_NOTHING:
index 8ef0acb..64f64c0 100644 (file)
@@ -109,24 +109,37 @@ public abstract class WindowOrientationListener {
      * {@link #onProposedRotationChanged(int)} when the device orientation changes.
      */
     public void enable() {
+        enable(true /* clearCurrentRotation */);
+    }
+
+    /**
+     * Enables the WindowOrientationListener so it will monitor the sensor and call
+     * {@link #onProposedRotationChanged(int)} when the device orientation changes.
+     *
+     * @param clearCurrentRotation True if the current proposed sensor rotation should be cleared as
+     *                             part of the reset.
+     */
+    public void enable(boolean clearCurrentRotation) {
         synchronized (mLock) {
             if (mSensor == null) {
                 Slog.w(TAG, "Cannot detect sensors. Not enabled");
                 return;
             }
-            if (mEnabled == false) {
-                if (LOG) {
-                    Slog.d(TAG, "WindowOrientationListener enabled");
-                }
-                mOrientationJudge.resetLocked();
-                if (mSensor.getType() == Sensor.TYPE_ACCELEROMETER) {
-                    mSensorManager.registerListener(
-                            mOrientationJudge, mSensor, mRate, DEFAULT_BATCH_LATENCY, mHandler);
-                } else {
-                    mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler);
-                }
-                mEnabled = true;
+            if (mEnabled) {
+                return;
             }
+            if (LOG) {
+                Slog.d(TAG, "WindowOrientationListener enabled clearCurrentRotation="
+                        + clearCurrentRotation);
+            }
+            mOrientationJudge.resetLocked(clearCurrentRotation);
+            if (mSensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+                mSensorManager.registerListener(
+                        mOrientationJudge, mSensor, mRate, DEFAULT_BATCH_LATENCY, mHandler);
+            } else {
+                mSensorManager.registerListener(mOrientationJudge, mSensor, mRate, mHandler);
+            }
+            mEnabled = true;
         }
     }
 
@@ -278,8 +291,11 @@ public abstract class WindowOrientationListener {
          * Resets the state of the judge.
          *
          * Should only be called when holding WindowOrientationListener lock.
+         *
+         * @param clearCurrentRotation True if the current proposed sensor rotation should be
+         *                             cleared as part of the reset.
          */
-        public abstract void resetLocked();
+        public abstract void resetLocked(boolean clearCurrentRotation);
 
         /**
          * Dumps internal state of the orientation judge.
@@ -602,7 +618,7 @@ public abstract class WindowOrientationListener {
                     if (LOG) {
                         Slog.v(TAG, "Resetting orientation listener.");
                     }
-                    resetLocked();
+                    resetLocked(true /* clearCurrentRotation */);
                     skipSample = true;
                 } else {
                     final float alpha = timeDeltaMS / (FILTER_TIME_CONSTANT_MS + timeDeltaMS);
@@ -778,9 +794,11 @@ public abstract class WindowOrientationListener {
         }
 
         @Override
-        public void resetLocked() {
+        public void resetLocked(boolean clearCurrentRotation) {
             mLastFilteredTimestampNanos = Long.MIN_VALUE;
-            mProposedRotation = -1;
+            if (clearCurrentRotation) {
+                mProposedRotation = -1;
+            }
             mFlatTimestampNanos = Long.MIN_VALUE;
             mFlat = false;
             mSwingTimestampNanos = Long.MIN_VALUE;
@@ -1015,9 +1033,11 @@ public abstract class WindowOrientationListener {
         }
 
         @Override
-        public void resetLocked() {
-            mProposedRotation = -1;
-            mDesiredRotation = -1;
+        public void resetLocked(boolean clearCurrentRotation) {
+            if (clearCurrentRotation) {
+                mProposedRotation = -1;
+                mDesiredRotation = -1;
+            }
             mTouching = false;
             mTouchEndedTimestampNanos = Long.MIN_VALUE;
             unscheduleRotationEvaluationLocked();
index 1b4eaf5..0121ee1 100644 (file)
@@ -30,7 +30,7 @@ import java.io.PrintWriter;
  */
 public class KeyguardServiceDelegate {
     private static final String TAG = "KeyguardServiceDelegate";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     private static final int SCREEN_STATE_OFF = 0;
     private static final int SCREEN_STATE_TURNING_ON = 1;
@@ -372,6 +372,12 @@ public class KeyguardServiceDelegate {
         mKeyguardState.bootCompleted = true;
     }
 
+    public void onShortPowerPressedGoHome() {
+        if (mKeyguardService != null) {
+            mKeyguardService.onShortPowerPressedGoHome();
+        }
+    }
+
     public void dump(String prefix, PrintWriter pw) {
         pw.println(prefix + TAG);
         prefix += "  ";
index 0b839b8..425be54 100644 (file)
@@ -218,6 +218,15 @@ public class KeyguardServiceWrapper implements IKeyguardService {
         }
     }
 
+    @Override
+    public void onShortPowerPressedGoHome() {
+        try {
+            mService.onShortPowerPressedGoHome();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
     @Override // Binder interface
     public IBinder asBinder() {
         return mService.asBinder();
index c8ade2d..3b5db29 100644 (file)
@@ -87,6 +87,7 @@ import com.android.server.LockGuard;
 import com.android.server.RescueParty;
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
+import com.android.server.UiThread;
 import com.android.server.Watchdog;
 import com.android.server.am.BatteryStatsService;
 import com.android.server.lights.Light;
@@ -1940,7 +1941,8 @@ public final class PowerManagerService extends SystemService
                         && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
                     nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
                     if (now < nextTimeout) {
-                        if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT) {
+                        if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_BRIGHT
+                                || mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_VR) {
                             mUserActivitySummary = USER_ACTIVITY_SCREEN_BRIGHT;
                         } else if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DIM) {
                             mUserActivitySummary = USER_ACTIVITY_SCREEN_DIM;
@@ -2728,9 +2730,9 @@ public final class PowerManagerService extends SystemService
         };
 
         // ShutdownThread must run on a looper capable of displaying the UI.
-        Message msg = Message.obtain(mHandler, runnable);
+        Message msg = Message.obtain(UiThread.getHandler(), runnable);
         msg.setAsynchronous(true);
-        mHandler.sendMessage(msg);
+        UiThread.getHandler().sendMessage(msg);
 
         // PowerManager.reboot() is documented not to return so just wait for the inevitable.
         if (wait) {
index fbc9e56..88b6d87 100644 (file)
 
 package com.android.server.storage;
 
-import android.app.NotificationChannel;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.util.DumpUtils;
-import com.android.server.EventLogTags;
-import com.android.server.SystemService;
-import com.android.server.pm.InstructionSets;
+import android.annotation.WorkerThread;
 import android.app.Notification;
+import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.IPackageDataObserver;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.net.TrafficStats;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.FileObserver;
 import android.os.Handler;
 import android.os.Message;
-import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.ServiceManager;
 import android.os.ShellCallback;
 import android.os.ShellCommand;
-import android.os.StatFs;
-import android.os.SystemClock;
-import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
-import android.provider.Settings;
-import android.text.format.Formatter;
-import android.util.EventLog;
+import android.os.storage.VolumeInfo;
+import android.text.format.DateUtils;
+import android.util.ArrayMap;
 import android.util.Slog;
-import android.util.TimeUtils;
+
+import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
+import com.android.internal.notification.SystemNotificationChannels;
+import com.android.internal.util.DumpUtils;
+import com.android.internal.util.IndentingPrintWriter;
+import com.android.server.EventLogTags;
+import com.android.server.IoThread;
+import com.android.server.SystemService;
+import com.android.server.pm.InstructionSets;
+import com.android.server.pm.PackageManagerService;
+
+import dalvik.system.VMRuntime;
 
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.Objects;
+import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import dalvik.system.VMRuntime;
-
 /**
- * This class implements a service to monitor the amount of disk
- * storage space on the device.  If the free storage on device is less
- * than a tunable threshold value (a secure settings parameter;
- * default 10%) a low memory notification is displayed to alert the
- * user. If the user clicks on the low memory notification the
- * Application Manager application gets launched to let the user free
- * storage space.
- *
- * Event log events: A low memory event with the free storage on
- * device in bytes is logged to the event log when the device goes low
- * on storage space.  The amount of free storage on the device is
- * periodically logged to the event log. The log interval is a secure
- * settings parameter with a default value of 12 hours.  When the free
- * storage differential goes below a threshold (again a secure
- * settings parameter with a default value of 2MB), the free memory is
- * logged to the event log.
+ * Service that monitors and maintains free space on storage volumes.
+ * <p>
+ * As the free space on a volume nears the threshold defined by
+ * {@link StorageManager#getStorageLowBytes(File)}, this service will clear out
+ * cached data to keep the disk from entering this low state.
  */
 public class DeviceStorageMonitorService extends SystemService {
-    static final String TAG = "DeviceStorageMonitorService";
+    private static final String TAG = "DeviceStorageMonitorService";
 
     /**
      * Extra for {@link android.content.Intent#ACTION_BATTERY_CHANGED}:
@@ -88,68 +77,75 @@ public class DeviceStorageMonitorService extends SystemService {
      */
     public static final String EXTRA_SEQUENCE = "seq";
 
-    // TODO: extend to watch and manage caches on all private volumes
+    private static final int MSG_CHECK = 1;
 
-    static final boolean DEBUG = false;
-    static final boolean localLOGV = false;
-
-    static final int DEVICE_MEMORY_WHAT = 1;
-    static final int FORCE_MEMORY_WHAT = 2;
-    private static final int MONITOR_INTERVAL = 1; //in minutes
-
-    private static final int DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES = 12*60; //in minutes
-    private static final long DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD = 2 * 1024 * 1024; // 2MB
-    private static final long DEFAULT_CHECK_INTERVAL = MONITOR_INTERVAL*60*1000;
+    private static final long DEFAULT_LOG_DELTA_BYTES = 64 * TrafficStats.MB_IN_BYTES;
+    private static final long DEFAULT_CHECK_INTERVAL = DateUtils.MINUTE_IN_MILLIS;
 
     // com.android.internal.R.string.low_internal_storage_view_text_no_boot
     // hard codes 250MB in the message as the storage space required for the
     // boot image.
-    private static final long BOOT_IMAGE_STORAGE_REQUIREMENT = 250 * 1024 * 1024;
-
-    private long mFreeMem;  // on /data
-    private long mFreeMemAfterLastCacheClear;  // on /data
-    private long mLastReportedFreeMem;
-    private long mLastReportedFreeMemTime;
-    boolean mLowMemFlag=false;
-    private boolean mMemFullFlag=false;
-    private final boolean mIsBootImageOnDisk;
-    private final ContentResolver mResolver;
-    private final long mTotalMemory;  // on /data
-    private final StatFs mDataFileStats;
-    private final StatFs mSystemFileStats;
-    private final StatFs mCacheFileStats;
-
-    private static final File DATA_PATH = Environment.getDataDirectory();
-    private static final File SYSTEM_PATH = Environment.getRootDirectory();
-    private static final File CACHE_PATH = Environment.getDownloadCacheDirectory();
-
-    private long mThreadStartTime = -1;
-    boolean mUpdatesStopped;
-    AtomicInteger mSeq = new AtomicInteger(1);
-    boolean mClearSucceeded = false;
-    boolean mClearingCache;
-    private final Intent mStorageLowIntent;
-    private final Intent mStorageOkIntent;
-    private final Intent mStorageFullIntent;
-    private final Intent mStorageNotFullIntent;
-    private CachePackageDataObserver mClearCacheObserver;
+    private static final long BOOT_IMAGE_STORAGE_REQUIREMENT = 250 * TrafficStats.MB_IN_BYTES;
+
+    private NotificationManager mNotifManager;
+
+    /** Sequence number used for testing */
+    private final AtomicInteger mSeq = new AtomicInteger(1);
+    /** Forced level used for testing */
+    private volatile int mForceLevel = State.LEVEL_UNKNOWN;
+
+    /** Map from storage volume UUID to internal state */
+    private final ArrayMap<UUID, State> mStates = new ArrayMap<>();
+
+    /**
+     * State for a specific storage volume, including the current "level" that
+     * we've alerted the user and apps about.
+     */
+    private static class State {
+        private static final int LEVEL_UNKNOWN = -1;
+        private static final int LEVEL_NORMAL = 0;
+        private static final int LEVEL_LOW = 1;
+        private static final int LEVEL_FULL = 2;
+
+        /** Last "level" that we alerted about */
+        public int level = LEVEL_NORMAL;
+        /** Last {@link File#getUsableSpace()} that we logged about */
+        public long lastUsableBytes = Long.MAX_VALUE;
+
+        /**
+         * Test if the given level transition is "entering" a specific level.
+         * <p>
+         * As an example, a transition from {@link #LEVEL_NORMAL} to
+         * {@link #LEVEL_FULL} is considered to "enter" both {@link #LEVEL_LOW}
+         * and {@link #LEVEL_FULL}.
+         */
+        private static boolean isEntering(int level, int oldLevel, int newLevel) {
+            return newLevel >= level && (oldLevel < level || oldLevel == LEVEL_UNKNOWN);
+        }
+
+        /**
+         * Test if the given level transition is "leaving" a specific level.
+         * <p>
+         * As an example, a transition from {@link #LEVEL_FULL} to
+         * {@link #LEVEL_NORMAL} is considered to "leave" both
+         * {@link #LEVEL_FULL} and {@link #LEVEL_LOW}.
+         */
+        private static boolean isLeaving(int level, int oldLevel, int newLevel) {
+            return newLevel < level && (oldLevel >= level || oldLevel == LEVEL_UNKNOWN);
+        }
+
+        private static String levelToString(int level) {
+            switch (level) {
+                case State.LEVEL_UNKNOWN: return "UNKNOWN";
+                case State.LEVEL_NORMAL: return "NORMAL";
+                case State.LEVEL_LOW: return "LOW";
+                case State.LEVEL_FULL: return "FULL";
+                default: return Integer.toString(level);
+            }
+        }
+    }
+
     private CacheFileDeletedObserver mCacheFileDeletedObserver;
-    private static final int _TRUE = 1;
-    private static final int _FALSE = 0;
-    // This is the raw threshold that has been set at which we consider
-    // storage to be low.
-    long mMemLowThreshold;
-    // This is the threshold at which we start trying to flush caches
-    // to get below the low threshold limit.  It is less than the low
-    // threshold; we will allow storage to get a bit beyond the limit
-    // before flushing and checking if we are actually low.
-    private long mMemCacheStartTrimThreshold;
-    // This is the threshold that we try to get to when deleting cache
-    // files.  This is greater than the low threshold so that we will flush
-    // more files than absolutely needed, to reduce the frequency that
-    // flushing takes place.
-    private long mMemCacheTrimToThreshold;
-    private long mMemFullThreshold;
 
     /**
      * This string is used for ServiceManager access to this class.
@@ -159,244 +155,107 @@ public class DeviceStorageMonitorService extends SystemService {
     private static final String TV_NOTIFICATION_CHANNEL_ID = "devicestoragemonitor.tv";
 
     /**
-    * Handler that checks the amount of disk space on the device and sends a
-    * notification if the device runs low on disk space
-    */
-    private final Handler mHandler = new Handler() {
+     * Handler that checks the amount of disk space on the device and sends a
+     * notification if the device runs low on disk space
+     */
+    private final Handler mHandler = new Handler(IoThread.get().getLooper()) {
         @Override
         public void handleMessage(Message msg) {
-            //don't handle an invalid message
             switch (msg.what) {
-                case DEVICE_MEMORY_WHAT:
-                    checkMemory(msg.arg1 == _TRUE);
-                    return;
-                case FORCE_MEMORY_WHAT:
-                    forceMemory(msg.arg1, msg.arg2);
-                    return;
-                default:
-                    Slog.w(TAG, "Will not process invalid message");
+                case MSG_CHECK:
+                    check();
                     return;
             }
         }
     };
 
-    private class CachePackageDataObserver extends IPackageDataObserver.Stub {
-        public void onRemoveCompleted(String packageName, boolean succeeded) {
-            mClearSucceeded = succeeded;
-            mClearingCache = false;
-            if(localLOGV) Slog.i(TAG, " Clear succeeded:"+mClearSucceeded
-                    +", mClearingCache:"+mClearingCache+" Forcing memory check");
-            postCheckMemoryMsg(false, 0);
-        }
-    }
-
-    private void restatDataDir() {
-        try {
-            mDataFileStats.restat(DATA_PATH.getAbsolutePath());
-            mFreeMem = (long) mDataFileStats.getAvailableBlocks() *
-                mDataFileStats.getBlockSize();
-        } catch (IllegalArgumentException e) {
-            // use the old value of mFreeMem
-        }
-        // Allow freemem to be overridden by debug.freemem for testing
-        String debugFreeMem = SystemProperties.get("debug.freemem");
-        if (!"".equals(debugFreeMem)) {
-            mFreeMem = Long.parseLong(debugFreeMem);
-        }
-        // Read the log interval from secure settings
-        long freeMemLogInterval = Settings.Global.getLong(mResolver,
-                Settings.Global.SYS_FREE_STORAGE_LOG_INTERVAL,
-                DEFAULT_FREE_STORAGE_LOG_INTERVAL_IN_MINUTES)*60*1000;
-        //log the amount of free memory in event log
-        long currTime = SystemClock.elapsedRealtime();
-        if((mLastReportedFreeMemTime == 0) ||
-           (currTime-mLastReportedFreeMemTime) >= freeMemLogInterval) {
-            mLastReportedFreeMemTime = currTime;
-            long mFreeSystem = -1, mFreeCache = -1;
-            try {
-                mSystemFileStats.restat(SYSTEM_PATH.getAbsolutePath());
-                mFreeSystem = (long) mSystemFileStats.getAvailableBlocks() *
-                    mSystemFileStats.getBlockSize();
-            } catch (IllegalArgumentException e) {
-                // ignore; report -1
-            }
-            try {
-                mCacheFileStats.restat(CACHE_PATH.getAbsolutePath());
-                mFreeCache = (long) mCacheFileStats.getAvailableBlocks() *
-                    mCacheFileStats.getBlockSize();
-            } catch (IllegalArgumentException e) {
-                // ignore; report -1
-            }
-            EventLog.writeEvent(EventLogTags.FREE_STORAGE_LEFT,
-                                mFreeMem, mFreeSystem, mFreeCache);
-        }
-        // Read the reporting threshold from secure settings
-        long threshold = Settings.Global.getLong(mResolver,
-                Settings.Global.DISK_FREE_CHANGE_REPORTING_THRESHOLD,
-                DEFAULT_DISK_FREE_CHANGE_REPORTING_THRESHOLD);
-        // If mFree changed significantly log the new value
-        long delta = mFreeMem - mLastReportedFreeMem;
-        if (delta > threshold || delta < -threshold) {
-            mLastReportedFreeMem = mFreeMem;
-            EventLog.writeEvent(EventLogTags.FREE_STORAGE_CHANGED, mFreeMem);
-        }
-    }
-
-    private void clearCache() {
-        if (mClearCacheObserver == null) {
-            // Lazy instantiation
-            mClearCacheObserver = new CachePackageDataObserver();
-        }
-        mClearingCache = true;
-        try {
-            if (localLOGV) Slog.i(TAG, "Clearing cache");
-            IPackageManager.Stub.asInterface(ServiceManager.getService("package")).
-                    freeStorageAndNotify(null, mMemCacheTrimToThreshold, mClearCacheObserver);
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Failed to get handle for PackageManger Exception: "+e);
-            mClearingCache = false;
-            mClearSucceeded = false;
+    private State findOrCreateState(UUID uuid) {
+        State state = mStates.get(uuid);
+        if (state == null) {
+            state = new State();
+            mStates.put(uuid, state);
         }
+        return state;
     }
 
-    void forceMemory(int opts, int seq) {
-        if ((opts&OPTION_UPDATES_STOPPED) == 0) {
-            if (mUpdatesStopped) {
-                mUpdatesStopped = false;
-                checkMemory(true);
-            }
-        } else {
-            mUpdatesStopped = true;
-            final boolean forceLow = (opts&OPTION_STORAGE_LOW) != 0;
-            if (mLowMemFlag != forceLow || (opts&OPTION_FORCE_UPDATE) != 0) {
-                mLowMemFlag = forceLow;
-                if (forceLow) {
-                    sendNotification(seq);
-                } else {
-                    cancelNotification(seq);
+    /**
+     * Core logic that checks the storage state of every mounted private volume.
+     * Since this can do heavy I/O, callers should invoke indirectly using
+     * {@link #MSG_CHECK}.
+     */
+    @WorkerThread
+    private void check() {
+        final StorageManager storage = getContext().getSystemService(StorageManager.class);
+        final int seq = mSeq.get();
+
+        // Check every mounted private volume to see if they're low on space
+        for (VolumeInfo vol : storage.getWritablePrivateVolumes()) {
+            final File file = vol.getPath();
+            final long fullBytes = storage.getStorageFullBytes(file);
+            final long lowBytes = storage.getStorageLowBytes(file);
+
+            // Automatically trim cached data when nearing the low threshold;
+            // when it's within 150% of the threshold, we try trimming usage
+            // back to 200% of the threshold.
+            if (file.getUsableSpace() < (lowBytes * 3) / 2) {
+                final PackageManagerService pms = (PackageManagerService) ServiceManager
+                        .getService("package");
+                try {
+                    pms.freeStorage(vol.getFsUuid(), lowBytes * 2, 0);
+                } catch (IOException e) {
+                    Slog.w(TAG, e);
                 }
             }
-        }
-    }
 
-    void checkMemory(boolean checkCache) {
-        if (mUpdatesStopped) {
-            return;
-        }
-
-        //if the thread that was started to clear cache is still running do nothing till its
-        //finished clearing cache. Ideally this flag could be modified by clearCache
-        // and should be accessed via a lock but even if it does this test will fail now and
-        //hopefully the next time this flag will be set to the correct value.
-        if (mClearingCache) {
-            if(localLOGV) Slog.i(TAG, "Thread already running just skip");
-            //make sure the thread is not hung for too long
-            long diffTime = System.currentTimeMillis() - mThreadStartTime;
-            if(diffTime > (10*60*1000)) {
-                Slog.w(TAG, "Thread that clears cache file seems to run for ever");
-            }
-        } else {
-            restatDataDir();
-            if (localLOGV)  Slog.v(TAG, "freeMemory="+mFreeMem);
-
-            //post intent to NotificationManager to display icon if necessary
-            if (mFreeMem < mMemLowThreshold) {
-                if (checkCache) {
-                    // We are allowed to clear cache files at this point to
-                    // try to get down below the limit, because this is not
-                    // the initial call after a cache clear has been attempted.
-                    // In this case we will try a cache clear if our free
-                    // space has gone below the cache clear limit.
-                    if (mFreeMem < mMemCacheStartTrimThreshold) {
-                        // We only clear the cache if the free storage has changed
-                        // a significant amount since the last time.
-                        if ((mFreeMemAfterLastCacheClear-mFreeMem)
-                                >= ((mMemLowThreshold-mMemCacheStartTrimThreshold)/4)) {
-                            // See if clearing cache helps
-                            // Note that clearing cache is asynchronous and so we do a
-                            // memory check again once the cache has been cleared.
-                            mThreadStartTime = System.currentTimeMillis();
-                            mClearSucceeded = false;
-                            clearCache();
-                        }
-                    }
-                } else {
-                    // This is a call from after clearing the cache.  Note
-                    // the amount of free storage at this point.
-                    mFreeMemAfterLastCacheClear = mFreeMem;
-                    if (!mLowMemFlag) {
-                        // We tried to clear the cache, but that didn't get us
-                        // below the low storage limit.  Tell the user.
-                        Slog.i(TAG, "Running low on memory. Sending notification");
-                        sendNotification(0);
-                        mLowMemFlag = true;
-                    } else {
-                        if (localLOGV) Slog.v(TAG, "Running low on memory " +
-                                "notification already sent. do nothing");
-                    }
-                }
+            // Send relevant broadcasts and show notifications based on any
+            // recently noticed state transitions.
+            final UUID uuid = StorageManager.convert(vol.getFsUuid());
+            final State state = findOrCreateState(uuid);
+            final long totalBytes = file.getTotalSpace();
+            final long usableBytes = file.getUsableSpace();
+
+            int oldLevel = state.level;
+            int newLevel;
+            if (mForceLevel != State.LEVEL_UNKNOWN) {
+                // When in testing mode, use unknown old level to force sending
+                // of any relevant broadcasts.
+                oldLevel = State.LEVEL_UNKNOWN;
+                newLevel = mForceLevel;
+            } else if (usableBytes <= fullBytes) {
+                newLevel = State.LEVEL_FULL;
+            } else if (usableBytes <= lowBytes) {
+                newLevel = State.LEVEL_LOW;
+            } else if (StorageManager.UUID_DEFAULT.equals(uuid) && !isBootImageOnDisk()
+                    && usableBytes < BOOT_IMAGE_STORAGE_REQUIREMENT) {
+                newLevel = State.LEVEL_LOW;
             } else {
-                mFreeMemAfterLastCacheClear = mFreeMem;
-                if (mLowMemFlag) {
-                    Slog.i(TAG, "Memory available. Cancelling notification");
-                    cancelNotification(0);
-                    mLowMemFlag = false;
-                }
+                newLevel = State.LEVEL_NORMAL;
             }
-            if (!mLowMemFlag && !mIsBootImageOnDisk && mFreeMem < BOOT_IMAGE_STORAGE_REQUIREMENT) {
-                Slog.i(TAG, "No boot image on disk due to lack of space. Sending notification");
-                sendNotification(0);
-                mLowMemFlag = true;
-            }
-            if (mFreeMem < mMemFullThreshold) {
-                if (!mMemFullFlag) {
-                    sendFullNotification();
-                    mMemFullFlag = true;
-                }
-            } else {
-                if (mMemFullFlag) {
-                    cancelFullNotification();
-                    mMemFullFlag = false;
-                }
+
+            // Log whenever we notice drastic storage changes
+            if ((Math.abs(state.lastUsableBytes - usableBytes) > DEFAULT_LOG_DELTA_BYTES)
+                    || oldLevel != newLevel) {
+                EventLogTags.writeStorageState(uuid.toString(), oldLevel, newLevel,
+                        usableBytes, totalBytes);
+                state.lastUsableBytes = usableBytes;
             }
+
+            updateNotifications(vol, oldLevel, newLevel);
+            updateBroadcasts(vol, oldLevel, newLevel, seq);
+
+            state.level = newLevel;
         }
-        if(localLOGV) Slog.i(TAG, "Posting Message again");
-        //keep posting messages to itself periodically
-        postCheckMemoryMsg(true, DEFAULT_CHECK_INTERVAL);
-    }
 
-    void postCheckMemoryMsg(boolean clearCache, long delay) {
-        // Remove queued messages
-        mHandler.removeMessages(DEVICE_MEMORY_WHAT);
-        mHandler.sendMessageDelayed(mHandler.obtainMessage(DEVICE_MEMORY_WHAT,
-                clearCache ?_TRUE : _FALSE, 0),
-                delay);
+        // Loop around to check again in future; we don't remove messages since
+        // there might be an immediate request pending.
+        if (!mHandler.hasMessages(MSG_CHECK)) {
+            mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK),
+                    DEFAULT_CHECK_INTERVAL);
+        }
     }
 
     public DeviceStorageMonitorService(Context context) {
         super(context);
-        mLastReportedFreeMemTime = 0;
-        mResolver = context.getContentResolver();
-        mIsBootImageOnDisk = isBootImageOnDisk();
-        //create StatFs object
-        mDataFileStats = new StatFs(DATA_PATH.getAbsolutePath());
-        mSystemFileStats = new StatFs(SYSTEM_PATH.getAbsolutePath());
-        mCacheFileStats = new StatFs(CACHE_PATH.getAbsolutePath());
-        //initialize total storage on device
-        mTotalMemory = (long)mDataFileStats.getBlockCount() *
-                        mDataFileStats.getBlockSize();
-        mStorageLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW);
-        mStorageLowIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
-                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
-                | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
-        mStorageOkIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK);
-        mStorageOkIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
-                | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
-                | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS);
-        mStorageFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL);
-        mStorageFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-        mStorageNotFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL);
-        mStorageNotFullIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
     }
 
     private static boolean isBootImageOnDisk() {
@@ -408,35 +267,20 @@ public class DeviceStorageMonitorService extends SystemService {
         return true;
     }
 
-    /**
-    * Initializes the disk space threshold value and posts an empty message to
-    * kickstart the process.
-    */
     @Override
     public void onStart() {
-        // cache storage thresholds
-        Context context = getContext();
-        final StorageManager sm = StorageManager.from(context);
-        mMemLowThreshold = sm.getStorageLowBytes(DATA_PATH);
-        mMemFullThreshold = sm.getStorageFullBytes(DATA_PATH);
-
-        mMemCacheStartTrimThreshold = ((mMemLowThreshold*3)+mMemFullThreshold)/4;
-        mMemCacheTrimToThreshold = mMemLowThreshold
-                + ((mMemLowThreshold-mMemCacheStartTrimThreshold)*2);
-        mFreeMemAfterLastCacheClear = mTotalMemory;
-        checkMemory(true);
+        final Context context = getContext();
+        mNotifManager = context.getSystemService(NotificationManager.class);
 
         mCacheFileDeletedObserver = new CacheFileDeletedObserver();
         mCacheFileDeletedObserver.startWatching();
 
         // Ensure that the notification channel is set up
-        NotificationManager notificationMgr =
-            (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
         PackageManager packageManager = context.getPackageManager();
         boolean isTv = packageManager.hasSystemFeature(PackageManager.FEATURE_LEANBACK);
 
         if (isTv) {
-            notificationMgr.createNotificationChannel(new NotificationChannel(
+            mNotifManager.createNotificationChannel(new NotificationChannel(
                     TV_NOTIFICATION_CHANNEL_ID,
                     context.getString(
                         com.android.internal.R.string.device_storage_monitor_notification_channel),
@@ -445,23 +289,29 @@ public class DeviceStorageMonitorService extends SystemService {
 
         publishBinderService(SERVICE, mRemoteService);
         publishLocalService(DeviceStorageMonitorInternal.class, mLocalService);
+
+        // Kick off pass to examine storage state
+        mHandler.removeMessages(MSG_CHECK);
+        mHandler.obtainMessage(MSG_CHECK).sendToTarget();
     }
 
     private final DeviceStorageMonitorInternal mLocalService = new DeviceStorageMonitorInternal() {
         @Override
         public void checkMemory() {
-            // force an early check
-            postCheckMemoryMsg(true, 0);
+            // Kick off pass to examine storage state
+            mHandler.removeMessages(MSG_CHECK);
+            mHandler.obtainMessage(MSG_CHECK).sendToTarget();
         }
 
         @Override
         public boolean isMemoryLow() {
-            return mLowMemFlag;
+            return Environment.getDataDirectory().getUsableSpace() < getMemoryLowThreshold();
         }
 
         @Override
         public long getMemoryLowThreshold() {
-            return mMemLowThreshold;
+            return getContext().getSystemService(StorageManager.class)
+                    .getStorageLowBytes(Environment.getDataDirectory());
         }
     };
 
@@ -494,8 +344,6 @@ public class DeviceStorageMonitorService extends SystemService {
     }
 
     static final int OPTION_FORCE_UPDATE = 1<<0;
-    static final int OPTION_UPDATES_STOPPED = 1<<1;
-    static final int OPTION_STORAGE_LOW = 1<<2;
 
     int parseOptions(Shell shell) {
         String opt;
@@ -518,10 +366,11 @@ public class DeviceStorageMonitorService extends SystemService {
                 int opts = parseOptions(shell);
                 getContext().enforceCallingOrSelfPermission(
                         android.Manifest.permission.DEVICE_POWER, null);
+                mForceLevel = State.LEVEL_LOW;
                 int seq = mSeq.incrementAndGet();
-                mHandler.sendMessage(mHandler.obtainMessage(FORCE_MEMORY_WHAT,
-                        opts | OPTION_UPDATES_STOPPED | OPTION_STORAGE_LOW, seq));
                 if ((opts & OPTION_FORCE_UPDATE) != 0) {
+                    mHandler.removeMessages(MSG_CHECK);
+                    mHandler.obtainMessage(MSG_CHECK).sendToTarget();
                     pw.println(seq);
                 }
             } break;
@@ -529,10 +378,11 @@ public class DeviceStorageMonitorService extends SystemService {
                 int opts = parseOptions(shell);
                 getContext().enforceCallingOrSelfPermission(
                         android.Manifest.permission.DEVICE_POWER, null);
+                mForceLevel = State.LEVEL_NORMAL;
                 int seq = mSeq.incrementAndGet();
-                mHandler.sendMessage(mHandler.obtainMessage(FORCE_MEMORY_WHAT,
-                        opts | OPTION_UPDATES_STOPPED, seq));
                 if ((opts & OPTION_FORCE_UPDATE) != 0) {
+                    mHandler.removeMessages(MSG_CHECK);
+                    mHandler.obtainMessage(MSG_CHECK).sendToTarget();
                     pw.println(seq);
                 }
             } break;
@@ -540,10 +390,11 @@ public class DeviceStorageMonitorService extends SystemService {
                 int opts = parseOptions(shell);
                 getContext().enforceCallingOrSelfPermission(
                         android.Manifest.permission.DEVICE_POWER, null);
+                mForceLevel = State.LEVEL_UNKNOWN;
                 int seq = mSeq.incrementAndGet();
-                mHandler.sendMessage(mHandler.obtainMessage(FORCE_MEMORY_WHAT,
-                        opts, seq));
                 if ((opts & OPTION_FORCE_UPDATE) != 0) {
+                    mHandler.removeMessages(MSG_CHECK);
+                    mHandler.obtainMessage(MSG_CHECK).sendToTarget();
                     pw.println(seq);
                 }
             } break;
@@ -568,145 +419,125 @@ public class DeviceStorageMonitorService extends SystemService {
         pw.println("    -f: force a storage change broadcast be sent, prints new sequence.");
     }
 
-    void dumpImpl(FileDescriptor fd, PrintWriter pw, String[] args) {
+    void dumpImpl(FileDescriptor fd, PrintWriter _pw, String[] args) {
+        final IndentingPrintWriter pw = new IndentingPrintWriter(_pw, "  ");
         if (args == null || args.length == 0 || "-a".equals(args[0])) {
-            final Context context = getContext();
-
-            pw.println("Current DeviceStorageMonitor state:");
-
-            pw.print("  mFreeMem=");
-            pw.print(Formatter.formatFileSize(context, mFreeMem));
-            pw.print(" mTotalMemory=");
-            pw.println(Formatter.formatFileSize(context, mTotalMemory));
-
-            pw.print("  mFreeMemAfterLastCacheClear=");
-            pw.println(Formatter.formatFileSize(context, mFreeMemAfterLastCacheClear));
-
-            pw.print("  mLastReportedFreeMem=");
-            pw.print(Formatter.formatFileSize(context, mLastReportedFreeMem));
-            pw.print(" mLastReportedFreeMemTime=");
-            TimeUtils.formatDuration(mLastReportedFreeMemTime, SystemClock.elapsedRealtime(), pw);
-            pw.println();
-
-            if (mUpdatesStopped) {
-                pw.print("  mUpdatesStopped=");
-                pw.print(mUpdatesStopped);
-                pw.print(" mSeq=");
-                pw.println(mSeq.get());
-            } else {
-                pw.print("  mClearSucceeded=");
-                pw.print(mClearSucceeded);
-                pw.print(" mClearingCache=");
-                pw.println(mClearingCache);
+            pw.println("Known volumes:");
+            pw.increaseIndent();
+            for (int i = 0; i < mStates.size(); i++) {
+                final UUID uuid = mStates.keyAt(i);
+                final State state = mStates.valueAt(i);
+                if (StorageManager.UUID_DEFAULT.equals(uuid)) {
+                    pw.println("Default:");
+                } else {
+                    pw.println(uuid + ":");
+                }
+                pw.increaseIndent();
+                pw.printPair("level", State.levelToString(state.level));
+                pw.printPair("lastUsableBytes", state.lastUsableBytes);
+                pw.println();
+                pw.decreaseIndent();
             }
+            pw.decreaseIndent();
+            pw.println();
 
-            pw.print("  mLowMemFlag=");
-            pw.print(mLowMemFlag);
-            pw.print(" mMemFullFlag=");
-            pw.println(mMemFullFlag);
-
-            pw.print("  mMemLowThreshold=");
-            pw.print(Formatter.formatFileSize(context, mMemLowThreshold));
-            pw.print(" mMemFullThreshold=");
-            pw.println(Formatter.formatFileSize(context, mMemFullThreshold));
-
-            pw.print("  mMemCacheStartTrimThreshold=");
-            pw.print(Formatter.formatFileSize(context, mMemCacheStartTrimThreshold));
-            pw.print(" mMemCacheTrimToThreshold=");
-            pw.println(Formatter.formatFileSize(context, mMemCacheTrimToThreshold));
+            pw.printPair("mSeq", mSeq.get());
+            pw.printPair("mForceState", State.levelToString(mForceLevel));
+            pw.println();
+            pw.println();
 
-            pw.print("  mIsBootImageOnDisk="); pw.println(mIsBootImageOnDisk);
         } else {
             Shell shell = new Shell();
             shell.exec(mRemoteService, null, fd, null, args, null, new ResultReceiver(null));
         }
     }
 
-    /**
-    * This method sends a notification to NotificationManager to display
-    * an error dialog indicating low disk space and launch the Installer
-    * application
-    */
-    private void sendNotification(int seq) {
+    private void updateNotifications(VolumeInfo vol, int oldLevel, int newLevel) {
         final Context context = getContext();
-        if(localLOGV) Slog.i(TAG, "Sending low memory notification");
-        //log the event to event log with the amount of free storage(in bytes) left on the device
-        EventLog.writeEvent(EventLogTags.LOW_STORAGE, mFreeMem);
-        //  Pack up the values and broadcast them to everyone
-        Intent lowMemIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
-        lowMemIntent.putExtra("memory", mFreeMem);
-        lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        NotificationManager notificationMgr =
-                (NotificationManager)context.getSystemService(
-                        Context.NOTIFICATION_SERVICE);
-        CharSequence title = context.getText(
-                com.android.internal.R.string.low_internal_storage_view_title);
-        CharSequence details = context.getText(mIsBootImageOnDisk
-                ? com.android.internal.R.string.low_internal_storage_view_text
-                : com.android.internal.R.string.low_internal_storage_view_text_no_boot);
-        PendingIntent intent = PendingIntent.getActivityAsUser(context, 0,  lowMemIntent, 0,
-                null, UserHandle.CURRENT);
-        Notification notification =
-                new Notification.Builder(context, SystemNotificationChannels.ALERTS)
-                        .setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full)
-                        .setTicker(title)
-                        .setColor(context.getColor(
-                            com.android.internal.R.color.system_notification_accent_color))
-                        .setContentTitle(title)
-                        .setContentText(details)
-                        .setContentIntent(intent)
-                        .setStyle(new Notification.BigTextStyle()
-                              .bigText(details))
-                        .setVisibility(Notification.VISIBILITY_PUBLIC)
-                        .setCategory(Notification.CATEGORY_SYSTEM)
-                        .extend(new Notification.TvExtender()
-                                .setChannelId(TV_NOTIFICATION_CHANNEL_ID))
-                        .build();
-        notification.flags |= Notification.FLAG_NO_CLEAR;
-        notificationMgr.notifyAsUser(null, SystemMessage.NOTE_LOW_STORAGE, notification,
-                UserHandle.ALL);
-        Intent broadcast = new Intent(mStorageLowIntent);
-        if (seq != 0) {
-            broadcast.putExtra(EXTRA_SEQUENCE, seq);
+        final UUID uuid = StorageManager.convert(vol.getFsUuid());
+
+        if (State.isEntering(State.LEVEL_LOW, oldLevel, newLevel)) {
+            Intent lowMemIntent = new Intent(StorageManager.ACTION_MANAGE_STORAGE);
+            lowMemIntent.putExtra(StorageManager.EXTRA_UUID, uuid);
+            lowMemIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+            final CharSequence title = context.getText(
+                    com.android.internal.R.string.low_internal_storage_view_title);
+
+            final CharSequence details;
+            if (StorageManager.UUID_DEFAULT.equals(uuid)) {
+                details = context.getText(isBootImageOnDisk()
+                        ? com.android.internal.R.string.low_internal_storage_view_text
+                        : com.android.internal.R.string.low_internal_storage_view_text_no_boot);
+            } else {
+                details = context.getText(
+                        com.android.internal.R.string.low_internal_storage_view_text);
+            }
+
+            PendingIntent intent = PendingIntent.getActivityAsUser(context, 0, lowMemIntent, 0,
+                    null, UserHandle.CURRENT);
+            Notification notification =
+                    new Notification.Builder(context, SystemNotificationChannels.ALERTS)
+                            .setSmallIcon(com.android.internal.R.drawable.stat_notify_disk_full)
+                            .setTicker(title)
+                            .setColor(context.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
+                            .setContentTitle(title)
+                            .setContentText(details)
+                            .setContentIntent(intent)
+                            .setStyle(new Notification.BigTextStyle()
+                                  .bigText(details))
+                            .setVisibility(Notification.VISIBILITY_PUBLIC)
+                            .setCategory(Notification.CATEGORY_SYSTEM)
+                            .extend(new Notification.TvExtender()
+                                    .setChannelId(TV_NOTIFICATION_CHANNEL_ID))
+                            .build();
+            notification.flags |= Notification.FLAG_NO_CLEAR;
+            mNotifManager.notifyAsUser(uuid.toString(), SystemMessage.NOTE_LOW_STORAGE,
+                    notification, UserHandle.ALL);
+        } else if (State.isLeaving(State.LEVEL_LOW, oldLevel, newLevel)) {
+            mNotifManager.cancelAsUser(uuid.toString(), SystemMessage.NOTE_LOW_STORAGE,
+                    UserHandle.ALL);
         }
-        context.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
     }
 
-    /**
-     * Cancels low storage notification and sends OK intent.
-     */
-    private void cancelNotification(int seq) {
-        final Context context = getContext();
-        if(localLOGV) Slog.i(TAG, "Canceling low memory notification");
-        NotificationManager mNotificationMgr =
-                (NotificationManager)context.getSystemService(
-                        Context.NOTIFICATION_SERVICE);
-        //cancel notification since memory has been freed
-        mNotificationMgr.cancelAsUser(null, SystemMessage.NOTE_LOW_STORAGE, UserHandle.ALL);
-
-        context.removeStickyBroadcastAsUser(mStorageLowIntent, UserHandle.ALL);
-        Intent broadcast = new Intent(mStorageOkIntent);
-        if (seq != 0) {
-            broadcast.putExtra(EXTRA_SEQUENCE, seq);
+    private void updateBroadcasts(VolumeInfo vol, int oldLevel, int newLevel, int seq) {
+        if (!Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, vol.getFsUuid())) {
+            // We don't currently send broadcasts for secondary volumes
+            return;
         }
-        context.sendBroadcastAsUser(broadcast, UserHandle.ALL);
-    }
 
-    /**
-     * Send a notification when storage is full.
-     */
-    private void sendFullNotification() {
-        if(localLOGV) Slog.i(TAG, "Sending memory full notification");
-        getContext().sendStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
-    }
+        final Intent lowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_LOW)
+                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+                        | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS)
+                .putExtra(EXTRA_SEQUENCE, seq);
+        final Intent notLowIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_OK)
+                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
+                        | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND
+                        | Intent.FLAG_RECEIVER_VISIBLE_TO_INSTANT_APPS)
+                .putExtra(EXTRA_SEQUENCE, seq);
+
+        if (State.isEntering(State.LEVEL_LOW, oldLevel, newLevel)) {
+            getContext().sendStickyBroadcastAsUser(lowIntent, UserHandle.ALL);
+        } else if (State.isLeaving(State.LEVEL_LOW, oldLevel, newLevel)) {
+            getContext().removeStickyBroadcastAsUser(lowIntent, UserHandle.ALL);
+            getContext().sendBroadcastAsUser(notLowIntent, UserHandle.ALL);
+        }
 
-    /**
-     * Cancels memory full notification and sends "not full" intent.
-     */
-    private void cancelFullNotification() {
-        if(localLOGV) Slog.i(TAG, "Canceling memory full notification");
-        getContext().removeStickyBroadcastAsUser(mStorageFullIntent, UserHandle.ALL);
-        getContext().sendBroadcastAsUser(mStorageNotFullIntent, UserHandle.ALL);
+        final Intent fullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_FULL)
+                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)
+                .putExtra(EXTRA_SEQUENCE, seq);
+        final Intent notFullIntent = new Intent(Intent.ACTION_DEVICE_STORAGE_NOT_FULL)
+                .addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT)
+                .putExtra(EXTRA_SEQUENCE, seq);
+
+        if (State.isEntering(State.LEVEL_FULL, oldLevel, newLevel)) {
+            getContext().sendStickyBroadcastAsUser(fullIntent, UserHandle.ALL);
+        } else if (State.isLeaving(State.LEVEL_FULL, oldLevel, newLevel)) {
+            getContext().removeStickyBroadcastAsUser(fullIntent, UserHandle.ALL);
+            getContext().sendBroadcastAsUser(notFullIntent, UserHandle.ALL);
+        }
     }
 
     private static class CacheFileDeletedObserver extends FileObserver {
index 0c119a7..96e3584 100644 (file)
@@ -203,7 +203,13 @@ public class FileCollector {
             return 0;
         }
 
-        final long sharedDataSize = shared.getPath().getTotalSpace();
+        // In some cases, the path may be null -- we can't determine the size in this case.
+        final File sharedPath = shared.getPath();
+        if (sharedPath == null) {
+          return 0;
+        }
+
+        final long sharedDataSize = sharedPath.getTotalSpace();
         long systemSize = sm.getPrimaryStorageSize() - sharedDataSize;
 
         // This case is not exceptional -- we just fallback to the shared data volume in this case.
index 4044fdb..b937f9d 100644 (file)
@@ -96,6 +96,7 @@ import java.util.Objects;
 public class VrManagerService extends SystemService implements EnabledComponentChangeListener{
 
     public static final String TAG = "VrManagerService";
+    static final boolean DBG = false;
 
     private static final int PENDING_STATE_DELAY_MS = 300;
     private static final int EVENT_LOG_SIZE = 32;
@@ -157,7 +158,7 @@ public class VrManagerService extends SystemService implements EnabledComponentC
     private void setVrModeAllowedLocked(boolean allowed) {
         if (mVrModeAllowed != allowed) {
             mVrModeAllowed = allowed;
-            Slog.i(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
+            if (DBG) Slog.d(TAG, "VR mode is " + ((allowed) ? "allowed" : "disallowed"));
             if (mVrModeAllowed) {
                 consumeAndApplyPendingStateLocked();
             } else {
index 972623c..7eebe39 100644 (file)
@@ -25,6 +25,7 @@ import static android.provider.Settings.ACTION_MANAGE_OVERLAY_PERMISSION;
 
 import android.app.Notification;
 import android.app.NotificationChannel;
+import android.app.NotificationChannelGroup;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
@@ -45,6 +46,7 @@ class AlertWindowNotification {
     private static final int NOTIFICATION_ID = 0;
 
     private static int sNextRequestCode = 0;
+    private static NotificationChannelGroup sChannelGroup;
     private final int mRequestCode;
     private final WindowManagerService mService;
     private String mNotificationTag;
@@ -61,6 +63,12 @@ class AlertWindowNotification {
         mNotificationTag = CHANNEL_PREFIX + mPackageName;
         mRequestCode = sNextRequestCode++;
         mIconUtilities = new IconUtilities(mService.mContext);
+        if (sChannelGroup == null) {
+            sChannelGroup = new NotificationChannelGroup(CHANNEL_PREFIX,
+                    mService.mContext.getString(
+                            R.string.alert_windows_notification_channel_group_name));
+            mNotificationManager.createNotificationChannelGroup(sChannelGroup);
+        }
     }
 
     void post() {
@@ -142,6 +150,7 @@ class AlertWindowNotification {
         channel.enableLights(false);
         channel.enableVibration(false);
         channel.setBlockableSystem(true);
+        channel.setGroup(sChannelGroup.getId());
         mNotificationManager.createNotificationChannel(channel);
     }
 
index a38addb..9d8f124 100644 (file)
@@ -52,6 +52,7 @@ import android.annotation.Nullable;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
 import android.graphics.Path;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -346,12 +347,12 @@ public class AppTransition implements Dump {
         mAppTransitionState = APP_STATE_TIMEOUT;
     }
 
-    Bitmap getAppTransitionThumbnailHeader(int taskId) {
+    GraphicBuffer getAppTransitionThumbnailHeader(int taskId) {
         AppTransitionAnimationSpec spec = mNextAppTransitionAnimationsSpecs.get(taskId);
         if (spec == null) {
             spec = mDefaultNextAppTransitionAnimationSpec;
         }
-        return spec != null ? spec.bitmap : null;
+        return spec != null ? spec.buffer : null;
     }
 
     /** Returns whether the next thumbnail transition is aspect scaled up. */
@@ -716,9 +717,9 @@ public class AppTransition implements Dump {
     }
 
     private void putDefaultNextAppTransitionCoordinates(int left, int top, int width, int height,
-            Bitmap bitmap) {
+            GraphicBuffer buffer) {
         mDefaultNextAppTransitionAnimationSpec = new AppTransitionAnimationSpec(-1 /* taskId */,
-                bitmap, new Rect(left, top, left + width, top + height));
+                buffer, new Rect(left, top, left + width, top + height));
     }
 
     /**
@@ -943,7 +944,7 @@ public class AppTransition implements Dump {
      * when a thumbnail is specified with the pending animation override.
      */
     Animation createThumbnailAspectScaleAnimationLocked(Rect appRect, @Nullable Rect contentInsets,
-            Bitmap thumbnailHeader, final int taskId, int uiMode, int orientation) {
+            GraphicBuffer thumbnailHeader, final int taskId, int uiMode, int orientation) {
         Animation a;
         final int thumbWidthI = thumbnailHeader.getWidth();
         final float thumbWidth = thumbWidthI > 0 ? thumbWidthI : 1;
@@ -1296,7 +1297,7 @@ public class AppTransition implements Dump {
      * when a thumbnail is specified with the pending animation override.
      */
     Animation createThumbnailScaleAnimationLocked(int appWidth, int appHeight, int transit,
-            Bitmap thumbnailHeader) {
+            GraphicBuffer thumbnailHeader) {
         Animation a;
         getDefaultNextAppTransitionStartRect(mTmpRect);
         final int thumbWidthI = thumbnailHeader.getWidth();
@@ -1341,7 +1342,7 @@ public class AppTransition implements Dump {
             int transit, int taskId) {
         final int appWidth = containingFrame.width();
         final int appHeight = containingFrame.height();
-        Bitmap thumbnailHeader = getAppTransitionThumbnailHeader(taskId);
+        final GraphicBuffer thumbnailHeader = getAppTransitionThumbnailHeader(taskId);
         Animation a;
         getDefaultNextAppTransitionStartRect(mTmpRect);
         final int thumbWidthI = thumbnailHeader != null ? thumbnailHeader.getWidth() : appWidth;
@@ -1714,7 +1715,7 @@ public class AppTransition implements Dump {
         }
     }
 
-    void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
+    void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY,
                                            IRemoteCallback startedCallback, boolean scaleUp) {
         if (isTransitionSet()) {
             clear();
@@ -1729,7 +1730,7 @@ public class AppTransition implements Dump {
         }
     }
 
-    void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX, int startY,
+    void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX, int startY,
             int targetWidth, int targetHeight, IRemoteCallback startedCallback, boolean scaleUp) {
         if (isTransitionSet()) {
             clear();
@@ -1763,7 +1764,7 @@ public class AppTransition implements Dump {
                             // to be set.
                             Rect rect = spec.rect;
                             putDefaultNextAppTransitionCoordinates(rect.left, rect.top,
-                                    rect.width(), rect.height(), spec.bitmap);
+                                    rect.width(), rect.height(), spec.buffer);
                         }
                     }
                 }
index 1a685eb..6640184 100644 (file)
@@ -19,7 +19,6 @@ package com.android.server.wm;
 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
 import static com.android.server.wm.AppTransition.TRANSIT_UNSET;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_APP_TRANSITIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
@@ -381,6 +380,7 @@ public class AppWindowContainerController
                 // if made visible again.
                 wtoken.removeDeadWindows();
                 wtoken.setVisibleBeforeClientHidden();
+                mService.mUnknownAppVisibilityController.appRemovedOrHidden(wtoken);
             } else {
                 if (!mService.mAppTransition.isTransitionSet()
                         && mService.mAppTransition.isReady()) {
index 37ebfd3..71ecaf6 100644 (file)
@@ -52,7 +52,6 @@ import static com.android.server.wm.WindowManagerService.logWithStack;
 
 import android.annotation.NonNull;
 import android.app.Activity;
-import android.app.ActivityManager;
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -526,7 +525,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
         boolean delayed = setVisibility(null, false, TRANSIT_UNSET, true, mVoiceInteraction);
 
         mService.mOpeningApps.remove(this);
-        mService.mUnknownAppVisibilityController.appRemoved(this);
+        mService.mUnknownAppVisibilityController.appRemovedOrHidden(this);
         mService.mTaskSnapshotController.onAppRemoved(this);
         waitingToShow = false;
         if (mService.mClosingApps.contains(this)) {
@@ -1108,7 +1107,7 @@ class AppWindowToken extends WindowToken implements WindowManagerService.AppFree
                 mAppAnimator.lastFreezeDuration = 0;
                 mService.mAppsFreezingScreen++;
                 if (mService.mAppsFreezingScreen == 1) {
-                    mService.startFreezingDisplayLocked(false, 0, 0);
+                    mService.startFreezingDisplayLocked(false, 0, 0, getDisplayContent());
                     mService.mH.removeMessages(H.APP_FREEZE_TIMEOUT);
                     mService.mH.sendEmptyMessageDelayed(H.APP_FREEZE_TIMEOUT, 2000);
                 }
index 221e795..ccc8f63 100644 (file)
@@ -987,7 +987,7 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
         }
 
         if (!rotateSeamlessly) {
-            mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1]);
+            mService.startFreezingDisplayLocked(inTransaction, anim[0], anim[1], this);
             // startFreezingDisplayLocked can reset the ScreenRotationAnimation.
             screenRotationAnimation = mService.mAnimator.getScreenRotationAnimationLocked(
                     mDisplayId);
@@ -3492,10 +3492,15 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
 
             if (win != null) {
                 final int req = win.mAttrs.screenOrientation;
-                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
                 if (policy.isKeyguardHostWindow(win.mAttrs)) {
                     mLastKeyguardForcedOrientation = req;
+                    if (mService.mKeyguardGoingAway) {
+                        // Keyguard can't affect the orientation if it is going away...
+                        mLastWindowForcedOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
+                        return SCREEN_ORIENTATION_UNSET;
+                    }
                 }
+                if (DEBUG_ORIENTATION) Slog.v(TAG_WM, win + " forcing orientation to " + req);
                 return (mLastWindowForcedOrientation = req);
             }
 
index fc4ec28..9a9e29a 100644 (file)
@@ -92,17 +92,16 @@ class PinnedStackController {
     private final Rect mStableInsets = new Rect();
 
     // The size and position information that describes where the pinned stack will go by default.
+    private int mDefaultMinSize;
     private int mDefaultStackGravity;
     private float mDefaultAspectRatio;
     private Point mScreenEdgeInsets;
+    private int mCurrentMinSize;
 
     // The aspect ratio bounds of the PIP.
     private float mMinAspectRatio;
     private float mMaxAspectRatio;
 
-    // The minimum edge size of the normal PiP bounds.
-    private int mMinSize;
-
     // Temp vars for calculation
     private final DisplayMetrics mTmpMetrics = new DisplayMetrics();
     private final Rect mTmpInsets = new Rect();
@@ -124,6 +123,13 @@ class PinnedStackController {
         }
 
         @Override
+        public void setMinEdgeSize(int minEdgeSize) {
+            mHandler.post(() -> {
+                mCurrentMinSize = Math.max(mDefaultMinSize, minEdgeSize);
+            });
+        }
+
+        @Override
         public int getDisplayRotation() {
             synchronized (mService.mWindowMap) {
                 return mDisplayInfo.rotation;
@@ -160,10 +166,12 @@ class PinnedStackController {
      */
     private void reloadResources() {
         final Resources res = mService.mContext.getResources();
-        mMinSize = res.getDimensionPixelSize(
+        mDefaultMinSize = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
+        mCurrentMinSize = mDefaultMinSize;
         mDefaultAspectRatio = res.getFloat(
                 com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
+        mAspectRatio = mDefaultAspectRatio;
         final String screenEdgeInsetsDpString = res.getString(
                 com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
         final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
@@ -212,11 +220,15 @@ class PinnedStackController {
      * Returns the current bounds (or the default bounds if there are no current bounds) with the
      * specified aspect ratio.
      */
-    Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio) {
+    Rect transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio,
+            boolean useCurrentMinEdgeSize) {
         // Save the snap fraction, calculate the aspect ratio based on screen size
         final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
                 getMovementBounds(stackBounds));
-        final Size size = getSize(aspectRatio);
+
+        final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize;
+        final Size size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize,
+                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
         final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f);
         final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f);
         stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight());
@@ -228,16 +240,6 @@ class PinnedStackController {
     }
 
     /**
-     * @return the size of the PIP based on the given {@param aspectRatio}.
-     */
-    Size getSize(float aspectRatio) {
-        synchronized (mService.mWindowMap) {
-            return mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, mMinSize,
-                    mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
-        }
-    }
-
-    /**
      * @return the default bounds to show the PIP when there is no active PIP.
      */
     Rect getDefaultBounds() {
@@ -246,7 +248,8 @@ class PinnedStackController {
             getInsetBounds(insetBounds);
 
             final Rect defaultBounds = new Rect();
-            final Size size = getSize(mDefaultAspectRatio);
+            final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
+                    mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
             Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
                     0, mIsImeShowing ? mImeHeight : 0, defaultBounds);
             return defaultBounds;
@@ -401,7 +404,8 @@ class PinnedStackController {
                     getInsetBounds(insetBounds);
                     final Rect normalBounds = getDefaultBounds();
                     if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
-                        transformBoundsToAspectRatio(normalBounds, mAspectRatio);
+                        transformBoundsToAspectRatio(normalBounds, mAspectRatio,
+                                false /* useCurrentMinEdgeSize */);
                     }
                     final Rect animatingBounds = mTmpAnimatingBoundsRect;
                     final TaskStack pinnedStack = mDisplayContent.getStackById(PINNED_STACK_ID);
index 0c628ac..989e8f2 100644 (file)
@@ -17,7 +17,6 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 
 import static com.android.server.wm.BoundsAnimationController.NO_PIP_MODE_CHANGED_CALLBACKS;
 import static com.android.server.wm.BoundsAnimationController.SCHEDULE_PIP_MODE_CHANGED_ON_END;
@@ -36,7 +35,8 @@ import java.util.List;
  */
 public class PinnedStackWindowController extends StackWindowController {
 
-    private Rect mTmpBoundsRect = new Rect();
+    private Rect mTmpFromBounds = new Rect();
+    private Rect mTmpToBounds = new Rect();
 
     public PinnedStackWindowController(int stackId, PinnedStackWindowListener listener,
             int displayId, boolean onTop, Rect outBounds) {
@@ -44,16 +44,16 @@ public class PinnedStackWindowController extends StackWindowController {
     }
 
     /**
-     * @param useExistingStackBounds Apply {@param aspectRatio} to the existing target stack bounds
-     *                               if possible
+     * @return the {@param currentStackBounds} transformed to the give {@param aspectRatio}.  If
+     *         {@param currentStackBounds} is null, then the {@param aspectRatio} is applied to the
+     *         default bounds.
      */
-    public Rect getPictureInPictureBounds(float aspectRatio, boolean useExistingStackBounds) {
+    public Rect getPictureInPictureBounds(float aspectRatio, Rect stackBounds) {
         synchronized (mWindowMap) {
             if (!mService.mSupportsPictureInPicture || mContainer == null) {
                 return null;
             }
 
-            final Rect stackBounds;
             final DisplayContent displayContent = mContainer.getDisplayContent();
             if (displayContent == null) {
                 return null;
@@ -61,18 +61,14 @@ public class PinnedStackWindowController extends StackWindowController {
 
             final PinnedStackController pinnedStackController =
                     displayContent.getPinnedStackController();
-            if (useExistingStackBounds) {
-                // If the stack exists, then use its final bounds to calculate the new aspect ratio
-                // bounds
-                stackBounds = new Rect();
-                mContainer.getAnimationOrCurrentBounds(stackBounds);
-            } else {
-                // Otherwise, just calculate the aspect ratio bounds from the default bounds
+            if (stackBounds == null) {
+                // Calculate the aspect ratio bounds from the default bounds
                 stackBounds = pinnedStackController.getDefaultBounds();
             }
 
             if (pinnedStackController.isValidPictureInPictureAspectRatio(aspectRatio)) {
-                return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio);
+                return pinnedStackController.transformBoundsToAspectRatio(stackBounds, aspectRatio,
+                        true /* useCurrentMinEdgeSize */);
             } else {
                 return stackBounds;
             }
@@ -104,10 +100,10 @@ public class PinnedStackWindowController extends StackWindowController {
                 }
                 schedulePipModeChangedState = SCHEDULE_PIP_MODE_CHANGED_ON_START;
 
-                mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpBoundsRect);
-                if (!mTmpBoundsRect.isEmpty()) {
+                mService.getStackBounds(FULLSCREEN_WORKSPACE_STACK_ID, mTmpToBounds);
+                if (!mTmpToBounds.isEmpty()) {
                     // If there is a fullscreen bounds, use that
-                    toBounds = new Rect(mTmpBoundsRect);
+                    toBounds = new Rect(mTmpToBounds);
                 } else {
                     // Otherwise, use the display bounds
                     toBounds = new Rect();
@@ -142,16 +138,15 @@ public class PinnedStackWindowController extends StackWindowController {
                 return;
             }
 
-            final Rect toBounds = getPictureInPictureBounds(aspectRatio,
-                    true /* useExistingStackBounds */);
-            final Rect targetBounds = new Rect();
-            mContainer.getAnimationOrCurrentBounds(targetBounds);
             final PinnedStackController pinnedStackController =
                     mContainer.getDisplayContent().getPinnedStackController();
 
             if (Float.compare(aspectRatio, pinnedStackController.getAspectRatio()) != 0) {
-                if (!toBounds.equals(targetBounds)) {
-                    animateResizePinnedStack(toBounds, null /* sourceHintBounds */,
+                mContainer.getAnimationOrCurrentBounds(mTmpFromBounds);
+                mTmpToBounds.set(mTmpFromBounds);
+                getPictureInPictureBounds(aspectRatio, mTmpToBounds);
+                if (!mTmpToBounds.equals(mTmpFromBounds)) {
+                    animateResizePinnedStack(mTmpToBounds, null /* sourceHintBounds */,
                             -1 /* duration */, false /* fromFullscreen */);
                 }
                 pinnedStackController.setAspectRatio(
index 818df01..bfebca8 100644 (file)
@@ -163,6 +163,8 @@ class Task extends WindowContainer<AppWindowToken> implements DimLayer.DimLayerU
 
     @VisibleForTesting
     boolean shouldDeferRemoval() {
+        // TODO: This should probably return false if mChildren.isEmpty() regardless if the stack
+        // is animating...
         return hasWindowsAlive() && mStack.isAnimating();
     }
 
index b266778..bf8fabd 100644 (file)
 package com.android.server.wm;
 
 import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
-import static android.graphics.Bitmap.Config.ARGB_8888;
-import static android.graphics.Bitmap.Config.HARDWARE;
 
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityManager.TaskSnapshot;
+import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.GraphicBuffer;
 import android.graphics.Rect;
 import android.os.Environment;
 import android.os.Handler;
 import android.util.ArraySet;
+import android.view.DisplayListCanvas;
+import android.view.RenderNode;
+import android.view.ThreadedRenderer;
 import android.view.WindowManager.LayoutParams;
 import android.view.WindowManagerPolicy.ScreenOffListener;
 import android.view.WindowManagerPolicy.StartingSurface;
@@ -86,9 +87,16 @@ class TaskSnapshotController {
     private final ArraySet<Task> mTmpTasks = new ArraySet<>();
     private final Handler mHandler = new Handler();
 
+    /**
+     * Flag indicating whether we are running on an Android TV device.
+     */
+    private final boolean mIsRunningOnTv;
+
     TaskSnapshotController(WindowManagerService service) {
         mService = service;
         mCache = new TaskSnapshotCache(mService, mLoader);
+        mIsRunningOnTv = mService.mContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_LEANBACK);
     }
 
     void systemReady() {
@@ -109,7 +117,7 @@ class TaskSnapshotController {
     }
 
     private void handleClosingApps(ArraySet<AppWindowToken> closingApps) {
-        if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+        if (shouldDisableSnapshots()) {
             return;
         }
 
@@ -185,6 +193,10 @@ class TaskSnapshotController {
                 1f /* scale */);
     }
 
+    private boolean shouldDisableSnapshots() {
+        return !ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic() || mIsRunningOnTv;
+    }
+
     private Rect minRect(Rect rect1, Rect rect2) {
         return new Rect(Math.min(rect1.left, rect2.left),
                 Math.min(rect1.top, rect2.top),
@@ -238,19 +250,22 @@ class TaskSnapshotController {
         final int color = task.getTaskDescription().getBackgroundColor();
         final int statusBarColor = task.getTaskDescription().getStatusBarColor();
         final int navigationBarColor = task.getTaskDescription().getNavigationBarColor();
-        final Bitmap b = Bitmap.createBitmap(mainWindow.getFrameLw().width(),
-                mainWindow.getFrameLw().height(), ARGB_8888);
-        final Canvas c = new Canvas(b);
-        c.drawColor(color);
         final LayoutParams attrs = mainWindow.getAttrs();
         final SystemBarBackgroundPainter decorPainter = new SystemBarBackgroundPainter(attrs.flags,
                 attrs.privateFlags, attrs.systemUiVisibility, statusBarColor, navigationBarColor);
+        final int width = mainWindow.getFrameLw().width();
+        final int height = mainWindow.getFrameLw().height();
+
+        final RenderNode node = RenderNode.create("TaskSnapshotController", null);
+        node.setLeftTopRightBottom(0, 0, width, height);
+        node.setClipToBounds(false);
+        final DisplayListCanvas c = node.start(width, height);
+        c.drawColor(color);
         decorPainter.setInsets(mainWindow.mContentInsets, mainWindow.mStableInsets);
         decorPainter.drawDecors(c, null /* statusBarExcludeFrame */);
+        node.end(c);
+        final Bitmap hwBitmap = ThreadedRenderer.createHardwareBitmap(node, width, height);
 
-        // Flush writer.
-        c.setBitmap(null);
-        final Bitmap hwBitmap = b.copy(HARDWARE, false /* isMutable */);
         return new TaskSnapshot(hwBitmap.createGraphicBufferHandle(),
                 topChild.getConfiguration().orientation, mainWindow.mStableInsets,
                 false /* reduced */, 1.0f /* scale */);
@@ -295,7 +310,7 @@ class TaskSnapshotController {
      * Called when screen is being turned off.
      */
     void screenTurningOff(ScreenOffListener listener) {
-        if (!ENABLE_TASK_SNAPSHOTS || ActivityManager.isLowRamDeviceStatic()) {
+        if (shouldDisableSnapshots()) {
             listener.onScreenOff();
             return;
         }
index 3a116bb..551e3bf 100644 (file)
@@ -102,6 +102,8 @@ class TaskSnapshotSurface implements StartingSurface {
             | FLAG_SCALED
             | FLAG_SECURE;
 
+    private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+
     private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
     private static final int MSG_REPORT_DRAW = 0;
     private static final String TITLE_FORMAT = "SnapshotStartingWindow for taskId=%s";
@@ -160,7 +162,8 @@ class TaskSnapshotSurface implements StartingSurface {
             layoutParams.flags = (windowFlags & ~FLAG_INHERIT_EXCLUDES)
                     | FLAG_NOT_FOCUSABLE
                     | FLAG_NOT_TOUCHABLE;
-            layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT;
+            layoutParams.privateFlags = PRIVATE_FLAG_TASK_SNAPSHOT
+                    | (windowPrivateFlags & PRIVATE_FLAG_INHERITS);
             layoutParams.token = token.token;
             layoutParams.width = LayoutParams.MATCH_PARENT;
             layoutParams.height = LayoutParams.MATCH_PARENT;
index eff8ed9..39878cc 100644 (file)
@@ -109,6 +109,7 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
 
     /** Application tokens that are exiting, but still on screen for animations. */
     final AppTokenList mExitingAppTokens = new AppTokenList();
+    final AppTokenList mTmpAppTokens = new AppTokenList();
 
     /** Detach this stack from its display when animation completes. */
     // TODO: maybe tie this to WindowContainer#removeChild some how...
@@ -1626,9 +1627,14 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
 
         // TODO: Why aren't we just using the loop above for this? mAppAnimator.animating isn't set
         // below but is set in the loop above. See if it really matters...
-        final int exitingCount = mExitingAppTokens.size();
-        for (int i = 0; i < exitingCount; i++) {
-            final AppWindowAnimator appAnimator = mExitingAppTokens.get(i).mAppAnimator;
+
+        // Clear before using.
+        mTmpAppTokens.clear();
+        // We copy the list as things can be removed from the exiting token list while we are
+        // processing.
+        mTmpAppTokens.addAll(mExitingAppTokens);
+        for (int i = 0; i < mTmpAppTokens.size(); i++) {
+            final AppWindowAnimator appAnimator = mTmpAppTokens.get(i).mAppAnimator;
             appAnimator.wasAnimating = appAnimator.animating;
             if (appAnimator.stepAnimationLocked(currentTime)) {
                 mService.mAnimator.setAnimating(true);
@@ -1641,6 +1647,8 @@ public class TaskStack extends WindowContainer<Task> implements DimLayer.DimLaye
                         "updateWindowsApps...: done animating exiting " + appAnimator.mAppToken);
             }
         }
+        // Clear to avoid holding reference to tokens.
+        mTmpAppTokens.clear();
     }
 
     @Override
index 8f4f09e..eb751fa 100644 (file)
@@ -84,9 +84,9 @@ class UnknownAppVisibilityController {
         return builder.toString();
     }
 
-    void appRemoved(@NonNull AppWindowToken appWindow) {
+    void appRemovedOrHidden(@NonNull AppWindowToken appWindow) {
         if (DEBUG_UNKNOWN_APP_VISIBILITY) {
-            Slog.d(TAG, "App removed appWindow=" + appWindow);
+            Slog.d(TAG, "App removed or hidden appWindow=" + appWindow);
         }
         mUnknownApps.remove(appWindow);
     }
index 8279b51..6d5673e 100644 (file)
@@ -52,7 +52,7 @@ public class WindowManagerDebugConfig {
     static final boolean DEBUG_CONFIGURATION = false;
     static final boolean DEBUG_APP_TRANSITIONS = false;
     static final boolean DEBUG_STARTING_WINDOW_VERBOSE = false;
-    static final boolean DEBUG_STARTING_WINDOW = DEBUG_STARTING_WINDOW_VERBOSE || true;
+    static final boolean DEBUG_STARTING_WINDOW = DEBUG_STARTING_WINDOW_VERBOSE || false;
     static final boolean DEBUG_WALLPAPER = false;
     static final boolean DEBUG_WALLPAPER_LIGHT = false || DEBUG_WALLPAPER;
     static final boolean DEBUG_DRAG = false;
index a15891b..e5af9d2 100644 (file)
@@ -20,7 +20,6 @@ import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
 import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.AppOpsManager.OP_SYSTEM_ALERT_WINDOW;
 import static android.app.StatusBarManager.DISABLE_MASK;
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
@@ -33,6 +32,7 @@ import static android.os.Process.THREAD_PRIORITY_DISPLAY;
 import static android.os.Process.myPid;
 import static android.os.UserHandle.USER_NULL;
 import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW;
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
@@ -123,6 +123,7 @@ import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
 import android.graphics.Matrix;
 import android.graphics.PixelFormat;
 import android.graphics.Point;
@@ -157,6 +158,7 @@ import android.os.Trace;
 import android.os.UserHandle;
 import android.os.WorkSource;
 import android.provider.Settings;
+import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -349,6 +351,7 @@ public class WindowManagerService extends IWindowManager.Stub
     private static final int ANIMATION_DURATION_SCALE = 2;
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
+    boolean mKeyguardGoingAway;
 
     private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
         @Override
@@ -599,7 +602,7 @@ public class WindowManagerService extends IWindowManager.Stub
 
     final UnknownAppVisibilityController mUnknownAppVisibilityController =
             new UnknownAppVisibilityController(this);
-    final TaskSnapshotController mTaskSnapshotController = new TaskSnapshotController(this);
+    final TaskSnapshotController mTaskSnapshotController;
 
     boolean mIsTouchDevice;
 
@@ -615,6 +618,11 @@ public class WindowManagerService extends IWindowManager.Stub
     WindowState mCurrentFocus = null;
     WindowState mLastFocus = null;
 
+    /** Windows added since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
+    private final ArrayList<WindowState> mWinAddedSinceNullFocus = new ArrayList<>();
+    /** Windows removed since {@link #mCurrentFocus} was set to null. Used for ANR blaming. */
+    private final ArrayList<WindowState> mWinRemovedSinceNullFocus = new ArrayList<>();
+
     /** This just indicates the window the input method is on top of, not
      * necessarily the window its input is going to. */
     WindowState mInputMethodTarget = null;
@@ -717,6 +725,9 @@ public class WindowManagerService extends IWindowManager.Stub
     // For frozen screen animations.
     private int mExitAnimId, mEnterAnimId;
 
+    // The display that the rotation animation is applying to.
+    private int mFrozenDisplayId;
+
     /** Skip repeated AppWindowTokens initialization. Note that AppWindowsToken's version of this
      * is a long initialized to Long.MIN_VALUE so that it doesn't match this value on startup. */
     int mTransactionSequence;
@@ -982,6 +993,7 @@ public class WindowManagerService extends IWindowManager.Stub
 
         mWindowPlacerLocked = new WindowSurfacePlacer(this);
         mPolicy = policy;
+        mTaskSnapshotController = new TaskSnapshotController(this);
 
         LocalServices.addService(WindowManagerPolicy.class, mPolicy);
 
@@ -1379,6 +1391,9 @@ public class WindowManagerService extends IWindowManager.Stub
             // From now on, no exceptions or errors allowed!
 
             res = WindowManagerGlobal.ADD_OKAY;
+            if (mCurrentFocus == null) {
+                mWinAddedSinceNullFocus.add(win);
+            }
 
             if (excludeWindowTypeFromTapOutTask(type)) {
                 displayContent.mTapExcludedWindows.add(win);
@@ -1665,6 +1680,9 @@ public class WindowManagerService extends IWindowManager.Stub
             mAppOps.finishOp(win.mAppOp, win.getOwningUid(), win.getOwningPackage());
         }
 
+        if (mCurrentFocus == null) {
+            mWinRemovedSinceNullFocus.add(win);
+        }
         mPendingRemove.remove(win);
         mResizingWindows.remove(win);
         mWindowsChanged = true;
@@ -2436,7 +2454,7 @@ public class WindowManagerService extends IWindowManager.Stub
                 } else {
                     mPolicy.selectRotationAnimationLw(anim);
                 }
-                startFreezingDisplayLocked(false, anim[0], anim[1]);
+                startFreezingDisplayLocked(false, anim[0], anim[1], displayContent);
                 config = new Configuration(mTempConfiguration);
             }
         }
@@ -2629,7 +2647,7 @@ public class WindowManagerService extends IWindowManager.Stub
     }
 
     @Override
-    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX,
+    public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX,
             int startY, IRemoteCallback startedCallback, boolean scaleUp) {
         synchronized(mWindowMap) {
             mAppTransition.overridePendingAppTransitionThumb(srcThumb, startX, startY,
@@ -2638,7 +2656,7 @@ public class WindowManagerService extends IWindowManager.Stub
     }
 
     @Override
-    public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+    public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX,
             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
             boolean scaleUp) {
         synchronized(mWindowMap) {
@@ -2876,6 +2894,12 @@ public class WindowManagerService extends IWindowManager.Stub
         }
     }
 
+    public void setKeyguardGoingAway(boolean keyguardGoingAway) {
+        synchronized (mWindowMap) {
+            mKeyguardGoingAway = keyguardGoingAway;
+        }
+    }
+
     // -------------------------------------------------------------
     // Misc IWindowSession methods
     // -------------------------------------------------------------
@@ -3577,8 +3601,16 @@ public class WindowManagerService extends IWindowManager.Stub
     // only allow disables from pids which have count on, etc.
     @Override
     public void showStrictModeViolation(boolean on) {
-        int pid = Binder.getCallingPid();
-        mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, on ? 1 : 0, pid));
+        final int pid = Binder.getCallingPid();
+        if (on) {
+            // Show the visualization, and enqueue a second message to tear it
+            // down if we don't hear back from the app.
+            mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 1, pid));
+            mH.sendMessageDelayed(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid),
+                    DateUtils.SECOND_IN_MILLIS);
+        } else {
+            mH.sendMessage(mH.obtainMessage(H.SHOW_STRICT_MODE_VIOLATION, 0, pid));
+        }
     }
 
     private void showStrictModeViolation(int arg, int pid) {
@@ -3816,20 +3848,22 @@ public class WindowManagerService extends IWindowManager.Stub
         long origId = Binder.clearCallingIdentity();
 
         try {
-            final boolean rotationChanged;
             // TODO(multi-display): Update rotation for different displays separately.
-            final DisplayContent displayContent = getDefaultDisplayContentLocked();
+            final boolean rotationChanged;
+            final int displayId;
             synchronized (mWindowMap) {
+                final DisplayContent displayContent = getDefaultDisplayContentLocked();
                 rotationChanged = displayContent.updateRotationUnchecked(
                         false /* inTransaction */);
                 if (!rotationChanged || forceRelayout) {
-                    getDefaultDisplayContentLocked().setLayoutNeeded();
+                    displayContent.setLayoutNeeded();
                     mWindowPlacerLocked.performSurfacePlacement();
                 }
+                displayId = displayContent.getDisplayId();
             }
 
             if (rotationChanged || alwaysSendConfiguration) {
-                sendNewConfiguration(displayContent.getDisplayId());
+                sendNewConfiguration(displayId);
             }
         } finally {
             Binder.restoreCallingIdentity(origId);
@@ -5534,7 +5568,7 @@ public class WindowManagerService extends IWindowManager.Stub
         if (configChanged) {
             mWaitingForConfig = true;
             startFreezingDisplayLocked(false /* inTransaction */, 0 /* exitAnim */,
-                    0 /* enterAnim */);
+                    0 /* enterAnim */, displayContent);
             mH.obtainMessage(H.SEND_NEW_CONFIGURATION, displayId).sendToTarget();
         }
 
@@ -5794,6 +5828,11 @@ public class WindowManagerService extends IWindowManager.Stub
             mCurrentFocus = newFocus;
             mLosingFocus.remove(newFocus);
 
+            if (mCurrentFocus != null) {
+                mWinAddedSinceNullFocus.clear();
+                mWinRemovedSinceNullFocus.clear();
+            }
+
             int focusChanged = mPolicy.focusChangedLw(oldFocus, newFocus);
 
             if (imWindowChanged && oldFocus != mInputMethodWindow) {
@@ -5836,6 +5875,12 @@ public class WindowManagerService extends IWindowManager.Stub
     }
 
     void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim) {
+        startFreezingDisplayLocked(inTransaction, exitAnim, enterAnim,
+                getDefaultDisplayContentLocked());
+    }
+
+    void startFreezingDisplayLocked(boolean inTransaction, int exitAnim, int enterAnim,
+            DisplayContent displayContent) {
         if (mDisplayFrozen) {
             return;
         }
@@ -5856,6 +5901,10 @@ public class WindowManagerService extends IWindowManager.Stub
         mDisplayFreezeTime = SystemClock.elapsedRealtime();
         mLastFinishedFreezeSource = null;
 
+        // {@link mDisplayFrozen} prevents us from freezing on multiple displays at the same time.
+        // As a result, we only track the display that has initially froze the screen.
+        mFrozenDisplayId = displayContent.getDisplayId();
+
         mInputMonitor.freezeInputDispatchingLw();
 
         // Clear the last input window -- that is just used for
@@ -5875,10 +5924,8 @@ public class WindowManagerService extends IWindowManager.Stub
         if (CUSTOM_SCREEN_ROTATION) {
             mExitAnimId = exitAnim;
             mEnterAnimId = enterAnim;
-            final DisplayContent displayContent = getDefaultDisplayContentLocked();
-            final int displayId = displayContent.getDisplayId();
             ScreenRotationAnimation screenRotationAnimation =
-                    mAnimator.getScreenRotationAnimationLocked(displayId);
+                    mAnimator.getScreenRotationAnimationLocked(mFrozenDisplayId);
             if (screenRotationAnimation != null) {
                 screenRotationAnimation.kill();
             }
@@ -5889,8 +5936,10 @@ public class WindowManagerService extends IWindowManager.Stub
             // TODO(multidisplay): rotation on main screen only.
             displayContent.updateDisplayInfo();
             screenRotationAnimation = new ScreenRotationAnimation(mContext, displayContent,
-                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure, this);
-            mAnimator.setScreenRotationAnimationLocked(displayId, screenRotationAnimation);
+                    mFxSession, inTransaction, mPolicy.isDefaultOrientationForced(), isSecure,
+                    this);
+            mAnimator.setScreenRotationAnimationLocked(mFrozenDisplayId,
+                    screenRotationAnimation);
         }
     }
 
@@ -5914,6 +5963,13 @@ public class WindowManagerService extends IWindowManager.Stub
         if (DEBUG_ORIENTATION) Slog.d(TAG_WM,
                 "stopFreezingDisplayLocked: Unfreezing now");
 
+        final DisplayContent displayContent = mRoot.getDisplayContent(mFrozenDisplayId);
+
+        // We must make a local copy of the displayId as it can be potentially overwritten later on
+        // in this method. For example, {@link startFreezingDisplayLocked} may be called as a result
+        // of update rotation, but we reference the frozen display after that call in this method.
+        final int displayId = mFrozenDisplayId;
+        mFrozenDisplayId = INVALID_DISPLAY;
         mDisplayFrozen = false;
         mLastDisplayFreezeDuration = (int)(SystemClock.elapsedRealtime() - mDisplayFreezeTime);
         StringBuilder sb = new StringBuilder(128);
@@ -5932,8 +5988,6 @@ public class WindowManagerService extends IWindowManager.Stub
 
         boolean updateRotation = false;
 
-        final DisplayContent displayContent = getDefaultDisplayContentLocked();
-        final int displayId = displayContent.getDisplayId();
         ScreenRotationAnimation screenRotationAnimation =
                 mAnimator.getScreenRotationAnimationLocked(displayId);
         if (CUSTOM_SCREEN_ROTATION && screenRotationAnimation != null
@@ -6457,7 +6511,7 @@ public class WindowManagerService extends IWindowManager.Stub
                     pw.print(" window="); pw.print(mWindowAnimationScaleSetting);
                     pw.print(" transition="); pw.print(mTransitionAnimationScaleSetting);
                     pw.print(" animator="); pw.println(mAnimatorDurationScaleSetting);
-            pw.print(" mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
+            pw.print("  mSkipAppTransitionAnimation=");pw.println(mSkipAppTransitionAnimation);
             pw.println("  mLayoutToAnim:");
             mAppTransition.dump(pw, "    ");
         }
@@ -6528,6 +6582,12 @@ public class WindowManagerService extends IWindowManager.Stub
         if (reason != null) {
             pw.println("  Reason: " + reason);
         }
+        if (!mWinAddedSinceNullFocus.isEmpty()) {
+            pw.println("  Windows added since null focus: " + mWinAddedSinceNullFocus);
+        }
+        if (!mWinRemovedSinceNullFocus.isEmpty()) {
+            pw.println("  Windows removed since null focus: " + mWinRemovedSinceNullFocus);
+        }
         pw.println();
         dumpWindowsNoHeaderLocked(pw, true, null);
         pw.println();
@@ -6890,9 +6950,11 @@ public class WindowManagerService extends IWindowManager.Stub
                 "registerDockedStackListener()")) {
             return;
         }
-        // TODO(multi-display): The listener is registered on the default display only.
-        getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
-                listener);
+        synchronized (mWindowMap) {
+            // TODO(multi-display): The listener is registered on the default display only.
+            getDefaultDisplayContentLocked().mDividerControllerLocked.registerDockedStackListener(
+                    listener);
+        }
     }
 
     @Override
@@ -7173,6 +7235,11 @@ public class WindowManagerService extends IWindowManager.Stub
         }
 
         @Override
+        public boolean isKeyguardGoingAway() {
+            return WindowManagerService.this.mKeyguardGoingAway;
+        }
+
+        @Override
         public void showGlobalActions() {
             WindowManagerService.this.showGlobalActions();
         }
index acd7703..f74948f 100644 (file)
@@ -18,7 +18,9 @@ package com.android.server.wm;
 
 import static android.app.ActivityManager.ENABLE_TASK_SNAPSHOTS;
 import static android.app.ActivityManager.StackId;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
 import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
 import static android.app.ActivityManager.isLowRamDeviceStatic;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
@@ -761,16 +763,19 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
             final WindowState imeWin = mService.mInputMethodWindow;
             // IME is up and obscuring this window. Adjust the window position so it is visible.
             if (imeWin != null && imeWin.isVisibleNow() && mService.mInputMethodTarget == this) {
-                    if (windowsAreFloating && mContainingFrame.bottom > contentFrame.bottom) {
-                        // In freeform we want to move the top up directly.
-                        // TODO: Investigate why this is contentFrame not parentFrame.
-                        mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
-                    } else if (mContainingFrame.bottom > parentFrame.bottom) {
-                        // But in docked we want to behave like fullscreen
-                        // and behave as if the task were given smaller bounds
-                        // for the purposes of layout.
-                        mContainingFrame.bottom = parentFrame.bottom;
-                    }
+                final int stackId = getStackId();
+                if (stackId == FREEFORM_WORKSPACE_STACK_ID
+                        && mContainingFrame.bottom > contentFrame.bottom) {
+                    // In freeform we want to move the top up directly.
+                    // TODO: Investigate why this is contentFrame not parentFrame.
+                    mContainingFrame.top -= mContainingFrame.bottom - contentFrame.bottom;
+                } else if (stackId != PINNED_STACK_ID
+                        && mContainingFrame.bottom > parentFrame.bottom) {
+                    // But in docked we want to behave like fullscreen and behave as if the task
+                    // were given smaller bounds for the purposes of layout. Skip adjustments for
+                    // the pinned stack, they are handled separately in the PinnedStackController.
+                    mContainingFrame.bottom = parentFrame.bottom;
+                }
             }
 
             if (windowsAreFloating) {
@@ -2202,18 +2207,30 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         }
     }
 
-    void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration) {
+    void prepareWindowToDisplayDuringRelayout(MergedConfiguration mergedConfiguration,
+            boolean wasVisible) {
+        // We need to turn on screen regardless of visibility.
+        if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
+            if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
+            mTurnOnScreen = true;
+        }
+
+        // If we were already visible, skip rest of preparation.
+        if (wasVisible) {
+            if (DEBUG_VISIBILITY) Slog.v(TAG,
+                    "Already visible and does not turn on screen, skip preparing: " + this);
+            return;
+        }
+
         if ((mAttrs.softInputMode & SOFT_INPUT_MASK_ADJUST)
                 == SOFT_INPUT_ADJUST_RESIZE) {
             mLayoutNeeded = true;
         }
+
         if (isDrawnLw() && mService.okToDisplay()) {
             mWinAnimator.applyEnterAnimationLocked();
         }
-        if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
-            if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
-            mTurnOnScreen = true;
-        }
+
         if (isConfigChanged()) {
             final Configuration globalConfig = mService.mRoot.getConfiguration();
             final Configuration overrideConfig = getMergedOverrideConfiguration();
@@ -3407,7 +3424,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
             pw.print(prefix); pw.print("mOrientationChanging=");
                     pw.print(mOrientationChanging);
                     pw.print(" mAppFreezing="); pw.print(mAppFreezing);
-                    pw.print(" mTurnOnScreen="); pw.println(mTurnOnScreen);
+                    pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen);
                     pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
         }
         if (mLastFreezeDuration != 0) {
@@ -4348,9 +4365,9 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
         mLastVisibleLayoutRotation = getDisplayContent().getRotation();
 
         mWinAnimator.mEnteringAnimation = true;
-        if (!wasVisible) {
-            prepareWindowToDisplayDuringRelayout(mergedConfiguration);
-        }
+
+        prepareWindowToDisplayDuringRelayout(mergedConfiguration, wasVisible);
+
         if ((attrChanges & FORMAT_CHANGED) != 0) {
             // If the format can't be changed in place, preserve the old surface until the app draws
             // on the new one. This prevents blinking when we change elevation of freeform and
index d75afcf..73f8d27 100644 (file)
@@ -687,6 +687,7 @@ class WindowStateAnimator {
             mSurfaceController = new WindowSurfaceController(mSession.mSurfaceSession,
                     attrs.getTitle().toString(),
                     width, height, format, flags, this, windowType, ownerUid);
+            mSurfaceFormat = format;
 
             w.setHasSurface(true);
 
index 4a1a705..4442bb8 100644 (file)
@@ -38,8 +38,7 @@ import static com.android.server.wm.WindowManagerService.MAX_ANIMATION_DURATION;
 import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
 
 import android.content.res.Configuration;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
+import android.graphics.GraphicBuffer;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.Binder;
@@ -675,8 +674,9 @@ class WindowSurfacePlacer {
             return;
         }
         final int taskId = appToken.getTask().mTaskId;
-        Bitmap thumbnailHeader = mService.mAppTransition.getAppTransitionThumbnailHeader(taskId);
-        if (thumbnailHeader == null || thumbnailHeader.getConfig() == Bitmap.Config.ALPHA_8) {
+        final GraphicBuffer thumbnailHeader =
+                mService.mAppTransition.getAppTransitionThumbnailHeader(taskId);
+        if (thumbnailHeader == null) {
             if (DEBUG_APP_TRANSITIONS) Slog.d(TAG, "No thumbnail header bitmap for: " + taskId);
             return;
         }
@@ -694,18 +694,17 @@ class WindowSurfacePlacer {
             SurfaceControl surfaceControl = new SurfaceControl(mService.mFxSession,
                     "thumbnail anim", dirty.width(), dirty.height(),
                     PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN,
-                    appToken.windowType, window.mOwnerUid);
+                    appToken.windowType,
+                    window != null ? window.mOwnerUid : Binder.getCallingUid());
             surfaceControl.setLayerStack(display.getLayerStack());
             if (SHOW_TRANSACTIONS) {
                 Slog.i(TAG, "  THUMBNAIL " + surfaceControl + ": CREATE");
             }
 
-            // Draw the thumbnail onto the surface
+            // Transfer the thumbnail to the surface
             Surface drawSurface = new Surface();
             drawSurface.copyFrom(surfaceControl);
-            Canvas c = drawSurface.lockCanvas(dirty);
-            c.drawBitmap(thumbnailHeader, 0, 0, null);
-            drawSurface.unlockCanvasAndPost(c);
+            drawSurface.attachAndQueueBuffer(thumbnailHeader);
             drawSurface.release();
 
             // Get the thumbnail animation
index 1d44a20..6f53099 100644 (file)
@@ -185,6 +185,8 @@ public final class SystemServer {
             "com.google.android.clockwork.ThermalObserver";
     private static final String WEAR_CONNECTIVITY_SERVICE_CLASS =
             "com.google.android.clockwork.connectivity.WearConnectivityService";
+    private static final String WEAR_DISPLAY_SERVICE_CLASS =
+            "com.google.android.clockwork.display.WearDisplayService";
     private static final String WEAR_TIME_SERVICE_CLASS =
             "com.google.android.clockwork.time.WearTimeService";
     private static final String ACCOUNT_SERVICE_CLASS =
@@ -1499,6 +1501,7 @@ public final class SystemServer {
 
             if (!disableNonCoreServices) {
                 traceBeginAndSlog("StartWearTimeService");
+                mSystemServiceManager.startService(WEAR_DISPLAY_SERVICE_CLASS);
                 mSystemServiceManager.startService(WEAR_TIME_SERVICE_CLASS);
                 traceEnd();
             }
index 39caa3c..ec08874 100644 (file)
@@ -61,6 +61,7 @@ import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.argThat;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.timeout;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -102,6 +103,7 @@ public class BuzzBeepBlinkTest extends NotificationTestCase {
     private static final long[] FALLBACK_VIBRATION_PATTERN = new long[] {100, 100, 100};
     private static final VibrationEffect FALLBACK_VIBRATION =
             VibrationEffect.createWaveform(FALLBACK_VIBRATION_PATTERN, -1);
+    private static final int MAX_VIBRATION_DELAY = 1000;
 
     @Before
     public void setUp() {
@@ -309,6 +311,11 @@ public class BuzzBeepBlinkTest extends NotificationTestCase {
                 (AudioAttributes) anyObject());
     }
 
+    private void verifyDelayedVibrateLooped() {
+        verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
+                argThat(mVibrateLoopMatcher), (AudioAttributes) anyObject());
+    }
+
     private void verifyStopVibrate() {
         verify(mVibrator, times(1)).cancel();
     }
@@ -506,8 +513,8 @@ public class BuzzBeepBlinkTest extends NotificationTestCase {
 
         VibrationEffect effect = VibrationEffect.createWaveform(r.getVibration(), -1);
 
-        verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), eq(effect),
-                    (AudioAttributes) anyObject());
+        verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
+                eq(effect), (AudioAttributes) anyObject());
     }
 
     @Test
@@ -521,8 +528,8 @@ public class BuzzBeepBlinkTest extends NotificationTestCase {
 
         mService.buzzBeepBlinkLocked(r);
 
-        verify(mVibrator, times(1)).vibrate(anyInt(), anyString(), eq(FALLBACK_VIBRATION),
-                (AudioAttributes) anyObject());
+        verify(mVibrator, timeout(MAX_VIBRATION_DELAY).times(1)).vibrate(anyInt(), anyString(),
+                eq(FALLBACK_VIBRATION), (AudioAttributes) anyObject());
         verify(mRingtonePlayer, never()).playAsync
                 (anyObject(), anyObject(), anyBoolean(), anyObject());
     }
@@ -539,7 +546,7 @@ public class BuzzBeepBlinkTest extends NotificationTestCase {
 
         mService.buzzBeepBlinkLocked(r);
 
-        verifyVibrateLooped();
+        verifyDelayedVibrateLooped();
     }
 
     @Test
index 9afb2d2..bd6e379 100644 (file)
@@ -17,6 +17,7 @@
 package com.android.server.notification;
 
 import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -67,7 +68,6 @@ import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
 import com.android.server.lights.Light;
@@ -91,6 +91,8 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
     private TestableLooper mTestableLooper;
     @Mock
     private RankingHelper mRankingHelper;
+    @Mock
+    private NotificationUsageStats mUsageStats;
     private NotificationChannel mTestNotificationChannel = new NotificationChannel(
             TEST_CHANNEL_ID, TEST_CHANNEL_ID, NotificationManager.IMPORTANCE_DEFAULT);
     @Mock
@@ -147,7 +149,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
         mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
                 mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr,
-                mSnoozeHelper);
+                mSnoozeHelper, mUsageStats);
 
         // Tests call directly into the Binder.
         mBinderService = mNotificationManagerService.getBinderService();
@@ -261,40 +263,38 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
 
     @Test
     public void testBlockedNotifications_suspended() throws Exception {
-        NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(true);
 
         NotificationChannel channel = new NotificationChannel("id", "name",
                 NotificationManager.IMPORTANCE_HIGH);
         NotificationRecord r = generateNotificationRecord(channel);
-        assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
-        verify(usageStats, times(1)).registerSuspendedByAdmin(eq(r));
+        assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
+        verify(mUsageStats, times(1)).registerSuspendedByAdmin(eq(r));
     }
 
     @Test
     public void testBlockedNotifications_blockedChannel() throws Exception {
-        NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
 
         NotificationChannel channel = new NotificationChannel("id", "name",
                 NotificationManager.IMPORTANCE_HIGH);
         channel.setImportance(NotificationManager.IMPORTANCE_NONE);
         NotificationRecord r = generateNotificationRecord(channel);
-        assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
-        verify(usageStats, times(1)).registerBlocked(eq(r));
+        assertTrue(mNotificationManagerService.isBlocked(r, mUsageStats));
+        verify(mUsageStats, times(1)).registerBlocked(eq(r));
     }
 
     @Test
-    public void testBlockedNotifications_blockedApp() throws Exception {
-        NotificationUsageStats usageStats = mock(NotificationUsageStats.class);
+    public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
 
-        NotificationChannel channel = new NotificationChannel("id", "name",
-                NotificationManager.IMPORTANCE_HIGH);
-        NotificationRecord r = generateNotificationRecord(channel);
-        r.setUserImportance(NotificationManager.IMPORTANCE_NONE);
-        assertTrue(mNotificationManagerService.isBlocked(r, usageStats));
-        verify(usageStats, times(1)).registerBlocked(eq(r));
+        mBinderService.setNotificationsEnabledForPackage(PKG, uid, false);
+
+        final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
+        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
+                sbn.getId(), sbn.getNotification(), sbn.getUserId());
+        waitForIdle();
+        assertEquals(0, mBinderService.getActiveNotifications(sbn.getPackageName()).length);
     }
 
     @Test
@@ -645,6 +645,7 @@ public class NotificationManagerServiceTest extends NotificationTestCase {
         associations.add("a");
         when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
+        mListener.component = new ComponentName(PKG, PKG);
         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
 
index 0812783..5a6225a 100644 (file)
@@ -35,6 +35,7 @@ import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.graphics.Color;
 import android.media.AudioAttributes;
+import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.Build;
 import android.os.UserHandle;
@@ -44,6 +45,8 @@ import android.support.test.runner.AndroidJUnit4;
 import android.test.suitebuilder.annotation.SmallTest;
 
 
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -71,6 +74,14 @@ public class NotificationRecordTest extends NotificationTestCase {
     private final String channelId = "channel";
     NotificationChannel channel =
             new NotificationChannel(channelId, "test", NotificationManager.IMPORTANCE_DEFAULT);
+    private final String channelIdLong =
+            "give_a_developer_a_string_argument_and_who_knows_what_they_will_pass_in_there";
+    final String groupId = "group";
+    final String groupIdOverride = "other_group";
+    private final String groupIdLong =
+            "0|com.foo.bar|g:content://com.foo.bar.ui/account%3A-0000000/account/";
+    NotificationChannel channelLongId =
+            new NotificationChannel(channelIdLong, "long", NotificationManager.IMPORTANCE_DEFAULT);
     NotificationChannel defaultChannel =
             new NotificationChannel(NotificationChannel.DEFAULT_CHANNEL_ID, "test",
                     NotificationManager.IMPORTANCE_UNSPECIFIED);
@@ -107,7 +118,8 @@ public class NotificationRecordTest extends NotificationTestCase {
     }
 
     private StatusBarNotification getNotification(boolean preO, boolean noisy, boolean defaultSound,
-            boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights) {
+            boolean buzzy, boolean defaultVibration, boolean lights, boolean defaultLights,
+            String group) {
         when(mMockContext.getApplicationInfo()).thenReturn(preO ? legacy : upgrade);
         final Builder builder = new Builder(mMockContext)
                 .setContentTitle("foo")
@@ -151,6 +163,9 @@ public class NotificationRecordTest extends NotificationTestCase {
             builder.setChannelId(channelId);
         }
 
+        if(group != null) {
+            builder.setGroup(group);
+        }
 
         Notification n = builder.build();
         if (preO) {
@@ -172,7 +187,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(Settings.System.DEFAULT_NOTIFICATION_URI, record.getSound());
@@ -185,7 +200,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // pre upgrade, custom sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -199,7 +214,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -211,7 +226,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // pre upgrade, default sound.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(null, record.getSound());
@@ -224,7 +239,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // post upgrade, default sound.
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_SOUND, record.getSound());
@@ -237,7 +252,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // pre upgrade, default vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, true /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNotNull(record.getVibration());
@@ -249,7 +264,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // pre upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_VIBRATION, record.getVibration());
@@ -262,7 +277,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // pre upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(true /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertTrue(!Objects.equals(CUSTOM_VIBRATION, record.getVibration()));
@@ -274,7 +289,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         // post upgrade, custom vibration.
         StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
                 false /* defaultSound */, true /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(CUSTOM_CHANNEL_VIBRATION, record.getVibration());
@@ -284,7 +299,7 @@ public class NotificationRecordTest extends NotificationTestCase {
     public void testImportance_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
     }
@@ -295,7 +310,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_LOW, record.getImportance());
@@ -307,7 +322,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(NotificationManager.IMPORTANCE_HIGH, record.getImportance());
@@ -317,7 +332,7 @@ public class NotificationRecordTest extends NotificationTestCase {
     public void testImportance_upgrade() throws Exception {
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(NotificationManager.IMPORTANCE_DEFAULT, record.getImportance());
     }
@@ -326,7 +341,7 @@ public class NotificationRecordTest extends NotificationTestCase {
     public void testLights_preUpgrade_noLight() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNull(record.getLight());
     }
@@ -336,7 +351,7 @@ public class NotificationRecordTest extends NotificationTestCase {
     public void testLights_preUpgrade() throws Exception {
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertEquals(CUSTOM_LIGHT, record.getLight());
     }
@@ -347,7 +362,7 @@ public class NotificationRecordTest extends NotificationTestCase {
         defaultChannel.lockFields(NotificationChannel.USER_LOCKED_LIGHTS);
         StatusBarNotification sbn = getNotification(true /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
 
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertFalse(CUSTOM_LIGHT.equals(record.getLight()));
@@ -366,7 +381,7 @@ public class NotificationRecordTest extends NotificationTestCase {
                 defaultLightColor, defaultLightOn, defaultLightOff);
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, true /*defaultLights */);
+                true /* lights */, true /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(expected, record.getLight());
     }
@@ -382,7 +397,7 @@ public class NotificationRecordTest extends NotificationTestCase {
                 Color.BLUE, defaultLightOn, defaultLightOff);
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                true /* lights */, false /*defaultLights */);
+                true /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
         assertEquals(expected, record.getLight());
     }
@@ -391,8 +406,80 @@ public class NotificationRecordTest extends NotificationTestCase {
     public void testLights_upgrade_noLight() throws Exception {
         StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
                 true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
-                false /* lights */, false /*defaultLights */);
+                false /* lights */, false /* defaultLights */, null /* group */);
         NotificationRecord record = new NotificationRecord(mMockContext, sbn, defaultChannel);
         assertNull(record.getLight());
     }
+
+    @Test
+    public void testLogmakerShortChannel() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        final LogMaker logMaker = record.getLogMaker();
+        assertEquals(channelId,
+                (String) logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID));
+        assertEquals(channel.getImportance(),
+                logMaker.getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_IMPORTANCE));
+    }
+
+    @Test
+    public void testLogmakerLongChannel() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+        true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+        false /* lights */, false /*defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channelLongId);
+        final String loggedId = (String)
+            record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_CHANNEL_ID);
+        assertEquals(channelIdLong.substring(0,10), loggedId.substring(0, 10));
+    }
+
+    @Test
+    public void testLogmakerNoGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /*defaultLights */, null /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertNull(record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+    @Test
+    public void testLogmakerShortGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*reO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+    @Test
+    public void testLogmakerLongGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupIdLong /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        final String loggedId = (String)
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID);
+        assertEquals(groupIdLong.substring(0,10), loggedId.substring(0, 10));
+    }
+
+    @Test
+    public void testLogmakerOverrideGroup() throws Exception {
+        StatusBarNotification sbn = getNotification(false /*preO */, true /* noisy */,
+                true /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+                false /* lights */, false /* defaultLights */, groupId /* group */);
+        NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+        record.setOverrideGroupKey(groupIdOverride);
+        assertEquals(groupIdOverride,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+        record.setOverrideGroupKey(null);
+        assertEquals(groupId,
+                record.getLogMaker().getTaggedData(MetricsEvent.FIELD_NOTIFICATION_GROUP_ID));
+    }
+
+
 }
index 41da88f..5a72e6b 100644 (file)
@@ -364,11 +364,14 @@ public class RankingHelperTest extends NotificationTestCase {
         channel2.enableVibration(false);
         channel2.setGroup(ncg.getId());
         channel2.setLightColor(Color.BLUE);
+        NotificationChannel channel3 = new NotificationChannel("id3", "NAM3", IMPORTANCE_HIGH);
+        channel3.enableVibration(true);
 
         mHelper.createNotificationChannelGroup(PKG, UID, ncg, true);
         mHelper.createNotificationChannelGroup(PKG, UID, ncg2, true);
         mHelper.createNotificationChannel(PKG, UID, channel1, true);
         mHelper.createNotificationChannel(PKG, UID, channel2, false);
+        mHelper.createNotificationChannel(PKG, UID, channel3, false);
         mHelper.createNotificationChannel(UPDATED_PKG, UID2, getChannel(), true);
 
         mHelper.setShowBadge(PKG, UID, true);
@@ -376,8 +379,9 @@ public class RankingHelperTest extends NotificationTestCase {
         mHelper.setImportance(UPDATED_PKG, UID2, IMPORTANCE_NONE);
 
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG, UID, true, channel1.getId(),
-                channel2.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
-        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG, UPDATED_PKG}, new int[]{UID, UID2});
+                channel2.getId(), channel3.getId(), NotificationChannel.DEFAULT_CHANNEL_ID);
+        mHelper.onPackagesChanged(true, UserHandle.myUserId(), new String[]{PKG, UPDATED_PKG},
+                new int[]{UID, UID2});
 
         mHelper.setShowBadge(UPDATED_PKG, UID2, true);
 
@@ -388,6 +392,8 @@ public class RankingHelperTest extends NotificationTestCase {
         assertEquals(channel1, mHelper.getNotificationChannel(PKG, UID, channel1.getId(), false));
         compareChannels(channel2,
                 mHelper.getNotificationChannel(PKG, UID, channel2.getId(), false));
+        compareChannels(channel3,
+                mHelper.getNotificationChannel(PKG, UID, channel3.getId(), false));
 
         List<NotificationChannelGroup> actualGroups =
                 mHelper.getNotificationChannelGroups(PKG, UID, false).getList();
index 686dad4..e12032d 100644 (file)
     <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
     <uses-permission android:name="android.permission.DELETE_PACKAGES" />
 
+    <!-- Uses API introduced in O (26) -->
+    <uses-sdk android:minSdkVersion="1"
+          android:targetSdkVersion="26"/>
+
     <application>
         <uses-library android:name="android.test.runner" />
 
index 36e9b3f..791d3e9 100644 (file)
@@ -1484,6 +1484,31 @@ public class AccountManagerServiceTest extends AndroidTestCase {
     }
 
     @SmallTest
+    public void testGetAccountsByTypeForPackageWhenTypeIsNull() throws Exception {
+        unlockSystemUser();
+        HashMap<String, Integer> visibility1 = new HashMap<>();
+        visibility1.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
+
+        HashMap<String, Integer> visibility2 = new HashMap<>();
+        visibility2.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "P11", null, visibility1);
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "P12", null, visibility2);
+
+        Account[] accounts = mAms.getAccountsByTypeForPackage(
+            null, "otherPackageName",
+            AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+        // Only get the USER_MANAGED_NOT_VISIBLE account.
+        assertEquals(1, accounts.length);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accounts[0].name);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accounts[0].type);
+    }
+
+    @SmallTest
     public void testGetAuthTokenLabelWithNullAccountType() throws Exception {
         unlockSystemUser();
         try {
@@ -2341,6 +2366,224 @@ public class AccountManagerServiceTest extends AndroidTestCase {
     }
 
     @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNullResponse() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.getAccountByTypeAndFeatures(
+                null, // response
+                AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+                AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+                "testpackage"); // opPackageName
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+            // IllegalArgumentException is expected.
+        }
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNullAccountType() throws Exception {
+        unlockSystemUser();
+        try {
+            mAms.getAccountByTypeAndFeatures(
+                mMockAccountManagerResponse, // response
+                null, // accountType
+                AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+                "testpackage"); // opPackageName
+            fail("IllegalArgumentException expected. But no exception was thrown.");
+        } catch (IllegalArgumentException e) {
+            // IllegalArgumentException is expected.
+        }
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndNoAccount() throws Exception {
+        unlockSystemUser();
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            "testpackage");
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(null, accountName);
+        assertEquals(null, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneVisibleAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            "testpackage");
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndOneNotVisibleAccount()
+        throws Exception {
+        unlockSystemUser();
+        HashMap<String, Integer> visibility = new HashMap<>();
+        visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(1, accounts.length);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithNoFeaturesAndTwoAccounts() throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            null,
+            "testpackage");
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(2, accounts.length);
+        if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[1]);
+        } else {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]);
+        }
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoAccount() throws Exception {
+        unlockSystemUser();
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(null, accountName);
+        assertEquals(null, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndNoQualifiedAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(null, accountName);
+        assertEquals(null, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p12", null);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockAccountManagerResponse).onResult(mBundleCaptor.capture());
+        Bundle result = mBundleCaptor.getValue();
+        String accountName = result.getString(AccountManager.KEY_ACCOUNT_NAME);
+        String accountType = result.getString(AccountManager.KEY_ACCOUNT_TYPE);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS, accountName);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1, accountType);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndOneQualifiedNotVisibleAccount()
+        throws Exception {
+        unlockSystemUser();
+        HashMap<String, Integer> visibility = new HashMap<>();
+        visibility.put(AccountManagerServiceTestFixtures.CALLER_PACKAGE,
+            AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE);
+        mAms.addAccountExplicitlyWithVisibility(
+            AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null, visibility);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            AccountManagerServiceTestFixtures.CALLER_PACKAGE);
+        waitForLatch(latch);
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(1, accounts.length);
+        assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+    }
+
+    @SmallTest
+    public void testGetAccountByTypeAndFeaturesWithFeaturesAndTwoQualifiedAccount()
+        throws Exception {
+        unlockSystemUser();
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p11", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, "p12", null);
+        mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_INTERVENE, "p13", null);
+        final CountDownLatch latch = new CountDownLatch(1);
+        mAms.getAccountByTypeAndFeatures(
+            mMockAccountManagerResponse,
+            AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1,
+            AccountManagerServiceTestFixtures.ACCOUNT_FEATURES,
+            "testpackage");
+        waitForLatch(latch);
+        verify(mMockContext).startActivityAsUser(mIntentCaptor.capture(), eq(UserHandle.SYSTEM));
+        Intent intent = mIntentCaptor.getValue();
+        Account[] accounts = (Account[]) intent.getExtra(AccountManager.KEY_ACCOUNTS);
+        assertEquals(2, accounts.length);
+        if (accounts[0].equals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS)) {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[1]);
+        } else {
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS_2, accounts[0]);
+            assertEquals(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, accounts[1]);
+        }
+    }
+
+    @SmallTest
     public void testGetAccountsByFeaturesWithNullResponse() throws Exception {
         unlockSystemUser();
         try {
index d176a0d..73f30d9 100644 (file)
@@ -34,6 +34,7 @@ public final class AccountManagerServiceTestFixtures {
     public static final String KEY_OPTIONS_BUNDLE =
             "account_manager_service_test:option_bundle_key";
     public static final String ACCOUNT_NAME_SUCCESS = "success_on_return@fixture.com";
+    public static final String ACCOUNT_NAME_SUCCESS_2 = "success_on_return_2@fixture.com";
     public static final String ACCOUNT_NAME_INTERVENE = "intervene@fixture.com";
     public static final String ACCOUNT_NAME_ERROR = "error@fixture.com";
 
@@ -69,6 +70,8 @@ public final class AccountManagerServiceTestFixtures {
 
     public static final Account ACCOUNT_SUCCESS =
             new Account(ACCOUNT_NAME_SUCCESS, ACCOUNT_TYPE_1);
+    public static final Account ACCOUNT_SUCCESS_2 =
+            new Account(ACCOUNT_NAME_SUCCESS_2, ACCOUNT_TYPE_1);
     public static final Account ACCOUNT_INTERVENE =
             new Account(ACCOUNT_NAME_INTERVENE, ACCOUNT_TYPE_1);
     public static final Account ACCOUNT_ERROR =
index eb839a2..8106364 100644 (file)
@@ -242,6 +242,8 @@ public class TestAccountType1Authenticator extends AbstractAccountAuthenticator
         if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS)) {
             // fill bundle with true.
             result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
+        } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_SUCCESS_2)) {
+            result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, true);
         } else if (account.name.equals(AccountManagerServiceTestFixtures.ACCOUNT_NAME_INTERVENE)) {
             // fill bundle with false.
             result.putBoolean(AccountManager.KEY_BOOLEAN_RESULT, false);
index 9cfa542..bac1216 100644 (file)
@@ -235,8 +235,7 @@ public class ActivityTestsBase {
                     if (mStackId == ActivityManager.StackId.PINNED_STACK_ID) {
                         mStack = new PinnedActivityStack(this, recents, mOnTop) {
                             @Override
-                            Rect getPictureInPictureBounds(float aspectRatio,
-                                    boolean useExistingStackBounds) {
+                            Rect getDefaultPictureInPictureBounds(float aspectRatio) {
                                 return new Rect(50, 50, 100, 100);
                             }
                         };
index 5a4bb27..4a22a29 100644 (file)
@@ -82,7 +82,7 @@ public class UnknownAppVisibilityControllerTest extends WindowTestsBase {
     public void testAppRemoved() throws Exception {
         final AppWindowToken token = new WindowTestUtils.TestAppWindowToken(mDisplayContent);
         sWm.mUnknownAppVisibilityController.notifyLaunched(token);
-        sWm.mUnknownAppVisibilityController.appRemoved(token);
+        sWm.mUnknownAppVisibilityController.appRemovedOrHidden(token);
         assertTrue(sWm.mUnknownAppVisibilityController.allResolved());
     }
 }
index 5f51898..c809c32 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.server.wm;
 
+import android.util.MergedConfiguration;
+import android.view.WindowManager;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -204,4 +206,20 @@ public class WindowStateTests extends WindowTestsBase {
         assertEquals(mediaChild, windows.pollFirst());
         assertTrue(windows.isEmpty());
     }
+
+    @Test
+    public void testPrepareWindowToDisplayDuringRelayout() throws Exception {
+        testPrepareWindowToDisplayDuringRelayout(false /*wasVisible*/);
+        testPrepareWindowToDisplayDuringRelayout(true /*wasVisible*/);
+    }
+
+    private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
+        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
+        root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
+        root.mTurnOnScreen = false;
+
+        root.prepareWindowToDisplayDuringRelayout(new MergedConfiguration(),
+                wasVisible /*wasVisible*/);
+        assertTrue(root.mTurnOnScreen);
+    }
 }
index 16b73d5..562443f 100644 (file)
@@ -62,6 +62,8 @@ import com.android.server.pm.Installer;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.storage.CacheQuotaStrategy;
 
+import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.IOException;
 
 public class StorageStatsService extends IStorageStatsManager.Stub {
@@ -181,29 +183,42 @@ public class StorageStatsService extends IStorageStatsManager.Stub {
     public long getFreeBytes(String volumeUuid, String callingPackage) {
         // NOTE: No permissions required
 
-        long cacheBytes = 0;
         final long token = Binder.clearCallingIdentity();
         try {
+            final File path;
+            try {
+                path = mStorage.findPathForUuid(volumeUuid);
+            } catch (FileNotFoundException e) {
+                throw new ParcelableException(e);
+            }
+
+            // Free space is usable bytes plus any cached data that we're
+            // willing to automatically clear. To avoid user confusion, this
+            // logic should be kept in sync with getAllocatableBytes().
             if (isQuotaSupported(volumeUuid, callingPackage)) {
-                for (UserInfo user : mUser.getUsers()) {
-                    final StorageStats stats = queryStatsForUser(volumeUuid, user.id, null);
-                    cacheBytes += stats.cacheBytes;
-                }
+                final long cacheTotal = getCacheBytes(volumeUuid, callingPackage);
+                final long cacheReserved = mStorage.getStorageCacheBytes(path);
+                final long cacheClearable = Math.max(0, cacheTotal - cacheReserved);
+
+                return path.getUsableSpace() + cacheClearable;
+            } else {
+                return path.getUsableSpace();
             }
         } finally {
             Binder.restoreCallingIdentity(token);
         }
+    }
 
-        if (volumeUuid == StorageManager.UUID_PRIVATE_INTERNAL) {
-            return Environment.getDataDirectory().getFreeSpace() + cacheBytes;
-        } else {
-            final VolumeInfo vol = mStorage.findVolumeByUuid(volumeUuid);
-            if (vol == null) {
-                throw new ParcelableException(
-                        new IOException("Failed to find storage device for UUID " + volumeUuid));
-            }
-            return vol.getPath().getFreeSpace() + cacheBytes;
+    @Override
+    public long getCacheBytes(String volumeUuid, String callingPackage) {
+        enforcePermission(Binder.getCallingUid(), callingPackage);
+
+        long cacheBytes = 0;
+        for (UserInfo user : mUser.getUsers()) {
+            final StorageStats stats = queryStatsForUser(volumeUuid, user.id, null);
+            cacheBytes += stats.cacheBytes;
         }
+        return cacheBytes;
     }
 
     @Override
index 26a406f..ca74688 100644 (file)
@@ -407,13 +407,15 @@ public class UsbDeviceManager {
                         UsbManager.USB_FUNCTION_ADB);
 
                 /**
-                 * Remove MTP from persistent config, to bring usb to a good state
-                 * after fixes to b/31814300. This block can be removed after the update
+                 * Previous versions can set persist config to mtp/ptp but it does not
+                 * get reset on OTA. Reset the property here instead.
                  */
                 String persisted = SystemProperties.get(USB_PERSISTENT_CONFIG_PROPERTY);
-                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)) {
+                if (UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_MTP)
+                        || UsbManager.containsFunction(persisted, UsbManager.USB_FUNCTION_PTP)) {
                     SystemProperties.set(USB_PERSISTENT_CONFIG_PROPERTY,
-                            UsbManager.removeFunction(persisted, UsbManager.USB_FUNCTION_MTP));
+                            UsbManager.removeFunction(UsbManager.removeFunction(persisted,
+                                    UsbManager.USB_FUNCTION_MTP), UsbManager.USB_FUNCTION_PTP));
                 }
 
                 String state = FileUtils.readTextFile(new File(STATE_PATH), 0, null).trim();
index 0c5e4bd..3788cf3 100644 (file)
@@ -16,6 +16,8 @@
 
 package com.android.server.voiceinteraction;
 
+import static android.app.ActivityManager.START_ASSISTANT_HIDDEN_SESSION;
+import static android.app.ActivityManager.START_ASSISTANT_NOT_ACTIVE_SESSION;
 import static android.app.ActivityManager.START_VOICE_HIDDEN_SESSION;
 import static android.app.ActivityManager.START_VOICE_NOT_ACTIVE_SESSION;
 
@@ -212,11 +214,11 @@ class VoiceInteractionManagerServiceImpl implements VoiceInteractionSessionConne
         try {
             if (mActiveSession == null || token != mActiveSession.mToken) {
                 Slog.w(TAG, "startAssistantActivity does not match active session");
-                return START_VOICE_NOT_ACTIVE_SESSION;
+                return START_ASSISTANT_NOT_ACTIVE_SESSION;
             }
             if (!mActiveSession.mShown) {
                 Slog.w(TAG, "startAssistantActivity not allowed on hidden session");
-                return START_VOICE_HIDDEN_SESSION;
+                return START_ASSISTANT_HIDDEN_SESSION;
             }
             intent = new Intent(intent);
             intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
index 4267ec4..d394d63 100644 (file)
@@ -453,6 +453,7 @@ final class VoiceInteractionSessionConnection implements ServiceConnection {
                 mShowFlags = 0;
                 mHaveAssistData = false;
                 mAssistData.clear();
+                mPendingShowCallbacks.clear();
                 if (mSession != null) {
                     try {
                         mSession.hide();
index 0a47a98..d0b36c9 100644 (file)
@@ -17,7 +17,9 @@ package android.telecom;
 import android.Manifest;
 import android.annotation.RequiresPermission;
 import android.annotation.SuppressAutoDoc;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -48,6 +50,7 @@ import java.util.List;
  * descriptions.
  */
 @SuppressAutoDoc
+@SystemService(Context.TELECOM_SERVICE)
 public class TelecomManager {
 
     /**
@@ -734,6 +737,10 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public List<PhoneAccountHandle> getPhoneAccountsSupportingScheme(String uriScheme) {
         try {
             if (isServiceConnected()) {
@@ -815,6 +822,7 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public List<PhoneAccountHandle> getPhoneAccountsForPackage() {
         try {
             if (isServiceConnected()) {
@@ -942,6 +950,7 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void clearPhoneAccounts() {
         clearAccounts();
     }
@@ -951,6 +960,7 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void clearAccounts() {
         try {
             if (isServiceConnected()) {
@@ -982,6 +992,7 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public ComponentName getDefaultPhoneApp() {
         try {
             if (isServiceConnected()) {
@@ -1198,6 +1209,10 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isRinging() {
         try {
             if (isServiceConnected()) {
@@ -1216,6 +1231,7 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean endCall() {
         try {
             if (isServiceConnected()) {
@@ -1295,6 +1311,10 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isTtySupported() {
         try {
             if (isServiceConnected()) {
@@ -1573,6 +1593,7 @@ public class TelecomManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void enablePhoneAccount(PhoneAccountHandle handle, boolean isEnabled) {
         ITelecomService service = getTelecomService();
         if (service != null) {
index 7174a70..c6c1be3 100644 (file)
@@ -18,7 +18,10 @@ package android.telephony;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.PersistableBundle;
 import android.os.RemoteException;
@@ -29,14 +32,8 @@ import com.android.internal.telephony.ICarrierConfigLoader;
 
 /**
  * Provides access to telephony configuration values that are carrier-specific.
- * <p>
- * Users should obtain an instance of this class by calling
- * {@code mContext.getSystemService(Context.CARRIER_CONFIG_SERVICE);}
- * </p>
- *
- * @see Context#getSystemService
- * @see Context#CARRIER_CONFIG_SERVICE
  */
+@SystemService(Context.CARRIER_CONFIG_SERVICE)
 public class CarrierConfigManager {
     private final static String TAG = "CarrierConfigManager";
 
@@ -1742,6 +1739,7 @@ public class CarrierConfigManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void updateConfigForPhoneId(int phoneId, String simState) {
         try {
             ICarrierConfigLoader loader = getICarrierConfigLoader();
@@ -1763,6 +1761,7 @@ public class CarrierConfigManager {
      */
     @NonNull
     @SystemApi
+    @SuppressLint("Doclava125")
     public static PersistableBundle getDefaultConfig() {
         return new PersistableBundle(sDefaults);
     }
index bc5e4d5..fa7b9b0 100644 (file)
@@ -1449,6 +1449,11 @@ public class PhoneNumberUtils
      * @hide
      */
     public static boolean isInternationalNumber(String phoneNumber, String defaultCountryIso) {
+        // If no phone number is provided, it can't be international.
+        if (TextUtils.isEmpty(phoneNumber)) {
+            return false;
+        }
+
         // If it starts with # or * its not international.
         if (phoneNumber.startsWith("#") || phoneNumber.startsWith("*")) {
             return false;
index 7d4d90b..1eac263 100644 (file)
@@ -16,6 +16,7 @@
 
 package android.telephony;
 
+import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
@@ -346,6 +347,7 @@ public final class SmsManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void sendTextMessageWithoutPersisting(
             String destinationAddress, String scAddress, String text,
             PendingIntent sentIntent, PendingIntent deliveryIntent) {
@@ -530,6 +532,7 @@ public final class SmsManager {
      * @hide
      **/
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void sendMultipartTextMessageWithoutPersisting(
             String destinationAddress, String scAddress, List<String> parts,
             List<PendingIntent> sentIntents, List<PendingIntent> deliveryIntents) {
index 7f616ad..709877d 100644 (file)
@@ -18,6 +18,7 @@ package android.telephony;
 
 import android.annotation.NonNull;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.content.Intent;
@@ -41,12 +42,10 @@ import java.util.List;
 /**
  * SubscriptionManager is the application interface to SubscriptionController
  * and provides information about the current Telephony Subscriptions.
- * * <p>
- * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through {@link #from}.
  * <p>
  * All SDK public methods require android.Manifest.permission.READ_PHONE_STATE.
  */
+@SystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE)
 public class SubscriptionManager {
     private static final String LOG_TAG = "SubscriptionManager";
     private static final boolean DBG = false;
index b8e24f0..6b921c7 100644 (file)
@@ -22,8 +22,10 @@ import android.annotation.IntDef;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.annotation.WorkerThread;
 import android.app.ActivityThread;
 import android.app.PendingIntent;
@@ -79,11 +81,6 @@ import java.util.regex.Pattern;
  * types of subscriber information. Applications can also register
  * a listener to receive notification of telephony state changes.
  * <p>
- * You do not instantiate this class directly; instead, you retrieve
- * a reference to an instance through
- * {@link android.content.Context#getSystemService
- * Context.getSystemService(Context.TELEPHONY_SERVICE)}.
- *
  * The returned TelephonyManager will use the default subscription for all calls.
  * To call an API for a specific subscription, use {@link #createForSubscriptionId(int)}. e.g.
  * <code>
@@ -96,6 +93,7 @@ import java.util.regex.Pattern;
  * its manifest file. Where permissions apply, they are noted in the
  * the methods through which you access the protected information.
  */
+@SystemService(Context.TELEPHONY_SERVICE)
 public class TelephonyManager {
     private static final String TAG = "TelephonyManager";
 
@@ -2671,8 +2669,8 @@ public class TelephonyManager {
      * be implemented instead.
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void setVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle, boolean enabled){
-
     }
 
     /**
@@ -2686,6 +2684,7 @@ public class TelephonyManager {
      */
     @SystemApi
     @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE)
+    @SuppressLint("Doclava125")
     public boolean isVisualVoicemailEnabled(PhoneAccountHandle phoneAccountHandle){
         return false;
     }
@@ -2704,6 +2703,7 @@ public class TelephonyManager {
      * @hide
      */
     @SystemApi
+    @SuppressLint("Doclava125")
     @Nullable
     public Bundle getVisualVoicemailSettings(){
         try {
@@ -4855,12 +4855,14 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMdn() {
         return getCdmaMdn(getSubId());
     }
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMdn(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4876,12 +4878,14 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMin() {
         return getCdmaMin(getSubId());
     }
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public String getCdmaMin(int subId) {
         try {
             ITelephony telephony = getITelephony();
@@ -4897,6 +4901,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public int checkCarrierPrivilegesForPackage(String pkgName) {
         try {
             ITelephony telephony = getITelephony();
@@ -4912,6 +4917,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) {
         try {
             ITelephony telephony = getITelephony();
@@ -4963,6 +4969,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void dial(String number) {
         try {
             ITelephony telephony = getITelephony();
@@ -4975,6 +4982,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public void call(String callingPackage, String number) {
         try {
             ITelephony telephony = getITelephony();
@@ -4987,6 +4995,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CALL_PHONE)
     public boolean endCall() {
         try {
             ITelephony telephony = getITelephony();
@@ -5000,6 +5009,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void answerRingingCall() {
         try {
             ITelephony telephony = getITelephony();
@@ -5012,6 +5022,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void silenceRinger() {
         try {
             getTelecomService().silenceRinger(getOpPackageName());
@@ -5022,6 +5033,10 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isOffhook() {
         try {
             ITelephony telephony = getITelephony();
@@ -5035,6 +5050,10 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isRinging() {
         try {
             ITelephony telephony = getITelephony();
@@ -5048,6 +5067,10 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isIdle() {
         try {
             ITelephony telephony = getITelephony();
@@ -5061,6 +5084,10 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isRadioOn() {
         try {
             ITelephony telephony = getITelephony();
@@ -5074,6 +5101,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean supplyPin(String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5087,6 +5115,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean supplyPuk(String puk, String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5100,6 +5129,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public int[] supplyPinReportResult(String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5113,6 +5143,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public int[] supplyPukReportResult(String puk, String pin) {
         try {
             ITelephony telephony = getITelephony();
@@ -5232,6 +5263,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean handlePinMmi(String dialString) {
         try {
             ITelephony telephony = getITelephony();
@@ -5245,6 +5277,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean handlePinMmiForSubscriber(int subId, String dialString) {
         try {
             ITelephony telephony = getITelephony();
@@ -5258,6 +5291,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void toggleRadioOnOff() {
         try {
             ITelephony telephony = getITelephony();
@@ -5270,6 +5304,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean setRadio(boolean turnOn) {
         try {
             ITelephony telephony = getITelephony();
@@ -5283,6 +5318,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean setRadioPower(boolean turnOn) {
         try {
             ITelephony telephony = getITelephony();
@@ -5296,6 +5332,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @SuppressLint("Doclava125")
     public void updateServiceLocation() {
         try {
             ITelephony telephony = getITelephony();
@@ -5308,6 +5345,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean enableDataConnectivity() {
         try {
             ITelephony telephony = getITelephony();
@@ -5321,6 +5359,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public boolean disableDataConnectivity() {
         try {
             ITelephony telephony = getITelephony();
@@ -5371,12 +5410,14 @@ public class TelephonyManager {
      *
      * @see #hasCarrierPrivileges
      */
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setDataEnabled(boolean enable) {
         setDataEnabled(getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enable);
     }
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void setDataEnabled(int subId, boolean enable) {
         try {
             Log.d(TAG, "setDataEnabled: enabled=" + enable);
@@ -5466,6 +5507,7 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public void enableVideoCalling(boolean enable) {
         try {
             ITelephony telephony = getITelephony();
@@ -5478,6 +5520,10 @@ public class TelephonyManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(anyOf = {
+            android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE,
+            android.Manifest.permission.READ_PHONE_STATE
+    })
     public boolean isVideoCallingEnabled() {
         try {
             ITelephony telephony = getITelephony();
@@ -6346,6 +6392,7 @@ public class TelephonyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public List<TelephonyHistogram> getTelephonyHistograms() {
         try {
             ITelephony service = getITelephony();
@@ -6373,6 +6420,7 @@ public class TelephonyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
     public int setAllowedCarriers(int slotIndex, List<CarrierIdentifier> carriers) {
         try {
             ITelephony service = getITelephony();
@@ -6391,9 +6439,6 @@ public class TelephonyManager {
      * Get the allowed carrier list for slotIndex.
      * Require system privileges. In the future we may add this to carrier APIs.
      *
-     * <p>Requires Permission:
-     *   {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE}
-     *
      * <p>This method returns valid data on devices with {@link
      * android.content.pm.PackageManager#FEATURE_TELEPHONY_CARRIERLOCK} enabled.
      *
@@ -6402,6 +6447,7 @@ public class TelephonyManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
     public List<CarrierIdentifier> getAllowedCarriers(int slotIndex) {
         try {
             ITelephony service = getITelephony();
index db45b9d..99d44e6 100644 (file)
@@ -17,7 +17,7 @@ package com.example.android.musicservicedemo;
 
 import android.os.Bundle;
 import android.support.v4.app.Fragment;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuItem;
@@ -31,7 +31,7 @@ import com.example.android.musicservicedemo.R;
 /**
  * Main activity of the app.
  */
-public class MainActivity extends ActionBarActivity {
+public class MainActivity extends AppCompatActivity {
 
     private static final String LOG = "MainActivity";
 
index 7632a6e..55440c8 100644 (file)
@@ -21,7 +21,7 @@ import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.os.CountDownTimer;
-import android.support.v7.app.ActionBarActivity;
+import android.support.v7.app.AppCompatActivity;
 import android.os.Bundle;
 import android.text.method.Touch;
 import android.util.AttributeSet;
@@ -173,7 +173,7 @@ class TouchLatencyView extends View implements View.OnTouchListener {
     private float mVelocityX, mVelocityY;
 }
 
-public class TouchLatencyActivity extends ActionBarActivity {
+public class TouchLatencyActivity extends AppCompatActivity {
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
index 3172c6e..281223e 100644 (file)
 
 package com.android.server.connectivity;
 
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_LOCAL_ONLY;
+import static android.net.wifi.WifiManager.IFACE_IP_MODE_TETHERED;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_INTERFACE_NAME;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_MODE;
+import static android.net.wifi.WifiManager.EXTRA_WIFI_AP_STATE;
+import static android.net.wifi.WifiManager.WIFI_AP_STATE_ENABLED;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Matchers.anyBoolean;
@@ -201,12 +207,19 @@ public class TetheringTest {
 
     private void sendWifiApStateChanged(int state) {
         final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
-        intent.putExtra(WifiManager.EXTRA_WIFI_AP_STATE, state);
+        intent.putExtra(EXTRA_WIFI_AP_STATE, state);
+        mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    private void sendWifiApStateChanged(int state, String ifname, int ipmode) {
+        final Intent intent = new Intent(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
+        intent.putExtra(EXTRA_WIFI_AP_STATE, state);
+        intent.putExtra(EXTRA_WIFI_AP_INTERFACE_NAME, ifname);
+        intent.putExtra(EXTRA_WIFI_AP_MODE, ipmode);
         mServiceContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
     }
 
     private void verifyInterfaceServingModeStarted() throws Exception {
-        verify(mNMService, times(1)).listInterfaces();
         verify(mNMService, times(1)).getInterfaceConfig(mTestIfname);
         verify(mNMService, times(1))
                 .setInterfaceConfig(eq(mTestIfname), any(InterfaceConfiguration.class));
@@ -223,14 +236,32 @@ public class TetheringTest {
     }
 
     @Test
-    public void workingLocalOnlyHotspot() throws Exception {
+    public void failingLocalOnlyHotspotLegacyApBroadcast() throws Exception {
         when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
 
         // Emulate externally-visible WifiManager effects, causing the
         // per-interface state machine to start up, and telling us that
         // hotspot mode is to be started.
         mTethering.interfaceStatusChanged(mTestIfname, true);
-        sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+        sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
+        mLooper.dispatchAll();
+
+        verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
+        verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+        verifyNoMoreInteractions(mConnectivityManager);
+        verifyNoMoreInteractions(mNMService);
+        verifyNoMoreInteractions(mWifiManager);
+    }
+
+    @Test
+    public void workingLocalOnlyHotspotEnrichedApBroadcast() throws Exception {
+        when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
+
+        // Emulate externally-visible WifiManager effects, causing the
+        // per-interface state machine to start up, and telling us that
+        // hotspot mode is to be started.
+        mTethering.interfaceStatusChanged(mTestIfname, true);
+        sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_LOCAL_ONLY);
         mLooper.dispatchAll();
 
         verifyInterfaceServingModeStarted();
@@ -274,7 +305,34 @@ public class TetheringTest {
     }
 
     @Test
-    public void workingWifiTethering() throws Exception {
+    public void failingWifiTetheringLegacyApBroadcast() throws Exception {
+        when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
+        when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
+
+        // Emulate pressing the WiFi tethering button.
+        mTethering.startTethering(ConnectivityManager.TETHERING_WIFI, null, false);
+        mLooper.dispatchAll();
+        verify(mWifiManager, times(1)).startSoftAp(null);
+        verifyNoMoreInteractions(mWifiManager);
+        verifyNoMoreInteractions(mConnectivityManager);
+        verifyNoMoreInteractions(mNMService);
+
+        // Emulate externally-visible WifiManager effects, causing the
+        // per-interface state machine to start up, and telling us that
+        // tethering mode is to be started.
+        mTethering.interfaceStatusChanged(mTestIfname, true);
+        sendWifiApStateChanged(WIFI_AP_STATE_ENABLED);
+        mLooper.dispatchAll();
+
+        verify(mConnectivityManager, atLeastOnce()).isTetheringSupported();
+        verifyTetheringBroadcast(mTestIfname, ConnectivityManager.EXTRA_AVAILABLE_TETHER);
+        verifyNoMoreInteractions(mConnectivityManager);
+        verifyNoMoreInteractions(mNMService);
+        verifyNoMoreInteractions(mWifiManager);
+    }
+
+    @Test
+    public void workingWifiTetheringEnrichedApBroadcast() throws Exception {
         when(mConnectivityManager.isTetheringSupported()).thenReturn(true);
         when(mWifiManager.startSoftAp(any(WifiConfiguration.class))).thenReturn(true);
 
@@ -290,7 +348,7 @@ public class TetheringTest {
         // per-interface state machine to start up, and telling us that
         // tethering mode is to be started.
         mTethering.interfaceStatusChanged(mTestIfname, true);
-        sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+        sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
         mLooper.dispatchAll();
 
         verifyInterfaceServingModeStarted();
@@ -372,11 +430,9 @@ public class TetheringTest {
         // per-interface state machine to start up, and telling us that
         // tethering mode is to be started.
         mTethering.interfaceStatusChanged(mTestIfname, true);
-        sendWifiApStateChanged(WifiManager.WIFI_AP_STATE_ENABLED);
+        sendWifiApStateChanged(WIFI_AP_STATE_ENABLED, mTestIfname, IFACE_IP_MODE_TETHERED);
         mLooper.dispatchAll();
 
-        // Activity caused by test_wlan0 becoming available.
-        verify(mNMService, times(1)).listInterfaces();
         // We verify get/set called twice here: once for setup and once during
         // teardown because all events happen over the course of the single
         // dispatchAll() above.
index 5a651aa..fca44ae 100644 (file)
@@ -31,12 +31,10 @@ public class ViewUtils {
                 LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                 LayoutParams.TYPE_APPLICATION_OVERLAY,
                 0, PixelFormat.TRANSLUCENT);
-        InstrumentationRegistry.getContext()
-                .getSystemService(WindowManager.class).addView(view, lp);
+        view.getContext().getSystemService(WindowManager.class).addView(view, lp);
     }
 
     public static void detachView(View view) {
-        InstrumentationRegistry.getContext()
-                .getSystemService(WindowManager.class).removeViewImmediate(view);
+        view.getContext().getSystemService(WindowManager.class).removeViewImmediate(view);
     }
 }
index bf18949..eff8283 100644 (file)
@@ -159,8 +159,8 @@ cc_library_host_shared {
 // ==========================================================
 cc_test_host {
     name: "aapt2_tests",
-    srcs: ["**/*_test.cpp"],
-    static_libs: ["libaapt2"],
+    srcs: ["test/Common.cpp", "**/*_test.cpp"],
+    static_libs: ["libaapt2", "libgmock"],
     defaults: ["aapt_defaults"],
 }
 
index 0917129..870b735 100644 (file)
@@ -69,6 +69,7 @@ message SymbolStatus {
        optional Visibility visibility = 1;
        optional Source source = 2;
        optional string comment = 3;
+       optional bool allow_new = 4;
 }
 
 message Entry {
index 0d1850f..9503b56 100644 (file)
@@ -92,14 +92,14 @@ struct ParsedResource {
   Source source;
   ResourceId id;
   Maybe<SymbolState> symbol_state;
+  bool allow_new = false;
   std::string comment;
   std::unique_ptr<Value> value;
   std::list<ParsedResource> child_resources;
 };
 
 // Recursively adds resources to the ResourceTable.
-static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag,
-                                ParsedResource* res) {
+static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, ParsedResource* res) {
   StringPiece trimmed_comment = util::TrimWhitespace(res->comment);
   if (trimmed_comment.size() != res->comment.size()) {
     // Only if there was a change do we re-assign.
@@ -111,6 +111,7 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag,
     symbol.state = res->symbol_state.value();
     symbol.source = res->source;
     symbol.comment = res->comment;
+    symbol.allow_new = res->allow_new;
     if (!table->SetSymbolState(res->name, res->id, symbol, diag)) {
       return false;
     }
@@ -121,8 +122,8 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag,
     res->value->SetComment(std::move(res->comment));
     res->value->SetSource(std::move(res->source));
 
-    if (!table->AddResource(res->name, res->id, res->config, res->product,
-                            std::move(res->value), diag)) {
+    if (!table->AddResource(res->name, res->id, res->config, res->product, std::move(res->value),
+                            diag)) {
       return false;
     }
   }
@@ -414,6 +415,10 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
   if (resource_type == "item") {
     can_be_bag = false;
 
+    // The default format for <item> is any. If a format attribute is present, that one will
+    // override the default.
+    resource_format = android::ResTable_map::TYPE_ANY;
+
     // Items have their type encoded in the type attribute.
     if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) {
       resource_type = maybe_type.value().to_string();
@@ -480,8 +485,8 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser,
       out_resource->name.type = item_iter->second.type;
       out_resource->name.entry = maybe_name.value().to_string();
 
-      // Only use the implicit format for this type if it wasn't overridden.
-      if (!resource_format) {
+      // Only use the implied format of the type when there is no explicit format.
+      if (resource_format == 0u) {
         resource_format = item_iter->second.format;
       }
 
@@ -618,6 +623,11 @@ std::unique_ptr<Item> ResourceParser::ParseXml(xml::XmlPullParser* parser,
     return std::move(string);
   }
 
+  // If the text is empty, and the value is not allowed to be a string, encode it as a @null.
+  if (util::TrimWhitespace(raw_value).empty()) {
+    return ResourceUtils::MakeNull();
+  }
+
   if (allow_raw_value) {
     // We can't parse this so return a RawString if we are allowed.
     return util::make_unique<RawString>(
@@ -849,6 +859,7 @@ bool ResourceParser::ParseAddResource(xml::XmlPullParser* parser,
                                       ParsedResource* out_resource) {
   if (ParseSymbolImpl(parser, out_resource)) {
     out_resource->symbol_state = SymbolState::kUndefined;
+    out_resource->allow_new = true;
     return true;
   }
   return false;
index 8258019..5631dc2 100644 (file)
@@ -78,42 +78,32 @@ class ResourceParser {
    * Item, then a
    * RawString is returned. Otherwise this returns false;
    */
-  std::unique_ptr<Item> ParseXml(xml::XmlPullParser* parser,
-                                 const uint32_t type_mask,
+  std::unique_ptr<Item> ParseXml(xml::XmlPullParser* parser, const uint32_t type_mask,
                                  const bool allow_raw_value);
 
   bool ParseResources(xml::XmlPullParser* parser);
   bool ParseResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
 
-  bool ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource,
-                 uint32_t format);
+  bool ParseItem(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t format);
   bool ParseString(xml::XmlPullParser* parser, ParsedResource* out_resource);
 
   bool ParsePublic(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParsePublicGroup(xml::XmlPullParser* parser,
-                        ParsedResource* out_resource);
-  bool ParseSymbolImpl(xml::XmlPullParser* parser,
-                       ParsedResource* out_resource);
+  bool ParsePublicGroup(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParseAddResource(xml::XmlPullParser* parser,
-                        ParsedResource* out_resource);
+  bool ParseAddResource(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseAttr(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
-                     bool weak);
+  bool ParseAttrImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, bool weak);
   Maybe<Attribute::Symbol> ParseEnumOrFlagItem(xml::XmlPullParser* parser,
                                                const android::StringPiece& tag);
   bool ParseStyle(const ResourceType type, xml::XmlPullParser* parser,
                   ParsedResource* out_resource);
   bool ParseStyleItem(xml::XmlPullParser* parser, Style* style);
-  bool ParseDeclareStyleable(xml::XmlPullParser* parser,
-                             ParsedResource* out_resource);
+  bool ParseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource* out_resource);
   bool ParseArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
-  bool ParseIntegerArray(xml::XmlPullParser* parser,
-                         ParsedResource* out_resource);
-  bool ParseStringArray(xml::XmlPullParser* parser,
-                        ParsedResource* out_resource);
-  bool ParseArrayImpl(xml::XmlPullParser* parser, ParsedResource* out_resource,
-                      uint32_t typeMask);
+  bool ParseIntegerArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseStringArray(xml::XmlPullParser* parser, ParsedResource* out_resource);
+  bool ParseArrayImpl(xml::XmlPullParser* parser, ParsedResource* out_resource, uint32_t typeMask);
   bool ParsePlural(xml::XmlPullParser* parser, ParsedResource* out_resource);
 
   IDiagnostics* diag_;
index faa6607..5352ca8 100644 (file)
 #include "test/Test.h"
 #include "xml/XmlPullParser.h"
 
-using android::StringPiece;
+using ::aapt::test::ValueEq;
+using ::android::StringPiece;
+using ::testing::Eq;
+using ::testing::NotNull;
+using ::testing::Pointee;
 
 namespace aapt {
 
-constexpr const char* kXmlPreamble =
-    "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+constexpr const char* kXmlPreamble = "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
 
 TEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) {
   std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();
   std::stringstream input(kXmlPreamble);
-  input << "<attr name=\"foo\"/>" << std::endl;
+  input << R"(<attr name="foo"/>)" << std::endl;
   ResourceTable table;
   ResourceParser parser(context->GetDiagnostics(), &table, Source{"test"}, {});
   xml::XmlPullParser xml_parser(input);
@@ -44,19 +47,20 @@ TEST(ResourceParserSingleTest, FailToParseWithNoRootResourcesElement) {
 
 class ResourceParserTest : public ::testing::Test {
  public:
-  void SetUp() override { context_ = test::ContextBuilder().Build(); }
+  void SetUp() override {
+    context_ = test::ContextBuilder().Build();
+  }
 
   ::testing::AssertionResult TestParse(const StringPiece& str) {
     return TestParse(str, ConfigDescription{});
   }
 
-  ::testing::AssertionResult TestParse(const StringPiece& str,
-                                       const ConfigDescription& config) {
+  ::testing::AssertionResult TestParse(const StringPiece& str, const ConfigDescription& config) {
     std::stringstream input(kXmlPreamble);
     input << "<resources>\n" << str << "\n</resources>" << std::endl;
     ResourceParserOptions parserOptions;
-    ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"},
-                          config, parserOptions);
+    ResourceParser parser(context_->GetDiagnostics(), &table_, Source{"test"}, config,
+                          parserOptions);
     xml::XmlPullParser xmlParser(input);
     if (parser.Parse(&xmlParser)) {
       return ::testing::AssertionSuccess();
@@ -203,18 +207,18 @@ TEST_F(ResourceParserTest, ParseNull) {
   // a non-existing value, and this causes problems in styles when trying to
   // resolve an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE
   // with a data value of 0.
-  BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
-  ASSERT_NE(nullptr, integer);
-  EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType);
-  EXPECT_EQ(0u, integer->value.data);
+  Reference* null_ref = test::GetValue<Reference>(&table_, "integer/foo");
+  ASSERT_THAT(null_ref, NotNull());
+  EXPECT_FALSE(null_ref->name);
+  EXPECT_FALSE(null_ref->id);
+  EXPECT_EQ(Reference::Type::kResource, null_ref->reference_type);
 }
 
 TEST_F(ResourceParserTest, ParseEmpty) {
   std::string input = "<integer name=\"foo\">@empty</integer>";
   ASSERT_TRUE(TestParse(input));
 
-  BinaryPrimitive* integer =
-      test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
+  BinaryPrimitive* integer = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
   ASSERT_NE(nullptr, integer);
   EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType);
   EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data);
@@ -239,22 +243,18 @@ TEST_F(ResourceParserTest, ParseAttr) {
 // ultimately
 // stored them with the default configuration. Check that we have the same
 // behavior.
-TEST_F(ResourceParserTest,
-       ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) {
+TEST_F(ResourceParserTest, ParseAttrAndDeclareStyleableUnderConfigButRecordAsNoConfig) {
   const ConfigDescription watch_config = test::ParseConfigOrDie("watch");
-  std::string input = R"EOF(
-        <attr name="foo" />
-        <declare-styleable name="bar">
-          <attr name="baz" />
-        </declare-styleable>)EOF";
+  std::string input = R"(
+      <attr name="foo" />
+      <declare-styleable name="bar">
+        <attr name="baz" />
+      </declare-styleable>)";
   ASSERT_TRUE(TestParse(input, watch_config));
 
-  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo",
-                                                        watch_config));
-  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz",
-                                                        watch_config));
-  EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>(
-                         &table_, "styleable/bar", watch_config));
+  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/foo", watch_config));
+  EXPECT_EQ(nullptr, test::GetValueForConfig<Attribute>(&table_, "attr/baz", watch_config));
+  EXPECT_EQ(nullptr, test::GetValueForConfig<Styleable>(&table_, "styleable/bar", watch_config));
 
   EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/foo"));
   EXPECT_NE(nullptr, test::GetValue<Attribute>(&table_, "attr/baz"));
@@ -777,8 +777,7 @@ TEST_F(ResourceParserTest, ExternalTypesShouldOnlyBeReferences) {
   ASSERT_FALSE(TestParse(input));
 }
 
-TEST_F(ResourceParserTest,
-       AddResourcesElementShouldAddEntryWithUndefinedSymbol) {
+TEST_F(ResourceParserTest, AddResourcesElementShouldAddEntryWithUndefinedSymbol) {
   std::string input = R"EOF(<add-resource name="bar" type="string" />)EOF";
   ASSERT_TRUE(TestParse(input));
 
@@ -788,18 +787,29 @@ TEST_F(ResourceParserTest,
   const ResourceEntry* entry = result.value().entry;
   ASSERT_NE(nullptr, entry);
   EXPECT_EQ(SymbolState::kUndefined, entry->symbol_status.state);
+  EXPECT_TRUE(entry->symbol_status.allow_new);
 }
 
 TEST_F(ResourceParserTest, ParseItemElementWithFormat) {
-  std::string input =
-      R"EOF(<item name="foo" type="integer" format="float">0.3</item>)EOF";
+  std::string input = R"(<item name="foo" type="integer" format="float">0.3</item>)";
   ASSERT_TRUE(TestParse(input));
 
-  BinaryPrimitive* val =
-      test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
-  ASSERT_NE(nullptr, val);
+  BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
+  ASSERT_THAT(val, NotNull());
+  EXPECT_THAT(val->value.dataType, Eq(android::Res_value::TYPE_FLOAT));
 
-  EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType);
+  input = R"(<item name="bar" type="integer" format="fraction">100</item>)";
+  ASSERT_FALSE(TestParse(input));
+}
+
+// An <item> without a format specifier accepts all types of values.
+TEST_F(ResourceParserTest, ParseItemElementWithoutFormat) {
+  std::string input = R"(<item name="foo" type="integer">100%p</item>)";
+  ASSERT_TRUE(TestParse(input));
+
+  BinaryPrimitive* val = test::GetValue<BinaryPrimitive>(&table_, "integer/foo");
+  ASSERT_THAT(val, NotNull());
+  EXPECT_THAT(val->value.dataType, Eq(android::Res_value::TYPE_FRACTION));
 }
 
 TEST_F(ResourceParserTest, ParseConfigVaryingItem) {
@@ -821,4 +831,16 @@ TEST_F(ResourceParserTest, ParseBagElement) {
   EXPECT_NE(nullptr, ValueCast<RawString>(val->entries[0].value.get()));
 }
 
+TEST_F(ResourceParserTest, ParseElementWithNoValue) {
+  std::string input = R"(
+      <item type="drawable" format="reference" name="foo" />
+      <string name="foo" />)";
+  ASSERT_TRUE(TestParse(input));
+  ASSERT_THAT(test::GetValue(&table_, "drawable/foo"), Pointee(ValueEq(Reference())));
+
+  String* str = test::GetValue<String>(&table_, "string/foo");
+  ASSERT_THAT(str, NotNull());
+  EXPECT_THAT(*str->value, Eq(""));
+}
+
 }  // namespace aapt
index 1947628..168004f 100644 (file)
@@ -440,8 +440,7 @@ bool ResourceTable::AddResourceImpl(const ResourceNameRef& name, const ResourceI
   return true;
 }
 
-bool ResourceTable::SetSymbolState(const ResourceNameRef& name,
-                                   const ResourceId& res_id,
+bool ResourceTable::SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id,
                                    const Symbol& symbol, IDiagnostics* diag) {
   return SetSymbolStateImpl(name, res_id, symbol, ValidateName, diag);
 }
@@ -489,8 +488,7 @@ bool ResourceTable::SetSymbolStateImpl(const ResourceNameRef& name, const Resour
     diag->Error(DiagMessage(symbol.source)
                 << "trying to add resource '" << name << "' with ID " << res_id
                 << " but resource already has ID "
-                << ResourceId(package->id.value(), type->id.value(),
-                              entry->id.value()));
+                << ResourceId(package->id.value(), type->id.value(), entry->id.value()));
     return false;
   }
 
@@ -505,6 +503,11 @@ bool ResourceTable::SetSymbolStateImpl(const ResourceNameRef& name, const Resour
     type->symbol_status.state = SymbolState::kPublic;
   }
 
+  if (symbol.allow_new) {
+    // This symbol can be added as a new resource when merging (if it belongs to an overlay).
+    entry->symbol_status.allow_new = true;
+  }
+
   if (symbol.state == SymbolState::kUndefined &&
       entry->symbol_status.state != SymbolState::kUndefined) {
     // We can't undefine a symbol (remove its visibility). Ignore.
@@ -517,7 +520,10 @@ bool ResourceTable::SetSymbolStateImpl(const ResourceNameRef& name, const Resour
     return true;
   }
 
-  entry->symbol_status = std::move(symbol);
+  // This symbol definition takes precedence, replace.
+  entry->symbol_status.state = symbol.state;
+  entry->symbol_status.source = symbol.source;
+  entry->symbol_status.comment = symbol.comment;
   return true;
 }
 
index b032121..4295d06 100644 (file)
@@ -50,6 +50,10 @@ enum class SymbolState {
 struct Symbol {
   SymbolState state = SymbolState::kUndefined;
   Source source;
+
+  // Whether this entry (originating from an overlay) can be added as a new resource.
+  bool allow_new = false;
+
   std::string comment;
 };
 
@@ -223,8 +227,7 @@ class ResourceTable {
   bool SetSymbolState(const ResourceNameRef& name, const ResourceId& res_id,
                       const Symbol& symbol, IDiagnostics* diag);
 
-  bool SetSymbolStateAllowMangled(const ResourceNameRef& name,
-                                  const ResourceId& res_id,
+  bool SetSymbolStateAllowMangled(const ResourceNameRef& name, const ResourceId& res_id,
                                   const Symbol& symbol, IDiagnostics* diag);
 
   struct SearchResult {
index 1bb7d9b..deeef6e 100644 (file)
@@ -305,21 +305,25 @@ std::unique_ptr<Reference> TryParseReference(const StringPiece& str,
   return {};
 }
 
-std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const StringPiece& str) {
-  StringPiece trimmed_str(util::TrimWhitespace(str));
-  android::Res_value value = {};
+std::unique_ptr<Item> TryParseNullOrEmpty(const StringPiece& str) {
+  const StringPiece trimmed_str(util::TrimWhitespace(str));
   if (trimmed_str == "@null") {
-    // TYPE_NULL with data set to 0 is interpreted by the runtime as an error.
-    // Instead we set the data type to TYPE_REFERENCE with a value of 0.
-    value.dataType = android::Res_value::TYPE_REFERENCE;
+    return MakeNull();
   } else if (trimmed_str == "@empty") {
-    // TYPE_NULL with value of DATA_NULL_EMPTY is handled fine by the runtime.
-    value.dataType = android::Res_value::TYPE_NULL;
-    value.data = android::Res_value::DATA_NULL_EMPTY;
-  } else {
-    return {};
+    return MakeEmpty();
   }
-  return util::make_unique<BinaryPrimitive>(value);
+  return {};
+}
+
+std::unique_ptr<Reference> MakeNull() {
+  // TYPE_NULL with data set to 0 is interpreted by the runtime as an error.
+  // Instead we set the data type to TYPE_REFERENCE with a value of 0.
+  return util::make_unique<Reference>();
+}
+
+std::unique_ptr<BinaryPrimitive> MakeEmpty() {
+  return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_NULL,
+                                            android::Res_value::DATA_NULL_EMPTY);
 }
 
 std::unique_ptr<BinaryPrimitive> TryParseEnumSymbol(const Attribute* enum_attr,
@@ -496,19 +500,17 @@ Maybe<int> ParseSdkVersion(const StringPiece& str) {
 
 std::unique_ptr<BinaryPrimitive> TryParseBool(const StringPiece& str) {
   if (Maybe<bool> maybe_result = ParseBool(str)) {
-    android::Res_value value = {};
-    value.dataType = android::Res_value::TYPE_INT_BOOLEAN;
-
-    if (maybe_result.value()) {
-      value.data = 0xffffffffu;
-    } else {
-      value.data = 0;
-    }
-    return util::make_unique<BinaryPrimitive>(value);
+    const uint32_t data = maybe_result.value() ? 0xffffffffu : 0u;
+    return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_BOOLEAN, data);
   }
   return {};
 }
 
+std::unique_ptr<BinaryPrimitive> MakeBool(bool val) {
+  return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_INT_BOOLEAN,
+                                            val ? 0xffffffffu : 0u);
+}
+
 std::unique_ptr<BinaryPrimitive> TryParseInt(const StringPiece& str) {
   std::u16string str16 = util::Utf8ToUtf16(str);
   android::Res_value value;
@@ -571,13 +573,15 @@ uint32_t AndroidTypeToAttributeTypeMask(uint16_t type) {
 std::unique_ptr<Item> TryParseItemForAttribute(
     const StringPiece& value, uint32_t type_mask,
     const std::function<void(const ResourceName&)>& on_create_reference) {
-  std::unique_ptr<BinaryPrimitive> null_or_empty = TryParseNullOrEmpty(value);
+  using android::ResTable_map;
+
+  auto null_or_empty = TryParseNullOrEmpty(value);
   if (null_or_empty) {
-    return std::move(null_or_empty);
+    return null_or_empty;
   }
 
   bool create = false;
-  std::unique_ptr<Reference> reference = TryParseReference(value, &create);
+  auto reference = TryParseReference(value, &create);
   if (reference) {
     if (create && on_create_reference) {
       on_create_reference(reference->name.value());
@@ -585,39 +589,37 @@ std::unique_ptr<Item> TryParseItemForAttribute(
     return std::move(reference);
   }
 
-  if (type_mask & android::ResTable_map::TYPE_COLOR) {
+  if (type_mask & ResTable_map::TYPE_COLOR) {
     // Try parsing this as a color.
-    std::unique_ptr<BinaryPrimitive> color = TryParseColor(value);
+    auto color = TryParseColor(value);
     if (color) {
       return std::move(color);
     }
   }
 
-  if (type_mask & android::ResTable_map::TYPE_BOOLEAN) {
+  if (type_mask & ResTable_map::TYPE_BOOLEAN) {
     // Try parsing this as a boolean.
-    std::unique_ptr<BinaryPrimitive> boolean = TryParseBool(value);
+    auto boolean = TryParseBool(value);
     if (boolean) {
       return std::move(boolean);
     }
   }
 
-  if (type_mask & android::ResTable_map::TYPE_INTEGER) {
+  if (type_mask & ResTable_map::TYPE_INTEGER) {
     // Try parsing this as an integer.
-    std::unique_ptr<BinaryPrimitive> integer = TryParseInt(value);
+    auto integer = TryParseInt(value);
     if (integer) {
       return std::move(integer);
     }
   }
 
-  const uint32_t float_mask = android::ResTable_map::TYPE_FLOAT |
-                              android::ResTable_map::TYPE_DIMENSION |
-                              android::ResTable_map::TYPE_FRACTION;
+  const uint32_t float_mask =
+      ResTable_map::TYPE_FLOAT | ResTable_map::TYPE_DIMENSION | ResTable_map::TYPE_FRACTION;
   if (type_mask & float_mask) {
     // Try parsing this as a float.
-    std::unique_ptr<BinaryPrimitive> floating_point = TryParseFloat(value);
+    auto floating_point = TryParseFloat(value);
     if (floating_point) {
-      if (type_mask &
-          AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
+      if (type_mask & AndroidTypeToAttributeTypeMask(floating_point->value.dataType)) {
         return std::move(floating_point);
       }
     }
@@ -632,24 +634,25 @@ std::unique_ptr<Item> TryParseItemForAttribute(
 std::unique_ptr<Item> TryParseItemForAttribute(
     const StringPiece& str, const Attribute* attr,
     const std::function<void(const ResourceName&)>& on_create_reference) {
+  using android::ResTable_map;
+
   const uint32_t type_mask = attr->type_mask;
-  std::unique_ptr<Item> value =
-      TryParseItemForAttribute(str, type_mask, on_create_reference);
+  auto value = TryParseItemForAttribute(str, type_mask, on_create_reference);
   if (value) {
     return value;
   }
 
-  if (type_mask & android::ResTable_map::TYPE_ENUM) {
+  if (type_mask & ResTable_map::TYPE_ENUM) {
     // Try parsing this as an enum.
-    std::unique_ptr<BinaryPrimitive> enum_value = TryParseEnumSymbol(attr, str);
+    auto enum_value = TryParseEnumSymbol(attr, str);
     if (enum_value) {
       return std::move(enum_value);
     }
   }
 
-  if (type_mask & android::ResTable_map::TYPE_FLAGS) {
+  if (type_mask & ResTable_map::TYPE_FLAGS) {
     // Try parsing this as a flag.
-    std::unique_ptr<BinaryPrimitive> flag_value = TryParseFlagSymbol(attr, str);
+    auto flag_value = TryParseFlagSymbol(attr, str);
     if (flag_value) {
       return std::move(flag_value);
     }
@@ -657,8 +660,7 @@ std::unique_ptr<Item> TryParseItemForAttribute(
   return {};
 }
 
-std::string BuildResourceFileName(const ResourceFile& res_file,
-                                  const NameMangler* mangler) {
+std::string BuildResourceFileName(const ResourceFile& res_file, const NameMangler* mangler) {
   std::stringstream out;
   out << "res/" << res_file.name.type;
   if (res_file.config != ConfigDescription{}) {
@@ -721,9 +723,9 @@ std::unique_ptr<Item> ParseBinaryResValue(const ResourceType& type, const Config
         ref_type = Reference::Type::kAttribute;
       }
 
-      if (data == 0) {
+      if (data == 0u) {
         // A reference of 0, must be the magic @null reference.
-        return util::make_unique<BinaryPrimitive>(android::Res_value::TYPE_REFERENCE, 0u);
+        return util::make_unique<Reference>();
       }
 
       // This is a normal reference.
index 48922b7..36f6c2b 100644 (file)
@@ -133,7 +133,16 @@ std::unique_ptr<Reference> TryParseReference(const android::StringPiece& str,
  * Returns a BinaryPrimitve object representing @null or @empty if the string
  * was parsed as one.
  */
-std::unique_ptr<BinaryPrimitive> TryParseNullOrEmpty(const android::StringPiece& str);
+std::unique_ptr<Item> TryParseNullOrEmpty(const android::StringPiece& str);
+
+// Returns a Reference representing @null.
+// Due to runtime compatibility issues, this is encoded as a reference with ID 0.
+// The runtime will convert this to TYPE_NULL.
+std::unique_ptr<Reference> MakeNull();
+
+// Returns a BinaryPrimitive representing @empty. This is encoded as a Res_value with
+// type Res_value::TYPE_NULL and data Res_value::DATA_NULL_EMPTY.
+std::unique_ptr<BinaryPrimitive> MakeEmpty();
 
 /*
  * Returns a BinaryPrimitve object representing a color if the string was parsed
@@ -147,6 +156,9 @@ std::unique_ptr<BinaryPrimitive> TryParseColor(const android::StringPiece& str);
  */
 std::unique_ptr<BinaryPrimitive> TryParseBool(const android::StringPiece& str);
 
+// Returns a boolean BinaryPrimitive.
+std::unique_ptr<BinaryPrimitive> MakeBool(bool val);
+
 /*
  * Returns a BinaryPrimitve object representing an integer if the string was
  * parsed as one.
index 048c692..cdc34f1 100644 (file)
@@ -19,6 +19,9 @@
 #include "Resource.h"
 #include "test/Test.h"
 
+using ::aapt::test::ValueEq;
+using ::testing::Pointee;
+
 namespace aapt {
 
 TEST(ResourceUtilsTest, ParseBool) {
@@ -200,4 +203,22 @@ TEST(ResourceUtilsTest, ParseEmptyFlag) {
   EXPECT_EQ(0u, result->value.data);
 }
 
+TEST(ResourceUtilsTest, NullIsEmptyReference) {
+  auto null_value = ResourceUtils::MakeNull();
+  ASSERT_THAT(null_value, Pointee(ValueEq(Reference())));
+
+  auto value = ResourceUtils::TryParseNullOrEmpty("@null");
+  ASSERT_THAT(value, Pointee(ValueEq(Reference())));
+}
+
+TEST(ResourceUtilsTest, EmptyIsBinaryPrimitive) {
+  auto empty_value = ResourceUtils::MakeEmpty();
+  ASSERT_THAT(empty_value, Pointee(ValueEq(BinaryPrimitive(android::Res_value::TYPE_NULL,
+                                                           android::Res_value::DATA_NULL_EMPTY))));
+
+  auto value = ResourceUtils::TryParseNullOrEmpty("@empty");
+  ASSERT_THAT(value, Pointee(ValueEq(BinaryPrimitive(android::Res_value::TYPE_NULL,
+                                                     android::Res_value::DATA_NULL_EMPTY))));
+}
+
 }  // namespace aapt
index 34bd2b4..e808984 100644 (file)
 
 namespace aapt {
 
+std::ostream& operator<<(std::ostream& out, const Value& value) {
+  value.Print(&out);
+  return out;
+}
+
 template <typename Derived>
 void BaseValue<Derived>::Accept(RawValueVisitor* visitor) {
   visitor->Visit(static_cast<Derived*>(this));
@@ -89,8 +94,8 @@ bool Reference::Equals(const Value* value) const {
 
 bool Reference::Flatten(android::Res_value* out_value) const {
   const ResourceId resid = id.value_or_default(ResourceId(0));
-  const bool dynamic =
-      (resid.package_id() != kFrameworkPackageId && resid.package_id() != kAppPackageId);
+  const bool dynamic = resid.is_valid_dynamic() && resid.package_id() != kFrameworkPackageId &&
+                       resid.package_id() != kAppPackageId;
 
   if (reference_type == Reference::Type::kResource) {
     if (dynamic) {
@@ -114,22 +119,29 @@ Reference* Reference::Clone(StringPool* /*new_pool*/) const {
 }
 
 void Reference::Print(std::ostream* out) const {
-  *out << "(reference) ";
-  if (reference_type == Reference::Type::kResource) {
-    *out << "@";
-    if (private_reference) {
-      *out << "*";
+  if (reference_type == Type::kResource) {
+    *out << "(reference) @";
+    if (!name && !id) {
+      *out << "null";
+      return;
     }
   } else {
-    *out << "?";
+    *out << "(attr-reference) ?";
+  }
+
+  if (private_reference) {
+    *out << "*";
   }
 
   if (name) {
     *out << name.value();
   }
 
-  if (id && !Res_INTERNALID(id.value().id)) {
-    *out << " " << id.value();
+  if (id && id.value().is_valid_dynamic()) {
+    if (name) {
+      *out << " ";
+    }
+    *out << id.value();
   }
 }
 
@@ -309,7 +321,11 @@ BinaryPrimitive* BinaryPrimitive::Clone(StringPool* /*new_pool*/) const {
 void BinaryPrimitive::Print(std::ostream* out) const {
   switch (value.dataType) {
     case android::Res_value::TYPE_NULL:
-      *out << "(null)";
+      if (value.data == android::Res_value::DATA_NULL_EMPTY) {
+        *out << "(empty)";
+      } else {
+        *out << "(null)";
+      }
       break;
     case android::Res_value::TYPE_INT_DEC:
       *out << "(integer) " << static_cast<int32_t>(value.data);
@@ -346,6 +362,15 @@ Attribute::Attribute(bool w, uint32_t t)
   weak_ = w;
 }
 
+std::ostream& operator<<(std::ostream& out, const Attribute::Symbol& s) {
+  if (s.symbol.name) {
+    out << s.symbol.name.value().entry;
+  } else {
+    out << "???";
+  }
+  return out << "=" << s.value;
+}
+
 template <typename T>
 constexpr T* add_pointer(T& val) {
   return &val;
@@ -361,31 +386,27 @@ bool Attribute::Equals(const Value* value) const {
     return false;
   }
 
-  if (type_mask != other->type_mask || min_int != other->min_int ||
-      max_int != other->max_int) {
+  if (type_mask != other->type_mask || min_int != other->min_int || max_int != other->max_int) {
     return false;
   }
 
   std::vector<const Symbol*> sorted_a;
   std::transform(symbols.begin(), symbols.end(), std::back_inserter(sorted_a),
                  add_pointer<const Symbol>);
-  std::sort(sorted_a.begin(), sorted_a.end(),
-            [](const Symbol* a, const Symbol* b) -> bool {
-              return a->symbol.name < b->symbol.name;
-            });
+  std::sort(sorted_a.begin(), sorted_a.end(), [](const Symbol* a, const Symbol* b) -> bool {
+    return a->symbol.name < b->symbol.name;
+  });
 
   std::vector<const Symbol*> sorted_b;
-  std::transform(other->symbols.begin(), other->symbols.end(),
-                 std::back_inserter(sorted_b), add_pointer<const Symbol>);
-  std::sort(sorted_b.begin(), sorted_b.end(),
-            [](const Symbol* a, const Symbol* b) -> bool {
-              return a->symbol.name < b->symbol.name;
-            });
+  std::transform(other->symbols.begin(), other->symbols.end(), std::back_inserter(sorted_b),
+                 add_pointer<const Symbol>);
+  std::sort(sorted_b.begin(), sorted_b.end(), [](const Symbol* a, const Symbol* b) -> bool {
+    return a->symbol.name < b->symbol.name;
+  });
 
   return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
                     [](const Symbol* a, const Symbol* b) -> bool {
-                      return a->symbol.Equals(&b->symbol) &&
-                             a->value == b->value;
+                      return a->symbol.Equals(&b->symbol) && a->value == b->value;
                     });
 }
 
@@ -588,14 +609,50 @@ bool Attribute::Matches(const Item* item, DiagMessage* out_msg) const {
   return true;
 }
 
+std::ostream& operator<<(std::ostream& out, const Style::Entry& entry) {
+  if (entry.key.name) {
+    out << entry.key.name.value();
+  } else if (entry.key.id) {
+    out << entry.key.id.value();
+  } else {
+    out << "???";
+  }
+  out << " = " << entry.value;
+  return out;
+}
+
+template <typename T>
+std::vector<T*> ToPointerVec(std::vector<T>& src) {
+  std::vector<T*> dst;
+  dst.reserve(src.size());
+  for (T& in : src) {
+    dst.push_back(&in);
+  }
+  return dst;
+}
+
+template <typename T>
+std::vector<const T*> ToPointerVec(const std::vector<T>& src) {
+  std::vector<const T*> dst;
+  dst.reserve(src.size());
+  for (const T& in : src) {
+    dst.push_back(&in);
+  }
+  return dst;
+}
+
+static bool KeyNameComparator(const Style::Entry* a, const Style::Entry* b) {
+  return a->key.name < b->key.name;
+}
+
 bool Style::Equals(const Value* value) const {
   const Style* other = ValueCast<Style>(value);
   if (!other) {
     return false;
   }
+
   if (bool(parent) != bool(other->parent) ||
-      (parent && other->parent &&
-       !parent.value().Equals(&other->parent.value()))) {
+      (parent && other->parent && !parent.value().Equals(&other->parent.value()))) {
     return false;
   }
 
@@ -603,26 +660,15 @@ bool Style::Equals(const Value* value) const {
     return false;
   }
 
-  std::vector<const Entry*> sorted_a;
-  std::transform(entries.begin(), entries.end(), std::back_inserter(sorted_a),
-                 add_pointer<const Entry>);
-  std::sort(sorted_a.begin(), sorted_a.end(),
-            [](const Entry* a, const Entry* b) -> bool {
-              return a->key.name < b->key.name;
-            });
+  std::vector<const Entry*> sorted_a = ToPointerVec(entries);
+  std::sort(sorted_a.begin(), sorted_a.end(), KeyNameComparator);
 
-  std::vector<const Entry*> sorted_b;
-  std::transform(other->entries.begin(), other->entries.end(),
-                 std::back_inserter(sorted_b), add_pointer<const Entry>);
-  std::sort(sorted_b.begin(), sorted_b.end(),
-            [](const Entry* a, const Entry* b) -> bool {
-              return a->key.name < b->key.name;
-            });
+  std::vector<const Entry*> sorted_b = ToPointerVec(other->entries);
+  std::sort(sorted_b.begin(), sorted_b.end(), KeyNameComparator);
 
   return std::equal(sorted_a.begin(), sorted_a.end(), sorted_b.begin(),
                     [](const Entry* a, const Entry* b) -> bool {
-                      return a->key.Equals(&b->key) &&
-                             a->value->Equals(b->value.get());
+                      return a->key.Equals(&b->key) && a->value->Equals(b->value.get());
                     });
 }
 
@@ -633,8 +679,7 @@ Style* Style::Clone(StringPool* new_pool) const {
   style->comment_ = comment_;
   style->source_ = source_;
   for (auto& entry : entries) {
-    style->entries.push_back(
-        Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))});
+    style->entries.push_back(Entry{entry.key, std::unique_ptr<Item>(entry.value->Clone(new_pool))});
   }
   return style;
 }
@@ -642,26 +687,73 @@ Style* Style::Clone(StringPool* new_pool) const {
 void Style::Print(std::ostream* out) const {
   *out << "(style) ";
   if (parent && parent.value().name) {
-    if (parent.value().private_reference) {
+    const Reference& parent_ref = parent.value();
+    if (parent_ref.private_reference) {
       *out << "*";
     }
-    *out << parent.value().name.value();
+    *out << parent_ref.name.value();
   }
   *out << " [" << util::Joiner(entries, ", ") << "]";
 }
 
-static ::std::ostream& operator<<(::std::ostream& out,
-                                  const Style::Entry& value) {
-  if (value.key.name) {
-    out << value.key.name.value();
-  } else if (value.key.id) {
-    out << value.key.id.value();
-  } else {
-    out << "???";
+Style::Entry CloneEntry(const Style::Entry& entry, StringPool* pool) {
+  Style::Entry cloned_entry{entry.key};
+  if (entry.value != nullptr) {
+    cloned_entry.value.reset(entry.value->Clone(pool));
   }
-  out << " = ";
-  value.value->Print(&out);
-  return out;
+  return cloned_entry;
+}
+
+void Style::MergeWith(Style* other, StringPool* pool) {
+  if (other->parent) {
+    parent = other->parent;
+  }
+
+  // We can't assume that the entries are sorted alphabetically since they're supposed to be
+  // sorted by Resource Id. Not all Resource Ids may be set though, so we can't sort and merge
+  // them keying off that.
+  //
+  // Instead, sort the entries of each Style by their name in a separate structure. Then merge
+  // those.
+
+  std::vector<Entry*> this_sorted = ToPointerVec(entries);
+  std::sort(this_sorted.begin(), this_sorted.end(), KeyNameComparator);
+
+  std::vector<Entry*> other_sorted = ToPointerVec(other->entries);
+  std::sort(other_sorted.begin(), other_sorted.end(), KeyNameComparator);
+
+  auto this_iter = this_sorted.begin();
+  const auto this_end = this_sorted.end();
+
+  auto other_iter = other_sorted.begin();
+  const auto other_end = other_sorted.end();
+
+  std::vector<Entry> merged_entries;
+  while (this_iter != this_end) {
+    if (other_iter != other_end) {
+      if ((*this_iter)->key.name < (*other_iter)->key.name) {
+        merged_entries.push_back(std::move(**this_iter));
+        ++this_iter;
+      } else {
+        // The other overrides.
+        merged_entries.push_back(CloneEntry(**other_iter, pool));
+        if ((*this_iter)->key.name == (*other_iter)->key.name) {
+          ++this_iter;
+        }
+        ++other_iter;
+      }
+    } else {
+      merged_entries.push_back(std::move(**this_iter));
+      ++this_iter;
+    }
+  }
+
+  while (other_iter != other_end) {
+    merged_entries.push_back(CloneEntry(**other_iter, pool));
+    ++other_iter;
+  }
+
+  entries = std::move(merged_entries);
 }
 
 bool Array::Equals(const Value* value) const {
@@ -758,11 +850,6 @@ void Plural::Print(std::ostream* out) const {
   }
 }
 
-static ::std::ostream& operator<<(::std::ostream& out,
-                                  const std::unique_ptr<Item>& item) {
-  return out << *item;
-}
-
 bool Styleable::Equals(const Value* value) const {
   const Styleable* other = ValueCast<Styleable>(value);
   if (!other) {
@@ -810,8 +897,7 @@ struct NameOnlyComparator {
 
 void Styleable::MergeWith(Styleable* other) {
   // Compare only names, because some References may already have their IDs
-  // assigned
-  // (framework IDs that don't change).
+  // assigned (framework IDs that don't change).
   std::set<Reference, NameOnlyComparator> references;
   references.insert(entries.begin(), entries.end());
   references.insert(other->entries.begin(), other->entries.end());
index 06f949f..ac5795f 100644 (file)
@@ -40,7 +40,8 @@ struct RawValueVisitor;
 // type specific operations is to check the Value's type() and
 // cast it to the appropriate subclass. This isn't super clean,
 // but it is the simplest strategy.
-struct Value {
+class Value {
+ public:
   virtual ~Value() = default;
 
   // Whether this value is weak and can be overridden without warning or error. Default is false.
@@ -82,6 +83,8 @@ struct Value {
   // Human readable printout of this value.
   virtual void Print(std::ostream* out) const = 0;
 
+  friend std::ostream& operator<<(std::ostream& out, const Value& value);
+
  protected:
   Source source_;
   std::string comment_;
@@ -245,6 +248,8 @@ struct Attribute : public BaseValue<Attribute> {
   struct Symbol {
     Reference symbol;
     uint32_t value;
+
+    friend std::ostream& operator<<(std::ostream& out, const Symbol& symbol);
   };
 
   uint32_t type_mask;
@@ -266,6 +271,8 @@ struct Style : public BaseValue<Style> {
   struct Entry {
     Reference key;
     std::unique_ptr<Item> value;
+
+    friend std::ostream& operator<<(std::ostream& out, const Entry& entry);
   };
 
   Maybe<Reference> parent;
@@ -278,6 +285,10 @@ struct Style : public BaseValue<Style> {
   bool Equals(const Value* value) const override;
   Style* Clone(StringPool* new_pool) const override;
   void Print(std::ostream* out) const override;
+
+  // Merges `style` into this Style. All identical attributes of `style` take precedence, including
+  // the parent, if there is one.
+  void MergeWith(Style* style, StringPool* pool);
 };
 
 struct Array : public BaseValue<Array> {
@@ -307,20 +318,15 @@ struct Styleable : public BaseValue<Styleable> {
   void MergeWith(Styleable* styleable);
 };
 
-// Stream operator for printing Value objects.
-inline ::std::ostream& operator<<(::std::ostream& out, const Value& value) {
-  value.Print(&out);
-  return out;
-}
-
-inline ::std::ostream& operator<<(::std::ostream& out,
-                                  const Attribute::Symbol& s) {
-  if (s.symbol.name) {
-    out << s.symbol.name.value().entry;
+template <typename T>
+typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<(
+    std::ostream& out, const std::unique_ptr<T>& value) {
+  if (value == nullptr) {
+    out << "NULL";
   } else {
-    out << "???";
+    value->Print(&out);
   }
-  return out << "=" << s.value;
+  return out;
 }
 
 }  // namespace aapt
index 6922580..69f8e67 100644 (file)
@@ -148,4 +148,46 @@ TEST(ResourceValuesTest, StyleClone) {
   EXPECT_TRUE(a->Equals(b.get()));
 }
 
+TEST(ResourceValuesTest, StyleMerges) {
+  StringPool pool_a;
+  StringPool pool_b;
+
+  std::unique_ptr<Style> a =
+      test::StyleBuilder()
+          .SetParent("android:style/Parent")
+          .AddItem("android:attr/a", util::make_unique<String>(pool_a.MakeRef("FooA")))
+          .AddItem("android:attr/b", util::make_unique<String>(pool_a.MakeRef("FooB")))
+          .Build();
+
+  std::unique_ptr<Style> b =
+      test::StyleBuilder()
+          .SetParent("android:style/OverlayParent")
+          .AddItem("android:attr/c", util::make_unique<String>(pool_b.MakeRef("OverlayFooC")))
+          .AddItem("android:attr/a", util::make_unique<String>(pool_b.MakeRef("OverlayFooA")))
+          .Build();
+
+  a->MergeWith(b.get(), &pool_a);
+
+  StringPool pool;
+  std::unique_ptr<Style> expected =
+      test::StyleBuilder()
+          .SetParent("android:style/OverlayParent")
+          .AddItem("android:attr/a", util::make_unique<String>(pool.MakeRef("OverlayFooA")))
+          .AddItem("android:attr/b", util::make_unique<String>(pool.MakeRef("FooB")))
+          .AddItem("android:attr/c", util::make_unique<String>(pool.MakeRef("OverlayFooC")))
+          .Build();
+
+  EXPECT_TRUE(a->Equals(expected.get()));
+}
+
+// TYPE_NULL is encoded as TYPE_REFERENCE with a value of 0. This is represented in AAPT2
+// by a default constructed Reference value.
+TEST(ResourcesValuesTest, EmptyReferenceFlattens) {
+  android::Res_value value = {};
+  ASSERT_TRUE(Reference().Flatten(&value));
+
+  EXPECT_EQ(android::Res_value::TYPE_REFERENCE, value.dataType);
+  EXPECT_EQ(0x0u, value.data);
+}
+
 } // namespace aapt
index 5adf04a..e09a397 100644 (file)
@@ -478,7 +478,8 @@ static bool CompilePng(IAaptContext* context, const CompileOptions& options,
 
   {
     std::string content;
-    if (!android::base::ReadFileToString(path_data.source.path, &content)) {
+    if (!android::base::ReadFileToString(path_data.source.path, &content,
+                                         true /*follow_symlinks*/)) {
       context->GetDiagnostics()->Error(DiagMessage(path_data.source)
                                        << android::base::SystemErrorCodeToString(errno));
       return false;
index 24a687c..740a401 100644 (file)
@@ -440,7 +440,8 @@ static bool IsTransitionElement(const std::string& name) {
 }
 
 static bool IsVectorElement(const std::string& name) {
-  return name == "vector" || name == "animated-vector";
+  return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
+         name == "objectAnimator";
 }
 
 template <typename T>
@@ -632,7 +633,7 @@ static bool WriteStableIdMapToPath(IDiagnostics* diag,
 static bool LoadStableIdMap(IDiagnostics* diag, const std::string& path,
                             std::unordered_map<ResourceName, ResourceId>* out_id_map) {
   std::string content;
-  if (!android::base::ReadFileToString(path, &content)) {
+  if (!android::base::ReadFileToString(path, &content, true /*follow_symlinks*/)) {
     diag->Error(DiagMessage(path) << "failed reading stable ID file");
     return false;
   }
index 91f8bfd..2c9e8b8 100644 (file)
         <flag name="weak" value="4" />
     </attr>
 
+    <item name="value_that_allows_any_format" type="integer">-100%p</item>
+
     <!-- Override the Widget styleable declared in StaticLibOne.
          This should merge the two when built in overlay mode. -->
     <declare-styleable name="Widget">
         <attr name="android:text" />
         <attr name="layout_width" />
     </declare-styleable>
+
+    <!-- Declare an empty, resource -->
+    <item type="drawable" name="undefined" />
 </resources>
diff --git a/tools/aapt2/integration-tests/SymlinkTest/Android.mk b/tools/aapt2/integration-tests/SymlinkTest/Android.mk
new file mode 100644 (file)
index 0000000..902fc65
--- /dev/null
@@ -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.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_USE_AAPT2 := true
+LOCAL_PACKAGE_NAME := AaptSymlinkTest
+LOCAL_MODULE_TAGS := tests
+include $(BUILD_PACKAGE)
diff --git a/tools/aapt2/integration-tests/SymlinkTest/AndroidManifest.xml b/tools/aapt2/integration-tests/SymlinkTest/AndroidManifest.xml
new file mode 100644 (file)
index 0000000..abbfa53
--- /dev/null
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="com.android.aapt.symlinktest" />
diff --git a/tools/aapt2/integration-tests/SymlinkTest/res/drawable/white_3x3.9.png b/tools/aapt2/integration-tests/SymlinkTest/res/drawable/white_3x3.9.png
new file mode 120000 (symlink)
index 0000000..a7e8e2f
--- /dev/null
@@ -0,0 +1 @@
+../../targets/white_3x3.9.png
\ No newline at end of file
diff --git a/tools/aapt2/integration-tests/SymlinkTest/res/layout/layout.xml b/tools/aapt2/integration-tests/SymlinkTest/res/layout/layout.xml
new file mode 120000 (symlink)
index 0000000..29c30e1
--- /dev/null
@@ -0,0 +1 @@
+../../targets/layout.xml
\ No newline at end of file
diff --git a/tools/aapt2/integration-tests/SymlinkTest/res/values/values.xml b/tools/aapt2/integration-tests/SymlinkTest/res/values/values.xml
new file mode 120000 (symlink)
index 0000000..554bb71
--- /dev/null
@@ -0,0 +1 @@
+../../targets/values.xml
\ No newline at end of file
diff --git a/tools/aapt2/integration-tests/SymlinkTest/targets/layout.xml b/tools/aapt2/integration-tests/SymlinkTest/targets/layout.xml
new file mode 100644 (file)
index 0000000..e5835ed
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<View xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" />
diff --git a/tools/aapt2/integration-tests/SymlinkTest/targets/values.xml b/tools/aapt2/integration-tests/SymlinkTest/targets/values.xml
new file mode 100644 (file)
index 0000000..5b02843
--- /dev/null
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<resources>
+    <bool name="foo">true</bool>
+</resources>
diff --git a/tools/aapt2/integration-tests/SymlinkTest/targets/white_3x3.9.png b/tools/aapt2/integration-tests/SymlinkTest/targets/white_3x3.9.png
new file mode 100644 (file)
index 0000000..1a3731b
Binary files /dev/null and b/tools/aapt2/integration-tests/SymlinkTest/targets/white_3x3.9.png differ
index 18498e3..a8e510c 100644 (file)
@@ -296,7 +296,10 @@ bool ReferenceLinker::LinkReference(const CallSite& callsite, Reference* referen
                                     IAaptContext* context, SymbolTable* symbols,
                                     xml::IPackageDeclStack* decls) {
   CHECK(reference != nullptr);
-  CHECK(reference->name || reference->id);
+  if (!reference->name && !reference->id) {
+    // This is @null.
+    return true;
+  }
 
   Reference transformed_reference = *reference;
   TransformReferenceFromNamespace(decls, context->GetCompilationPackage(), &transformed_reference);
index 9311091..10e837c 100644 (file)
@@ -179,32 +179,39 @@ static bool MergeEntry(IAaptContext* context, const Source& src,
   return true;
 }
 
-/**
- * Modified CollisionResolver which will merge Styleables. Used with overlays.
- *
- * Styleables are not actual resources, but they are treated as such during the
- * compilation phase. Styleables don't simply overlay each other, their
- * definitions merge
- * and accumulate. If both values are Styleables, we just merge them into the
- * existing value.
- */
-static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing,
-                                                            Value* incoming) {
+// Modified CollisionResolver which will merge Styleables and Styles. Used with overlays.
+//
+// Styleables are not actual resources, but they are treated as such during the
+// compilation phase.
+//
+// Styleables and Styles don't simply overlay each other, their definitions merge
+// and accumulate. If both values are Styleables/Styles, we just merge them into the
+// existing value.
+static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Value* incoming,
+                                                            StringPool* pool) {
   if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) {
     if (Styleable* incoming_styleable = ValueCast<Styleable>(incoming)) {
       // Styleables get merged.
       existing_styleable->MergeWith(incoming_styleable);
       return ResourceTable::CollisionResult::kKeepOriginal;
     }
+  } else if (Style* existing_style = ValueCast<Style>(existing)) {
+    if (Style* incoming_style = ValueCast<Style>(incoming)) {
+      // Styles get merged.
+      existing_style->MergeWith(incoming_style, pool);
+      return ResourceTable::CollisionResult::kKeepOriginal;
+    }
   }
   // Delegate to the default handler.
   return ResourceTable::ResolveValueCollision(existing, incoming);
 }
 
-static ResourceTable::CollisionResult MergeConfigValue(
-    IAaptContext* context, const ResourceNameRef& res_name, const bool overlay,
-    ResourceConfigValue* dst_config_value,
-    ResourceConfigValue* src_config_value) {
+static ResourceTable::CollisionResult MergeConfigValue(IAaptContext* context,
+                                                       const ResourceNameRef& res_name,
+                                                       const bool overlay,
+                                                       ResourceConfigValue* dst_config_value,
+                                                       ResourceConfigValue* src_config_value,
+                                                       StringPool* pool) {
   using CollisionResult = ResourceTable::CollisionResult;
 
   Value* dst_value = dst_config_value->value.get();
@@ -212,10 +219,9 @@ static ResourceTable::CollisionResult MergeConfigValue(
 
   CollisionResult collision_result;
   if (overlay) {
-    collision_result = ResolveMergeCollision(dst_value, src_value);
+    collision_result = ResolveMergeCollision(dst_value, src_value, pool);
   } else {
-    collision_result =
-        ResourceTable::ResolveValueCollision(dst_value, src_value);
+    collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value);
   }
 
   if (collision_result == CollisionResult::kConflict) {
@@ -224,10 +230,9 @@ static ResourceTable::CollisionResult MergeConfigValue(
     }
 
     // Error!
-    context->GetDiagnostics()->Error(
-        DiagMessage(src_value->GetSource())
-        << "resource '" << res_name << "' has a conflicting value for "
-        << "configuration (" << src_config_value->config << ")");
+    context->GetDiagnostics()->Error(DiagMessage(src_value->GetSource())
+                                     << "resource '" << res_name << "' has a conflicting value for "
+                                     << "configuration (" << src_config_value->config << ")");
     context->GetDiagnostics()->Note(DiagMessage(dst_value->GetSource())
                                     << "originally defined here");
     return CollisionResult::kConflict;
@@ -243,8 +248,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
   bool error = false;
 
   for (auto& src_type : src_package->types) {
-    ResourceTableType* dst_type =
-        master_package_->FindOrCreateType(src_type->type);
+    ResourceTableType* dst_type = master_package_->FindOrCreateType(src_type->type);
     if (!MergeType(context_, src, dst_type, src_type.get())) {
       error = true;
       continue;
@@ -253,27 +257,24 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
     for (auto& src_entry : src_type->entries) {
       std::string entry_name = src_entry->name;
       if (mangle_package) {
-        entry_name =
-            NameMangler::MangleEntry(src_package->name, src_entry->name);
+        entry_name = NameMangler::MangleEntry(src_package->name, src_entry->name);
       }
 
       ResourceEntry* dst_entry;
-      if (allow_new_resources) {
+      if (allow_new_resources || src_entry->symbol_status.allow_new) {
         dst_entry = dst_type->FindOrCreateEntry(entry_name);
       } else {
         dst_entry = dst_type->FindEntry(entry_name);
       }
 
-      const ResourceNameRef res_name(src_package->name, src_type->type,
-                                     src_entry->name);
+      const ResourceNameRef res_name(src_package->name, src_type->type, src_entry->name);
 
       if (!dst_entry) {
-        context_->GetDiagnostics()->Error(
-            DiagMessage(src) << "resource " << res_name
-                             << " does not override an existing resource");
-        context_->GetDiagnostics()->Note(
-            DiagMessage(src) << "define an <add-resource> tag or use "
-                             << "--auto-add-overlay");
+        context_->GetDiagnostics()->Error(DiagMessage(src)
+                                          << "resource " << res_name
+                                          << " does not override an existing resource");
+        context_->GetDiagnostics()->Note(DiagMessage(src) << "define an <add-resource> tag or use "
+                                                          << "--auto-add-overlay");
         error = true;
         continue;
       }
@@ -291,7 +292,7 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
         if (dst_config_value) {
           CollisionResult collision_result =
               MergeConfigValue(context_, res_name, overlay, dst_config_value,
-                               src_config_value.get());
+                               src_config_value.get(), &master_table_->string_pool);
           if (collision_result == CollisionResult::kConflict) {
             error = true;
             continue;
@@ -299,25 +300,22 @@ bool TableMerger::DoMerge(const Source& src, ResourceTable* src_table,
             continue;
           }
         } else {
-          dst_config_value = dst_entry->FindOrCreateValue(
-              src_config_value->config, src_config_value->product);
+          dst_config_value =
+              dst_entry->FindOrCreateValue(src_config_value->config, src_config_value->product);
         }
 
         // Continue if we're taking the new resource.
 
-        if (FileReference* f =
-                ValueCast<FileReference>(src_config_value->value.get())) {
+        if (FileReference* f = ValueCast<FileReference>(src_config_value->value.get())) {
           std::unique_ptr<FileReference> new_file_ref;
           if (mangle_package) {
             new_file_ref = CloneAndMangleFile(src_package->name, *f);
           } else {
-            new_file_ref = std::unique_ptr<FileReference>(
-                f->Clone(&master_table_->string_pool));
+            new_file_ref = std::unique_ptr<FileReference>(f->Clone(&master_table_->string_pool));
           }
 
           if (callback) {
-            if (!callback(res_name, src_config_value->config,
-                          new_file_ref.get(), f)) {
+            if (!callback(res_name, src_config_value->config, new_file_ref.get(), f)) {
               error = true;
               continue;
             }
@@ -341,18 +339,15 @@ std::unique_ptr<FileReference> TableMerger::CloneAndMangleFile(
     std::string mangled_entry = NameMangler::MangleEntry(package, entry.to_string());
     std::string newPath = prefix.to_string() + mangled_entry + suffix.to_string();
     std::unique_ptr<FileReference> new_file_ref =
-        util::make_unique<FileReference>(
-            master_table_->string_pool.MakeRef(newPath));
+        util::make_unique<FileReference>(master_table_->string_pool.MakeRef(newPath));
     new_file_ref->SetComment(file_ref.GetComment());
     new_file_ref->SetSource(file_ref.GetSource());
     return new_file_ref;
   }
-  return std::unique_ptr<FileReference>(
-      file_ref.Clone(&master_table_->string_pool));
+  return std::unique_ptr<FileReference>(file_ref.Clone(&master_table_->string_pool));
 }
 
-bool TableMerger::MergeFileImpl(const ResourceFile& file_desc, io::IFile* file,
-                                bool overlay) {
+bool TableMerger::MergeFileImpl(const ResourceFile& file_desc, io::IFile* file, bool overlay) {
   ResourceTable table;
   std::string path = ResourceUtils::BuildResourceFileName(file_desc);
   std::unique_ptr<FileReference> file_ref =
index 742f5a7..45b01a4 100644 (file)
 #include "io/FileSystem.h"
 #include "test/Test.h"
 
+using ::aapt::test::ValueEq;
+using ::testing::Contains;
+using ::testing::NotNull;
+using ::testing::UnorderedElementsAreArray;
+using ::testing::Pointee;
+using ::testing::Field;
+using ::testing::Eq;
+
 namespace aapt {
 
 struct TableMergerTest : public ::testing::Test {
@@ -62,26 +70,20 @@ TEST_F(TableMergerTest, SimpleMerge) {
   io::FileCollection collection;
 
   ASSERT_TRUE(merger.Merge({}, table_a.get()));
-  ASSERT_TRUE(
-      merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection));
+  ASSERT_TRUE(merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection));
 
   EXPECT_TRUE(merger.merged_packages().count("com.app.b") != 0);
 
   // Entries from com.app.a should not be mangled.
-  AAPT_EXPECT_TRUE(
-      final_table.FindResource(test::ParseNameOrDie("com.app.a:id/foo")));
-  AAPT_EXPECT_TRUE(
-      final_table.FindResource(test::ParseNameOrDie("com.app.a:id/bar")));
-  AAPT_EXPECT_TRUE(final_table.FindResource(
-      test::ParseNameOrDie("com.app.a:styleable/view")));
+  EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/foo")));
+  EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/bar")));
+  EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:styleable/view")));
 
   // The unmangled name should not be present.
-  AAPT_EXPECT_FALSE(
-      final_table.FindResource(test::ParseNameOrDie("com.app.b:id/foo")));
+  EXPECT_FALSE(final_table.FindResource(test::ParseNameOrDie("com.app.b:id/foo")));
 
   // Look for the mangled name.
-  AAPT_EXPECT_TRUE(final_table.FindResource(
-      test::ParseNameOrDie("com.app.a:id/com.app.b$foo")));
+  EXPECT_TRUE(final_table.FindResource(test::ParseNameOrDie("com.app.a:id/com.app.b$foo")));
 }
 
 TEST_F(TableMergerTest, MergeFile) {
@@ -100,7 +102,7 @@ TEST_F(TableMergerTest, MergeFile) {
 
   FileReference* file = test::GetValueForConfig<FileReference>(
       &final_table, "com.app.a:layout/main", test::ParseConfigOrDie("hdpi-v4"));
-  ASSERT_NE(nullptr, file);
+  ASSERT_THAT(file, NotNull());
   EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path);
 }
 
@@ -137,17 +139,14 @@ TEST_F(TableMergerTest, MergeFileReferences) {
   collection.InsertFile("res/xml/file.xml");
 
   ASSERT_TRUE(merger.Merge({}, table_a.get()));
-  ASSERT_TRUE(
-      merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection));
+  ASSERT_TRUE(merger.MergeAndMangle({}, "com.app.b", table_b.get(), &collection));
 
-  FileReference* f =
-      test::GetValue<FileReference>(&final_table, "com.app.a:xml/file");
-  ASSERT_NE(f, nullptr);
+  FileReference* f = test::GetValue<FileReference>(&final_table, "com.app.a:xml/file");
+  ASSERT_THAT(f, NotNull());
   EXPECT_EQ(std::string("res/xml/file.xml"), *f->path);
 
-  f = test::GetValue<FileReference>(&final_table,
-                                    "com.app.a:xml/com.app.b$file");
-  ASSERT_NE(f, nullptr);
+  f = test::GetValue<FileReference>(&final_table, "com.app.a:xml/com.app.b$file");
+  ASSERT_THAT(f, NotNull());
   EXPECT_EQ(std::string("res/xml/com.app.b$file.xml"), *f->path);
 }
 
@@ -171,10 +170,9 @@ TEST_F(TableMergerTest, OverrideResourceWithOverlay) {
   ASSERT_TRUE(merger.Merge({}, base.get()));
   ASSERT_TRUE(merger.MergeOverlay({}, overlay.get()));
 
-  BinaryPrimitive* foo =
-      test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/foo");
-  ASSERT_NE(nullptr, foo);
-  EXPECT_EQ(0x0u, foo->value.data);
+  BinaryPrimitive* foo = test::GetValue<BinaryPrimitive>(&final_table, "com.app.a:bool/foo");
+  ASSERT_THAT(foo,
+              Pointee(Field(&BinaryPrimitive::value, Field(&android::Res_value::data, Eq(0u)))));
 }
 
 TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
@@ -248,18 +246,18 @@ TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
 
 TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
   std::unique_ptr<ResourceTable> table_a =
-      test::ResourceTableBuilder()
-          .SetPackageId("", 0x7f)
-          .SetSymbolState("bool/foo", {}, SymbolState::kUndefined)
-          .Build();
+      test::ResourceTableBuilder().SetPackageId("", 0x7f).Build();
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
           .SetPackageId("", 0x7f)
+          .SetSymbolState("bool/foo", {}, SymbolState::kUndefined, true /*allow new overlay*/)
           .AddValue("bool/foo", ResourceUtils::TryParseBool("true"))
           .Build();
 
   ResourceTable final_table;
-  TableMerger merger(context_.get(), &final_table, TableMergerOptions{});
+  TableMergerOptions options;
+  options.auto_add_overlay = false;
+  TableMerger merger(context_.get(), &final_table, options);
 
   ASSERT_TRUE(merger.Merge({}, table_a.get()));
   ASSERT_TRUE(merger.MergeOverlay({}, table_b.get()));
@@ -301,7 +299,7 @@ TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
   ASSERT_FALSE(merger.MergeOverlay({}, table_b.get()));
 }
 
-TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) {
+TEST_F(TableMergerTest, OverlaidStyleablesAndStylesShouldBeMerged) {
   std::unique_ptr<ResourceTable> table_a =
       test::ResourceTableBuilder()
           .SetPackageId("com.app.a", 0x7f)
@@ -310,15 +308,27 @@ TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) {
                         .AddItem("com.app.a:attr/bar")
                         .AddItem("com.app.a:attr/foo", ResourceId(0x01010000))
                         .Build())
+          .AddValue("com.app.a:style/Theme",
+                    test::StyleBuilder()
+                        .SetParent("com.app.a:style/Parent")
+                        .AddItem("com.app.a:attr/bar", util::make_unique<Id>())
+                        .AddItem("com.app.a:attr/foo", ResourceUtils::MakeBool(false))
+                        .Build())
           .Build();
 
   std::unique_ptr<ResourceTable> table_b =
       test::ResourceTableBuilder()
           .SetPackageId("com.app.a", 0x7f)
-          .AddValue("com.app.a:styleable/Foo",
-                    test::StyleableBuilder()
-                        .AddItem("com.app.a:attr/bat")
-                        .AddItem("com.app.a:attr/foo")
+          .AddValue("com.app.a:styleable/Foo", test::StyleableBuilder()
+                                                   .AddItem("com.app.a:attr/bat")
+                                                   .AddItem("com.app.a:attr/foo")
+                                                   .Build())
+          .AddValue("com.app.a:style/Theme",
+                    test::StyleBuilder()
+                        .SetParent("com.app.a:style/OverlayParent")
+                        .AddItem("com.app.a:attr/bat", util::make_unique<Id>())
+                        .AddItem("com.app.a:attr/foo", ResourceId(0x01010000),
+                                 ResourceUtils::MakeBool(true))
                         .Build())
           .Build();
 
@@ -330,18 +340,29 @@ TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) {
   ASSERT_TRUE(merger.Merge({}, table_a.get()));
   ASSERT_TRUE(merger.MergeOverlay({}, table_b.get()));
 
-  Styleable* styleable =
-      test::GetValue<Styleable>(&final_table, "com.app.a:styleable/Foo");
-  ASSERT_NE(nullptr, styleable);
+  Styleable* styleable = test::GetValue<Styleable>(&final_table, "com.app.a:styleable/Foo");
+  ASSERT_THAT(styleable, NotNull());
 
   std::vector<Reference> expected_refs = {
       Reference(test::ParseNameOrDie("com.app.a:attr/bar")),
       Reference(test::ParseNameOrDie("com.app.a:attr/bat")),
-      Reference(test::ParseNameOrDie("com.app.a:attr/foo"),
-                ResourceId(0x01010000)),
+      Reference(test::ParseNameOrDie("com.app.a:attr/foo"), ResourceId(0x01010000)),
   };
+  EXPECT_THAT(styleable->entries, UnorderedElementsAreArray(expected_refs));
+
+  Style* style = test::GetValue<Style>(&final_table, "com.app.a:style/Theme");
+  ASSERT_THAT(style, NotNull());
+
+  std::vector<Reference> extracted_refs;
+  for (const auto& entry : style->entries) {
+    extracted_refs.push_back(entry.key);
+  }
+  EXPECT_THAT(extracted_refs, UnorderedElementsAreArray(expected_refs));
 
-  EXPECT_EQ(expected_refs, styleable->entries);
+  const auto expected = ResourceUtils::MakeBool(true);
+  EXPECT_THAT(style->entries, Contains(Field(&Style::Entry::value, Pointee(ValueEq(*expected)))));
+  EXPECT_THAT(style->parent,
+              Eq(make_value(Reference(test::ParseNameOrDie("com.app.a:style/OverlayParent")))));
 }
 
 }  // namespace aapt
index d93d495..4b56192 100644 (file)
@@ -32,8 +32,7 @@ class ReferenceIdToNameVisitor : public ValueVisitor {
  public:
   using ValueVisitor::Visit;
 
-  explicit ReferenceIdToNameVisitor(
-      const std::map<ResourceId, ResourceNameRef>* mapping)
+  explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping)
       : mapping_(mapping) {
     CHECK(mapping_ != nullptr);
   }
@@ -75,13 +74,11 @@ class PackagePbDeserializer {
 
     std::map<ResourceId, ResourceNameRef> idIndex;
 
-    ResourceTablePackage* pkg =
-        table->CreatePackage(pbPackage.package_name(), id);
+    ResourceTablePackage* pkg = table->CreatePackage(pbPackage.package_name(), id);
     for (const pb::Type& pbType : pbPackage.types()) {
       const ResourceType* resType = ParseResourceType(pbType.name());
       if (!resType) {
-        diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name()
-                                          << "'");
+        diag_->Error(DiagMessage(source_) << "unknown type '" << pbType.name() << "'");
         return {};
       }
 
@@ -95,21 +92,20 @@ class PackagePbDeserializer {
         if (pbEntry.has_symbol_status()) {
           const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
           if (pbStatus.has_source()) {
-            DeserializeSourceFromPb(pbStatus.source(), *source_pool_,
-                                    &entry->symbol_status.source);
+            DeserializeSourceFromPb(pbStatus.source(), *source_pool_, &entry->symbol_status.source);
           }
 
           if (pbStatus.has_comment()) {
             entry->symbol_status.comment = pbStatus.comment();
           }
 
-          SymbolState visibility =
-              DeserializeVisibilityFromPb(pbStatus.visibility());
+          entry->symbol_status.allow_new = pbStatus.allow_new();
+
+          SymbolState visibility = DeserializeVisibilityFromPb(pbStatus.visibility());
           entry->symbol_status.state = visibility;
 
           if (visibility == SymbolState::kPublic) {
-            // This is a public symbol, we must encode the ID now if there is
-            // one.
+            // This is a public symbol, we must encode the ID now if there is one.
             if (pbEntry.has_id()) {
               entry->id = static_cast<uint16_t>(pbEntry.id());
             }
@@ -142,16 +138,15 @@ class PackagePbDeserializer {
             return {};
           }
 
-          ResourceConfigValue* configValue =
-              entry->FindOrCreateValue(config, pbConfig.product());
+          ResourceConfigValue* configValue = entry->FindOrCreateValue(config, pbConfig.product());
           if (configValue->value) {
             // Duplicate config.
             diag_->Error(DiagMessage(source_) << "duplicate configuration");
             return {};
           }
 
-          configValue->value = DeserializeValueFromPb(
-              pbConfigValue.value(), config, &table->string_pool);
+          configValue->value =
+              DeserializeValueFromPb(pbConfigValue.value(), config, &table->string_pool);
           if (!configValue->value) {
             return {};
           }
@@ -348,26 +343,19 @@ class PackagePbDeserializer {
     return value;
   }
 
-  bool DeserializeReferenceFromPb(const pb::Reference& pb_ref,
-                                  Reference* out_ref) {
+  bool DeserializeReferenceFromPb(const pb::Reference& pb_ref, Reference* out_ref) {
     out_ref->reference_type = DeserializeReferenceTypeFromPb(pb_ref.type());
     out_ref->private_reference = pb_ref.private_();
 
-    if (!pb_ref.has_id() && !pb_ref.has_symbol_idx()) {
-      return false;
-    }
-
     if (pb_ref.has_id()) {
       out_ref->id = ResourceId(pb_ref.id());
     }
 
     if (pb_ref.has_symbol_idx()) {
-      const std::string str_symbol =
-          util::GetString(*symbol_pool_, pb_ref.symbol_idx());
+      const std::string str_symbol = util::GetString(*symbol_pool_, pb_ref.symbol_idx());
       ResourceNameRef name_ref;
       if (!ResourceUtils::ParseResourceName(str_symbol, &name_ref, nullptr)) {
-        diag_->Error(DiagMessage(source_) << "invalid reference name '"
-                                          << str_symbol << "'");
+        diag_->Error(DiagMessage(source_) << "invalid reference name '" << str_symbol << "'");
         return false;
       }
 
index 7230b55..d87d64e 100644 (file)
@@ -190,8 +190,7 @@ class PbSerializerVisitor : public RawValueVisitor {
     }
 
     if (ref.name) {
-      StringPool::Ref symbol_ref =
-          symbol_pool_->MakeRef(ref.name.value().ToString());
+      StringPool::Ref symbol_ref = symbol_pool_->MakeRef(ref.name.value().ToString());
       pb_ref->set_symbol_idx(static_cast<uint32_t>(symbol_ref.index()));
     }
 
@@ -250,19 +249,16 @@ std::unique_ptr<pb::ResourceTable> SerializeTableToPb(ResourceTable* table) {
 
         // Write the SymbolStatus struct.
         pb::SymbolStatus* pb_status = pb_entry->mutable_symbol_status();
-        pb_status->set_visibility(
-            SerializeVisibilityToPb(entry->symbol_status.state));
-        SerializeSourceToPb(entry->symbol_status.source, &source_pool,
-                            pb_status->mutable_source());
+        pb_status->set_visibility(SerializeVisibilityToPb(entry->symbol_status.state));
+        SerializeSourceToPb(entry->symbol_status.source, &source_pool, pb_status->mutable_source());
         pb_status->set_comment(entry->symbol_status.comment);
+        pb_status->set_allow_new(entry->symbol_status.allow_new);
 
         for (auto& config_value : entry->values) {
           pb::ConfigValue* pb_config_value = pb_entry->add_config_values();
-          SerializeConfig(config_value->config,
-                          pb_config_value->mutable_config());
+          SerializeConfig(config_value->config, pb_config_value->mutable_config());
           if (!config_value->product.empty()) {
-            pb_config_value->mutable_config()->set_product(
-                config_value->product);
+            pb_config_value->mutable_config()->set_product(config_value->product);
           }
 
           pb::Value* pb_value = pb_config_value->mutable_value();
index fdd5197..e6ce6d3 100644 (file)
@@ -28,12 +28,11 @@ TEST(TableProtoSerializer, SerializeSinglePackage) {
   std::unique_ptr<ResourceTable> table =
       test::ResourceTableBuilder()
           .SetPackageId("com.app.a", 0x7f)
-          .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000),
-                            "res/layout/main.xml")
-          .AddReference("com.app.a:layout/other", ResourceId(0x7f020001),
-                        "com.app.a:layout/main")
+          .AddFileReference("com.app.a:layout/main", ResourceId(0x7f020000), "res/layout/main.xml")
+          .AddReference("com.app.a:layout/other", ResourceId(0x7f020001), "com.app.a:layout/main")
           .AddString("com.app.a:string/text", {}, "hi")
           .AddValue("com.app.a:id/foo", {}, util::make_unique<Id>())
+          .SetSymbolState("com.app.a:bool/foo", {}, SymbolState::kUndefined, true /*allow_new*/)
           .Build();
 
   Symbol public_symbol;
@@ -94,21 +93,23 @@ TEST(TableProtoSerializer, SerializeSinglePackage) {
   EXPECT_EQ(SymbolState::kPublic, result.value().type->symbol_status.state);
   EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbol_status.state);
 
+  result = new_table->FindResource(test::ParseNameOrDie("com.app.a:bool/foo"));
+  ASSERT_TRUE(result);
+  EXPECT_EQ(SymbolState::kUndefined, result.value().entry->symbol_status.state);
+  EXPECT_TRUE(result.value().entry->symbol_status.allow_new);
+
   // Find the product-dependent values
   BinaryPrimitive* prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
-      new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"),
-      "");
+      new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), "");
   ASSERT_NE(nullptr, prim);
   EXPECT_EQ(123u, prim->value.data);
 
   prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
-      new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"),
-      "tablet");
+      new_table.get(), "com.app.a:integer/one", test::ParseConfigOrDie("land"), "tablet");
   ASSERT_NE(nullptr, prim);
   EXPECT_EQ(321u, prim->value.data);
 
-  Reference* actual_ref =
-      test::GetValue<Reference>(new_table.get(), "com.app.a:layout/abc");
+  Reference* actual_ref = test::GetValue<Reference>(new_table.get(), "com.app.a:layout/abc");
   ASSERT_NE(nullptr, actual_ref);
   AAPT_ASSERT_TRUE(actual_ref->name);
   AAPT_ASSERT_TRUE(actual_ref->id);
index 7e28ae7..0290e30 100644 (file)
@@ -1,5 +1,10 @@
 # Android Asset Packaging Tool 2.0 (AAPT2) release notes
 
+## Version 2.17
+### `aapt2 compile ...`
+- Fixed an issue where symlinks would not be followed when compiling PNGs. (bug 62144459)
+- Fixed issue where overlays that declared `<add-resource>` did not compile. (bug 38355988)
+
 ## Version 2.16
 ### `aapt2 link ...`
 - Versioning of XML files is more intelligent, using a small set of rules to degrade
index 6888cf3..f3da780 100644 (file)
@@ -59,8 +59,7 @@ class ResourceTableBuilder {
 
   ResourceTableBuilder& AddReference(const android::StringPiece& name, const ResourceId& id,
                                      const android::StringPiece& ref) {
-    return AddValue(name, id,
-                    util::make_unique<Reference>(ParseNameOrDie(ref)));
+    return AddValue(name, id, util::make_unique<Reference>(ParseNameOrDie(ref)));
   }
 
   ResourceTableBuilder& AddString(const android::StringPiece& name,
@@ -111,18 +110,18 @@ class ResourceTableBuilder {
   ResourceTableBuilder& AddValue(const android::StringPiece& name, const ConfigDescription& config,
                                  const ResourceId& id, std::unique_ptr<Value> value) {
     ResourceName res_name = ParseNameOrDie(name);
-    CHECK(table_->AddResourceAllowMangled(res_name, id, config, {},
-                                          std::move(value), &diagnostics_));
+    CHECK(table_->AddResourceAllowMangled(res_name, id, config, {}, std::move(value),
+                                          GetDiagnostics()));
     return *this;
   }
 
   ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id,
-                                       SymbolState state) {
+                                       SymbolState state, bool allow_new = false) {
     ResourceName res_name = ParseNameOrDie(name);
     Symbol symbol;
     symbol.state = state;
-    CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol,
-                                             &diagnostics_));
+    symbol.allow_new = allow_new;
+    CHECK(table_->SetSymbolStateAllowMangled(res_name, id, symbol, GetDiagnostics()));
     return *this;
   }
 
@@ -131,7 +130,6 @@ class ResourceTableBuilder {
  private:
   DISALLOW_COPY_AND_ASSIGN(ResourceTableBuilder);
 
-  DummyDiagnosticsImpl diagnostics_;
   std::unique_ptr<ResourceTable> table_ = util::make_unique<ResourceTable>();
 };
 
diff --git a/tools/aapt2/test/Common.cpp b/tools/aapt2/test/Common.cpp
new file mode 100644 (file)
index 0000000..0fabbc4
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "test/Common.h"
+
+namespace aapt {
+namespace test {
+
+struct DummyDiagnosticsImpl : public IDiagnostics {
+  void Log(Level level, DiagMessageActual& actual_msg) override {
+    switch (level) {
+      case Level::Note:
+        return;
+
+      case Level::Warn:
+        std::cerr << actual_msg.source << ": warn: " << actual_msg.message << "." << std::endl;
+        break;
+
+      case Level::Error:
+        std::cerr << actual_msg.source << ": error: " << actual_msg.message << "." << std::endl;
+        break;
+    }
+  }
+};
+
+IDiagnostics* GetDiagnostics() {
+  static DummyDiagnosticsImpl diag;
+  return &diag;
+}
+
+template <>
+Value* GetValueForConfigAndProduct<Value>(ResourceTable* table,
+                                          const android::StringPiece& res_name,
+                                          const ConfigDescription& config,
+                                          const android::StringPiece& product) {
+  Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name));
+  if (result) {
+    ResourceConfigValue* config_value = result.value().entry->FindValue(config, product);
+    if (config_value) {
+      return config_value->value.get();
+    }
+  }
+  return nullptr;
+}
+
+}  // namespace test
+}  // namespace aapt
index 248921f..0585148 100644 (file)
 #include "android-base/logging.h"
 #include "android-base/macros.h"
 #include "androidfw/StringPiece.h"
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
 #include "ConfigDescription.h"
 #include "Debug.h"
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
+#include "ResourceValues.h"
 #include "ValueVisitor.h"
 #include "io/File.h"
 #include "process/IResourceTableConsumer.h"
 namespace aapt {
 namespace test {
 
-struct DummyDiagnosticsImpl : public IDiagnostics {
-  void Log(Level level, DiagMessageActual& actual_msg) override {
-    switch (level) {
-      case Level::Note:
-        return;
-
-      case Level::Warn:
-        std::cerr << actual_msg.source << ": warn: " << actual_msg.message
-                  << "." << std::endl;
-        break;
-
-      case Level::Error:
-        std::cerr << actual_msg.source << ": error: " << actual_msg.message
-                  << "." << std::endl;
-        break;
-    }
-  }
-};
-
-inline IDiagnostics* GetDiagnostics() {
-  static DummyDiagnosticsImpl diag;
-  return &diag;
-}
+IDiagnostics* GetDiagnostics();
 
 inline ResourceName ParseNameOrDie(const android::StringPiece& str) {
   ResourceNameRef ref;
@@ -80,15 +60,13 @@ inline ConfigDescription ParseConfigOrDie(const android::StringPiece& str) {
   return config;
 }
 
-template <typename T>
+template <typename T = Value>
 T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece& res_name,
                                const ConfigDescription& config,
                                const android::StringPiece& product) {
-  Maybe<ResourceTable::SearchResult> result =
-      table->FindResource(ParseNameOrDie(res_name));
+  Maybe<ResourceTable::SearchResult> result = table->FindResource(ParseNameOrDie(res_name));
   if (result) {
-    ResourceConfigValue* config_value =
-        result.value().entry->FindValue(config, product);
+    ResourceConfigValue* config_value = result.value().entry->FindValue(config, product);
     if (config_value) {
       return ValueCast<T>(config_value->value.get());
     }
@@ -96,13 +74,19 @@ T* GetValueForConfigAndProduct(ResourceTable* table, const android::StringPiece&
   return nullptr;
 }
 
-template <typename T>
+template <>
+Value* GetValueForConfigAndProduct<Value>(ResourceTable* table,
+                                          const android::StringPiece& res_name,
+                                          const ConfigDescription& config,
+                                          const android::StringPiece& product);
+
+template <typename T = Value>
 T* GetValueForConfig(ResourceTable* table, const android::StringPiece& res_name,
                      const ConfigDescription& config) {
   return GetValueForConfigAndProduct<T>(table, res_name, config, {});
 }
 
-template <typename T>
+template <typename T = Value>
 T* GetValue(ResourceTable* table, const android::StringPiece& res_name) {
   return GetValueForConfig<T>(table, res_name, {});
 }
@@ -111,9 +95,13 @@ class TestFile : public io::IFile {
  public:
   explicit TestFile(const android::StringPiece& path) : source_(path) {}
 
-  std::unique_ptr<io::IData> OpenAsData() override { return {}; }
+  std::unique_ptr<io::IData> OpenAsData() override {
+    return {};
+  }
 
-  const Source& GetSource() const override { return source_; }
+  const Source& GetSource() const override {
+    return source_;
+  }
 
  private:
   DISALLOW_COPY_AND_ASSIGN(TestFile);
@@ -122,6 +110,47 @@ class TestFile : public io::IFile {
 };
 
 }  // namespace test
+
+// Workaround gtest bug (https://github.com/google/googletest/issues/443)
+// that does not select base class operator<< for derived class T.
+template <typename T>
+typename std::enable_if<std::is_base_of<Value, T>::value, std::ostream&>::type operator<<(
+    std::ostream& out, const T& value) {
+  value.Print(&out);
+  return out;
+}
+
+template std::ostream& operator<<<Item>(std::ostream&, const Item&);
+template std::ostream& operator<<<Reference>(std::ostream&, const Reference&);
+template std::ostream& operator<<<Id>(std::ostream&, const Id&);
+template std::ostream& operator<<<RawString>(std::ostream&, const RawString&);
+template std::ostream& operator<<<String>(std::ostream&, const String&);
+template std::ostream& operator<<<StyledString>(std::ostream&, const StyledString&);
+template std::ostream& operator<<<FileReference>(std::ostream&, const FileReference&);
+template std::ostream& operator<<<BinaryPrimitive>(std::ostream&, const BinaryPrimitive&);
+template std::ostream& operator<<<Attribute>(std::ostream&, const Attribute&);
+template std::ostream& operator<<<Style>(std::ostream&, const Style&);
+template std::ostream& operator<<<Array>(std::ostream&, const Array&);
+template std::ostream& operator<<<Plural>(std::ostream&, const Plural&);
+
+// Add a print method to Maybe.
+template <typename T>
+void PrintTo(const Maybe<T>& value, std::ostream* out) {
+  if (value) {
+    *out << ::testing::PrintToString(value.value());
+  } else {
+    *out << "Nothing";
+  }
+}
+
+namespace test {
+
+MATCHER_P(ValueEq, a,
+          std::string(negation ? "isn't" : "is") + " equal to " + ::testing::PrintToString(a)) {
+  return arg.Equals(&a);
+}
+
+}  // namespace test
 }  // namespace aapt
 
 #endif /* AAPT_TEST_COMMON_H */
index ec07432..a24c01c 100644 (file)
@@ -17,6 +17,7 @@
 #ifndef AAPT_TEST_TEST_H
 #define AAPT_TEST_TEST_H
 
+#include "gmock/gmock.h"
 #include "gtest/gtest.h"
 
 #include "test/Builders.h"
index d10351b..1bf2594 100644 (file)
@@ -181,12 +181,13 @@ Maybe<android::FileMap> MmapPath(const StringPiece& path,
   return std::move(filemap);
 }
 
-bool AppendArgsFromFile(const StringPiece& path,
-                        std::vector<std::string>* out_arglist,
+bool AppendArgsFromFile(const StringPiece& path, std::vector<std::string>* out_arglist,
                         std::string* out_error) {
   std::string contents;
-  if (!android::base::ReadFileToString(path.to_string(), &contents)) {
-    if (out_error) *out_error = "failed to read argument-list file";
+  if (!android::base::ReadFileToString(path.to_string(), &contents, true /*follow_symlinks*/)) {
+    if (out_error) {
+      *out_error = "failed to read argument-list file";
+    }
     return false;
   }
 
index 15fd2ce..deb0e09 100644 (file)
@@ -18,6 +18,7 @@ package android.view;
 
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
+import android.graphics.GraphicBuffer;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.os.Bundle;
@@ -210,13 +211,13 @@ public class IWindowManagerImpl implements IWindowManager {
     }
 
     @Override
-    public void overridePendingAppTransitionThumb(Bitmap srcThumb, int startX, int startY,
+    public void overridePendingAppTransitionThumb(GraphicBuffer srcThumb, int startX, int startY,
             IRemoteCallback startedCallback, boolean scaleUp) throws RemoteException {
         // TODO Auto-generated method stub
     }
 
     @Override
-    public void overridePendingAppTransitionAspectScaledThumb(Bitmap srcThumb, int startX,
+    public void overridePendingAppTransitionAspectScaledThumb(GraphicBuffer srcThumb, int startX,
             int startY, int targetWidth, int targetHeight, IRemoteCallback startedCallback,
             boolean scaleUp) {
         // TODO Auto-generated method stub
index b133a44..a4b3bf2 100644 (file)
@@ -1,7 +1,10 @@
 package android.net.wifi;
 
 import android.annotation.NonNull;
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
@@ -20,6 +23,7 @@ import com.android.internal.util.Protocol;
 
 /** @hide */
 @SystemApi
+@SystemService(Context.WIFI_RTT_SERVICE)
 public class RttManager {
 
     private static final boolean DBG = false;
@@ -167,6 +171,7 @@ public class RttManager {
 
     /** @deprecated Use the new {@link android.net.wifi.RttManager#getRttCapabilities()} API.*/
     @Deprecated
+    @SuppressLint("Doclava125")
     public Capabilities getCapabilities() {
         return new Capabilities();
     }
@@ -990,7 +995,7 @@ public class RttManager {
      * @exception throw IllegalArgumentException when params are illegal
      *            throw IllegalStateException when RttCapabilities do not exist
      */
-
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startRanging(RttParams[] params, RttListener listener) {
         int index  = 0;
         for(RttParams rttParam : params) {
@@ -1006,6 +1011,7 @@ public class RttManager {
                 0, putListener(listener), parcelableParams);
     }
 
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopRanging(RttListener listener) {
         validateChannel();
         mAsyncChannel.sendMessage(CMD_OP_STOP_RANGING, 0, removeListener(listener));
@@ -1039,6 +1045,7 @@ public class RttManager {
      * @param callback Callback for responder enabling/disabling result.
      * @throws IllegalArgumentException If {@code callback} is null.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void enableResponder(ResponderCallback callback) {
         if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null");
@@ -1058,6 +1065,7 @@ public class RttManager {
      * @param callback The same callback used for enabling responder.
      * @throws IllegalArgumentException If {@code callback} is null.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void disableResponder(ResponderCallback callback) {
         if (callback == null) {
             throw new IllegalArgumentException("callback cannot be null");
index f7333e2..91fc2f7 100644 (file)
@@ -67,6 +67,8 @@ public class WifiConfiguration implements Parcelable {
     public static final String updateIdentiferVarName = "update_identifier";
     /** {@hide} */
     public static final int INVALID_NETWORK_ID = -1;
+    /** {@hide} */
+    public static final int LOCAL_ONLY_NETWORK_ID = -2;
 
     /** {@hide} */
     private String mPasspointManagementObjectTree;
index cfc1fd2..c89a9a4 100644 (file)
 package android.net.wifi;
 
 import android.annotation.Nullable;
+import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
+import android.annotation.SuppressLint;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.content.pm.ParceledListSlice;
 import android.net.ConnectivityManager;
@@ -56,27 +59,30 @@ import java.util.concurrent.CountDownLatch;
 
 /**
  * This class provides the primary API for managing all aspects of Wi-Fi
- * connectivity. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context.WIFI_SERVICE)}.
- * On releases before NYC, it should only be obtained from an application context, and not from
- * any other derived context to avoid memory leaks within the calling process.
-
+ * connectivity.
+ * <p>
+ * On releases before {@link android.os.Build.VERSION_CODES#N}, this object
+ * should only be obtained from an {@linkplain Context#getApplicationContext()
+ * application context}, and not from any other derived context to avoid memory
+ * leaks within the calling process.
+ * <p>
  * It deals with several categories of items:
  * <ul>
- * <li>The list of configured networks. The list can be viewed and updated,
- * and attributes of individual entries can be modified.</li>
+ * <li>The list of configured networks. The list can be viewed and updated, and
+ * attributes of individual entries can be modified.</li>
  * <li>The currently active Wi-Fi network, if any. Connectivity can be
- * established or torn down, and dynamic information about the state of
- * the network can be queried.</li>
- * <li>Results of access point scans, containing enough information to
- * make decisions about what access point to connect to.</li>
- * <li>It defines the names of various Intent actions that are broadcast
- * upon any sort of change in Wi-Fi state.
+ * established or torn down, and dynamic information about the state of the
+ * network can be queried.</li>
+ * <li>Results of access point scans, containing enough information to make
+ * decisions about what access point to connect to.</li>
+ * <li>It defines the names of various Intent actions that are broadcast upon
+ * any sort of change in Wi-Fi state.
  * </ul>
- * This is the API to use when performing Wi-Fi specific operations. To
- * perform operations that pertain to network connectivity at an abstract
- * level, use {@link android.net.ConnectivityManager}.
+ * This is the API to use when performing Wi-Fi specific operations. To perform
+ * operations that pertain to network connectivity at an abstract level, use
+ * {@link android.net.ConnectivityManager}.
  */
+@SystemService(Context.WIFI_SERVICE)
 public class WifiManager {
 
     private static final String TAG = "WifiManager";
@@ -160,6 +166,8 @@ public class WifiManager {
      *
      * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
      * components will be launched.
+     *
+     * @hide
      */
     public static final String ACTION_PASSPOINT_ICON = "android.net.wifi.action.PASSPOINT_ICON";
     /**
@@ -167,6 +175,8 @@ public class WifiManager {
      * String representation.
      *
      * Retrieve with {@link android.content.Intent#getLongExtra(String, long)}.
+     *
+     * @hide
      */
     public static final String EXTRA_BSSID_LONG = "android.net.wifi.extra.BSSID_LONG";
     /**
@@ -174,12 +184,16 @@ public class WifiManager {
      *
      * Retrieve with {@link android.content.Intent#getParcelableExtra(String)} and cast into
      * {@link android.graphics.drawable.Icon}.
+     *
+     * @hide
      */
     public static final String EXTRA_ICON = "android.net.wifi.extra.ICON";
     /**
      * Name of a file.
      *
      * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+     *
+     * @hide
      */
     public static final String EXTRA_FILENAME = "android.net.wifi.extra.FILENAME";
 
@@ -195,6 +209,7 @@ public class WifiManager {
      * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
      * components will be launched.
      *
+     * @hide
      */
     public static final String ACTION_PASSPOINT_OSU_PROVIDERS_LIST =
             "android.net.wifi.action.PASSPOINT_OSU_PROVIDERS_LIST";
@@ -202,6 +217,8 @@ public class WifiManager {
      * Raw binary data of an ANQP (Access Network Query Protocol) element.
      *
      * Retrieve with {@link android.content.Intent#getByteArrayExtra(String)}.
+     *
+     * @hide
      */
     public static final String EXTRA_ANQP_ELEMENT_DATA =
             "android.net.wifi.extra.ANQP_ELEMENT_DATA";
@@ -220,6 +237,7 @@ public class WifiManager {
      * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
      * components will be launched.
      *
+     * @hide
      */
     public static final String ACTION_PASSPOINT_DEAUTH_IMMINENT =
             "android.net.wifi.action.PASSPOINT_DEAUTH_IMMINENT";
@@ -228,18 +246,24 @@ public class WifiManager {
      * {@code true} for ESS.
      *
      * Retrieve with {@link android.content.Intent#getBooleanExtra(String, boolean)}.
+     *
+     * @hide
      */
     public static final String EXTRA_ESS = "android.net.wifi.extra.ESS";
     /**
      * Delay in seconds.
      *
      * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
+     *
+     * @hide
      */
     public static final String EXTRA_DELAY = "android.net.wifi.extra.DELAY";
     /**
      * String representation of an URL.
      *
      * Retrieve with {@link android.content.Intent#getStringExtra(String)}.
+     *
+     * @hide
      */
     public static final String EXTRA_URL = "android.net.wifi.extra.URL";
 
@@ -254,8 +278,10 @@ public class WifiManager {
      *
      * Receiver Required Permission: android.Manifest.permission.ACCESS_WIFI_STATE
      *
-     ** <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
+     * <p>Note: The broadcast is only delivered to registered receivers - no manifest registered
      * components will be launched.
+     *
+     * @hide
      */
     public static final String ACTION_PASSPOINT_SUBSCRIPTION_REMEDIATION =
             "android.net.wifi.action.PASSPOINT_SUBSCRIPTION_REMEDIATION";
@@ -265,6 +291,8 @@ public class WifiManager {
      * 1 - SOAP XML SPP
      *
      * Retrieve with {@link android.content.Intent#getIntExtra(String, int)}.
+     *
+     * @hide
      */
     public static final String EXTRA_SUBSCRIPTION_REMEDIATION_METHOD =
             "android.net.wifi.extra.SUBSCRIPTION_REMEDIATION_METHOD";
@@ -944,6 +972,7 @@ public class WifiManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL)
     public List<WifiConfiguration> getPrivilegedConfiguredNetworks() {
         try {
             ParceledListSlice<WifiConfiguration> parceledList =
@@ -959,6 +988,7 @@ public class WifiManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_WIFI_CREDENTIAL)
     public WifiConnectionStatistics getConnectionStatistics() {
         try {
             return mService.getConnectionStatistics();
@@ -1058,11 +1088,9 @@ public class WifiManager {
      * Name).  In the case when there is an existing configuration with the same
      * FQDN, the new configuration will replace the existing configuration.
      *
-     * An {@link IllegalArgumentException} will be thrown on failure.
-     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
-     * on the device.
-     *
      * @param config The Passpoint configuration to be added
+     * @throws IllegalArgumentException if configuration is invalid
+     * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      */
     public void addOrUpdatePasspointConfiguration(PasspointConfiguration config) {
         try {
@@ -1077,11 +1105,9 @@ public class WifiManager {
     /**
      * Remove the Passpoint configuration identified by its FQDN (Fully Qualified Domain Name).
      *
-     * An {@link IllegalArgumentException} will be thrown on failure.
-     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
-     * on the device.
-     *
      * @param fqdn The FQDN of the Passpoint configuration to be removed
+     * @throws IllegalArgumentException if no configuration is associated with the given FQDN.
+     * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      */
     public void removePasspointConfiguration(String fqdn) {
         try {
@@ -1098,10 +1124,8 @@ public class WifiManager {
      *
      * An empty list will be returned when no configurations are installed.
      *
-     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
-     * on the device.
-     *
      * @return A list of {@link PasspointConfiguration}
+     * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
      */
     public List<PasspointConfiguration> getPasspointConfigurations() {
         try {
@@ -1117,11 +1141,11 @@ public class WifiManager {
      * {@link #EXTRA_ICON} will indicate the result of the request.
      * A missing intent extra {@link #EXTRA_ICON} will indicate a failure.
      *
-     * An {@link UnsupportedOperationException} will be thrown if Passpoint is not enabled
-     * on the device.
-     *
      * @param bssid The BSSID of the AP
      * @param fileName Name of the icon file (remote file) to query from the AP
+     *
+     * @throws UnsupportedOperationException if Passpoint is not enabled on the device.
+     * @hide
      */
     public void queryPasspointIcon(long bssid, String fileName) {
         try {
@@ -1506,6 +1530,7 @@ public class WifiManager {
 
     /** @hide */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
     public boolean startScan(WorkSource workSource) {
         try {
             String packageName = mContext.getOpPackageName();
@@ -1526,6 +1551,7 @@ public class WifiManager {
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean startLocationRestrictedScan(WorkSource workSource) {
         return false;
     }
@@ -1540,6 +1566,7 @@ public class WifiManager {
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public boolean isBatchedScanSupported() {
         return false;
     }
@@ -1553,6 +1580,7 @@ public class WifiManager {
      */
     @Deprecated
     @SystemApi
+    @SuppressLint("Doclava125")
     public List<BatchedScanResult> getBatchedScanResults() {
         return null;
     }
@@ -1778,25 +1806,26 @@ public class WifiManager {
     }
 
     /**
-     * Start AccessPoint mode with the specified
-     * configuration. If the radio is already running in
-     * AP mode, update the new configuration
-     * Note that starting in access point mode disables station
-     * mode operation
+     * This call will be deprecated and removed in an upcoming release.  It is no longer used to
+     * start WiFi Tethering.  Please use {@link ConnectivityManager#startTethering(int, boolean,
+     * ConnectivityManager#OnStartTetheringCallback)} if
+     * the caller has proper permissions.  Callers can also use the LocalOnlyHotspot feature for a
+     * hotspot capable of communicating with co-located devices {@link
+     * WifiManager#startLocalOnlyHotspot(LocalOnlyHotspotCallback)}.
+     *
      * @param wifiConfig SSID, security and channel details as
      *        part of WifiConfiguration
-     * @return {@code true} if the operation succeeds, {@code false} otherwise
+     * @return {@code false}
      *
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
     public boolean setWifiApEnabled(WifiConfiguration wifiConfig, boolean enabled) {
-        try {
-            mService.setWifiApEnabled(wifiConfig, enabled);
-            return true;
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        }
+        String packageName = mContext.getOpPackageName();
+
+        Log.w(TAG, packageName + " attempted call to setWifiApEnabled: enabled = " + enabled);
+        return false;
     }
 
     /**
@@ -2037,6 +2066,7 @@ public class WifiManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
     public int getWifiApState() {
         try {
             return mService.getWifiApEnabledState();
@@ -2053,6 +2083,7 @@ public class WifiManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
     public boolean isWifiApEnabled() {
         return getWifiApState() == WIFI_AP_STATE_ENABLED;
     }
@@ -2064,6 +2095,7 @@ public class WifiManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)
     public WifiConfiguration getWifiApConfiguration() {
         try {
             return mService.getWifiApConfiguration();
@@ -2079,6 +2111,7 @@ public class WifiManager {
      * @hide
      */
     @SystemApi
+    @RequiresPermission(android.Manifest.permission.CHANGE_WIFI_STATE)
     public boolean setWifiApConfiguration(WifiConfiguration wifiConfig) {
         try {
             mService.setWifiApConfiguration(wifiConfig);
index c02ceef..f47d5ca 100644 (file)
 
 package android.net.wifi;
 
+import android.annotation.RequiresPermission;
+import android.annotation.SuppressLint;
 import android.annotation.SystemApi;
+import android.annotation.SystemService;
 import android.content.Context;
 import android.os.Bundle;
 import android.os.Handler;
@@ -40,12 +43,10 @@ import java.util.List;
 
 /**
  * This class provides a way to scan the Wifi universe around the device
- * Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String) Context.getSystemService(Context
- * .WIFI_SCANNING_SERVICE)}.
  * @hide
  */
 @SystemApi
+@SystemService(Context.WIFI_SCANNING_SERVICE)
 public class WifiScanner {
 
     /** no band specified; use channel list instead */
@@ -732,6 +733,7 @@ public class WifiScanner {
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startBackgroundScan(ScanSettings settings, ScanListener listener) {
         startBackgroundScan(settings, listener, null);
     }
@@ -744,6 +746,7 @@ public class WifiScanner {
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startBackgroundScan(ScanSettings settings, ScanListener listener,
             WorkSource workSource) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
@@ -761,6 +764,7 @@ public class WifiScanner {
      * @param listener specifies which scan to cancel; must be same object as passed in {@link
      *  #startBackgroundScan}
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopBackgroundScan(ScanListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         int key = removeListener(listener);
@@ -772,6 +776,7 @@ public class WifiScanner {
      * reports currently available scan results on appropriate listeners
      * @return true if all scan results were reported correctly
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public boolean getScanResults() {
         validateChannel();
         Message reply = mAsyncChannel.sendMessageSynchronously(CMD_GET_SCAN_RESULTS, 0);
@@ -786,6 +791,7 @@ public class WifiScanner {
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startScan(ScanSettings settings, ScanListener listener) {
         startScan(settings, listener, null);
     }
@@ -799,6 +805,7 @@ public class WifiScanner {
      *                 key for this scan, and must also be specified to cancel the scan. Multiple
      *                 scans should also not share this object.
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void startScan(ScanSettings settings, ScanListener listener, WorkSource workSource) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         int key = addListener(listener);
@@ -815,6 +822,7 @@ public class WifiScanner {
      * hasn't been called on the listener, ignored otherwise
      * @param listener
      */
+    @RequiresPermission(android.Manifest.permission.LOCATION_HARDWARE)
     public void stopScan(ScanListener listener) {
         Preconditions.checkNotNull(listener, "listener cannot be null");
         int key = removeListener(listener);
@@ -962,6 +970,7 @@ public class WifiScanner {
      * @param bssidInfos access points to watch
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void configureWifiChange(
             int rssiSampleSize,                             /* sample size for RSSI averaging */
             int lostApSampleSize,                           /* samples to confirm AP's loss */
@@ -995,6 +1004,7 @@ public class WifiScanner {
      *                 provided on {@link #stopTrackingWifiChange}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void startTrackingWifiChange(WifiChangeListener listener) {
         throw new UnsupportedOperationException();
     }
@@ -1005,6 +1015,7 @@ public class WifiScanner {
      * #stopTrackingWifiChange}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void stopTrackingWifiChange(WifiChangeListener listener) {
         throw new UnsupportedOperationException();
     }
@@ -1012,6 +1023,7 @@ public class WifiScanner {
     /** @hide */
     @SystemApi
     @Deprecated
+    @SuppressLint("Doclava125")
     public void configureWifiChange(WifiChangeSettings settings) {
         throw new UnsupportedOperationException();
     }
@@ -1067,6 +1079,7 @@ public class WifiScanner {
      *                 also be provided on {@link #stopTrackingBssids}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void startTrackingBssids(BssidInfo[] bssidInfos,
                                     int apLostThreshold, BssidListener listener) {
         throw new UnsupportedOperationException();
@@ -1077,6 +1090,7 @@ public class WifiScanner {
      * @param listener same object provided in {@link #startTrackingBssids}
      */
     @Deprecated
+    @SuppressLint("Doclava125")
     public void stopTrackingBssids(BssidListener listener) {
         throw new UnsupportedOperationException();
     }
index d3ed792..c22daaf 100644 (file)
@@ -20,6 +20,7 @@ import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.net.ConnectivityManager;
@@ -48,9 +49,7 @@ import java.util.List;
 
 /**
  * This class provides the primary API for managing Wi-Fi Aware operations:
- * discovery and peer-to-peer data connections. Get an instance of this class by calling
- * {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.WIFI_AWARE_SERVICE)}.
+ * discovery and peer-to-peer data connections.
  * <p>
  * The class provides access to:
  * <ul>
@@ -120,6 +119,7 @@ import java.util.List;
  *        {@link DiscoverySession#createNetworkSpecifierPassphrase(PeerHandle, String)}.
  *    </ul>
  */
+@SystemService(Context.WIFI_AWARE_SERVICE)
 public class WifiAwareManager {
     private static final String TAG = "WifiAwareManager";
     private static final boolean DBG = false;
index f892bb0..71d4173 100644 (file)
@@ -62,16 +62,36 @@ public final class PasspointConfiguration implements Parcelable {
      * Configurations under HomeSp subtree.
      */
     private HomeSp mHomeSp = null;
+    /**
+     * Set the Home SP (Service Provider) information.
+     *
+     * @param homeSp The Home SP information to set to
+     */
     public void setHomeSp(HomeSp homeSp) { mHomeSp = homeSp; }
+    /**
+     * Get the Home SP (Service Provider) information.
+     *
+     * @return Home SP information
+     */
     public HomeSp getHomeSp() { return mHomeSp; }
 
     /**
      * Configurations under Credential subtree.
      */
     private Credential mCredential = null;
+    /**
+     * Set the credential information.
+     *
+     * @param credential The credential information to set to
+     */
     public void setCredential(Credential credential) {
         mCredential = credential;
     }
+    /**
+     * Get the credential information.
+     *
+     * @return credential information
+     */
     public Credential getCredential() {
         return mCredential;
     }
index d712feb..e8fcbfd 100644 (file)
@@ -97,9 +97,19 @@ public final class Credential implements Parcelable {
      * comparing the realm specified in that hotspot's ANQP element.
      */
     private String mRealm = null;
+    /**
+     * Set the realm associated with this credential.
+     *
+     * @param realm The realm to set to
+     */
     public void setRealm(String realm) {
         mRealm = realm;
     }
+    /**
+     * Get the realm associated with this credential.
+     *
+     * @return the realm associated with this credential
+     */
     public String getRealm() {
         return mRealm;
     }
@@ -162,9 +172,19 @@ public final class Credential implements Parcelable {
          * Username of the credential.
          */
         private String mUsername = null;
+        /**
+         * Set the username associated with this user credential.
+         *
+         * @param username The username to set to
+         */
         public void setUsername(String username) {
             mUsername = username;
         }
+        /**
+         * Get the username associated with this user credential.
+         *
+         * @return the username associated with this user credential
+         */
         public String getUsername() {
             return mUsername;
         }
@@ -173,9 +193,19 @@ public final class Credential implements Parcelable {
          * Base64-encoded password.
          */
         private String mPassword = null;
+        /**
+         * Set the Base64-encoded password associated with this user credential.
+         *
+         * @param password The password to set to
+         */
         public void setPassword(String password) {
             mPassword = password;
         }
+        /**
+         * Get the Base64-encoded password associated with this user credential.
+         *
+         * @return the Base64-encoded password associated with this user credential
+         */
         public String getPassword() {
             return mPassword;
         }
@@ -233,14 +263,30 @@ public final class Credential implements Parcelable {
 
         /**
          * EAP (Extensible Authentication Protocol) method type.
-         * Refer to http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4
-         * for valid values.
+         * Refer to
+         * <a href="http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4">
+         * EAP Numbers</a> for valid values.
          * Using Integer.MIN_VALUE to indicate unset value.
          */
         private int mEapType = Integer.MIN_VALUE;
+        /**
+         * Set the EAP (Extensible Authentication Protocol) method type associated with this
+         * user credential.
+         * Refer to
+         * <a href="http://www.iana.org/assignments/eap-numbers/eap-numbers.xml#eap-numbers-4">
+         * EAP Numbers</a> for valid values.
+         *
+         * @param eapType The EAP method type associated with this user credential
+         */
         public void setEapType(int eapType) {
             mEapType = eapType;
         }
+        /**
+         * Get the EAP (Extensible Authentication Protocol) method type associated with this
+         * user credential.
+         *
+         * @return EAP method type
+         */
         public int getEapType() {
             return mEapType;
         }
@@ -249,9 +295,19 @@ public final class Credential implements Parcelable {
          * Non-EAP inner authentication method.
          */
         private String mNonEapInnerMethod = null;
+        /**
+         * Set the inner non-EAP method associated with this user credential.
+         *
+         * @param nonEapInnerMethod The non-EAP inner method to set to
+         */
         public void setNonEapInnerMethod(String nonEapInnerMethod) {
             mNonEapInnerMethod = nonEapInnerMethod;
         }
+        /**
+         * Get the inner non-EAP method associated with this user credential.
+         *
+         * @return Non-EAP inner method associated with this user credential
+         */
         public String getNonEapInnerMethod() {
             return mNonEapInnerMethod;
         }
@@ -394,9 +450,19 @@ public final class Credential implements Parcelable {
             };
     }
     private UserCredential mUserCredential = null;
+    /**
+     * Set the user credential information.
+     *
+     * @param userCredential The user credential to set to
+     */
     public void setUserCredential(UserCredential userCredential) {
         mUserCredential = userCredential;
     }
+    /**
+     * Get the user credential information.
+     *
+     * @return user credential information
+     */
     public UserCredential getUserCredential() {
         return mUserCredential;
     }
@@ -421,9 +487,19 @@ public final class Credential implements Parcelable {
          * Certificate type.
          */
         private String mCertType = null;
+        /**
+         * Set the certificate type associated with this certificate credential.
+         *
+         * @param certType The certificate type to set to
+         */
         public void setCertType(String certType) {
             mCertType = certType;
         }
+        /**
+         * Get the certificate type associated with this certificate credential.
+         *
+         * @return certificate type
+         */
         public String getCertType() {
             return mCertType;
         }
@@ -432,9 +508,19 @@ public final class Credential implements Parcelable {
          * The SHA-256 fingerprint of the certificate.
          */
         private byte[] mCertSha256Fingerprint = null;
+        /**
+         * Set the certificate SHA-256 fingerprint associated with this certificate credential.
+         *
+         * @param certSha256Fingerprint The certificate fingerprint to set to
+         */
         public void setCertSha256Fingerprint(byte[] certSha256Fingerprint) {
             mCertSha256Fingerprint = certSha256Fingerprint;
         }
+        /**
+         * Get the certificate SHA-256 fingerprint associated with this certificate credential.
+         *
+         * @return certificate SHA-256 fingerprint
+         */
         public byte[] getCertSha256Fingerprint() {
             return mCertSha256Fingerprint;
         }
@@ -530,9 +616,19 @@ public final class Credential implements Parcelable {
             };
     }
     private CertificateCredential mCertCredential = null;
+    /**
+     * Set the certificate credential information.
+     *
+     * @param certCredential The certificate credential to set to
+     */
     public void setCertCredential(CertificateCredential certCredential) {
         mCertCredential = certCredential;
     }
+    /**
+     * Get the certificate credential information.
+     *
+     * @return certificate credential information
+     */
     public CertificateCredential getCertCredential() {
         return mCertCredential;
     }
@@ -553,9 +649,21 @@ public final class Credential implements Parcelable {
          * cellular networks
          */
         private String mImsi = null;
+        /**
+         * Set the IMSI (International Mobile Subscriber Identity) associated with this SIM
+         * credential.
+         *
+         * @param imsi The IMSI to set to
+         */
         public void setImsi(String imsi) {
             mImsi = imsi;
         }
+        /**
+         * Get the IMSI (International Mobile Subscriber Identity) associated with this SIM
+         * credential.
+         *
+         * @return IMSI associated with this SIM credential
+         */
         public String getImsi() {
             return mImsi;
         }
@@ -567,9 +675,21 @@ public final class Credential implements Parcelable {
          * Using Integer.MIN_VALUE to indicate unset value.
          */
         private int mEapType = Integer.MIN_VALUE;
+        /**
+         * Set the EAP (Extensible Authentication Protocol) method type associated with this
+         * SIM credential.
+         *
+         * @param eapType The EAP method type to set to
+         */
         public void setEapType(int eapType) {
             mEapType = eapType;
         }
+        /**
+         * Get the EAP (Extensible Authentication Protocol) method type associated with this
+         * SIM credential.
+         *
+         * @return EAP method type associated with this SIM credential
+         */
         public int getEapType() {
             return mEapType;
         }
@@ -704,9 +824,19 @@ public final class Credential implements Parcelable {
         }
     }
     private SimCredential mSimCredential = null;
+    /**
+     * Set the SIM credential information.
+     *
+     * @param simCredential The SIM credential to set to
+     */
     public void setSimCredential(SimCredential simCredential) {
         mSimCredential = simCredential;
     }
+    /**
+     * Get the SIM credential information.
+     *
+     * @return SIM credential information
+     */
     public SimCredential getSimCredential() {
         return mSimCredential;
     }
@@ -715,9 +845,19 @@ public final class Credential implements Parcelable {
      * CA (Certificate Authority) X509 certificate.
      */
     private X509Certificate mCaCertificate = null;
+    /**
+     * Set the CA (Certification Authority) certificate associated with this credential.
+     *
+     * @param caCertificate The CA certificate to set to
+     */
     public void setCaCertificate(X509Certificate caCertificate) {
         mCaCertificate = caCertificate;
     }
+    /**
+     * Get the CA (Certification Authority) certificate associated with this credential.
+     *
+     * @return CA certificate associated with this credential
+     */
     public X509Certificate getCaCertificate() {
         return mCaCertificate;
     }
@@ -726,9 +866,19 @@ public final class Credential implements Parcelable {
      * Client side X509 certificate chain.
      */
     private X509Certificate[] mClientCertificateChain = null;
+    /**
+     * Set the client certificate chain associated with this credential.
+     *
+     * @param certificateChain The client certificate chain to set to
+     */
     public void setClientCertificateChain(X509Certificate[] certificateChain) {
         mClientCertificateChain = certificateChain;
     }
+    /**
+     * Get the client certificate chain associated with this credential.
+     *
+     * @return client certificate chain associated with this credential
+     */
     public X509Certificate[] getClientCertificateChain() {
         return mClientCertificateChain;
     }
@@ -737,9 +887,19 @@ public final class Credential implements Parcelable {
      * Client side private key.
      */
     private PrivateKey mClientPrivateKey = null;
+    /**
+     * Set the client private key associated with this credential.
+     *
+     * @param clientPrivateKey the client private key to set to
+     */
     public void setClientPrivateKey(PrivateKey clientPrivateKey) {
         mClientPrivateKey = clientPrivateKey;
     }
+    /**
+     * Get the client private key associated with this credential.
+     *
+     * @return client private key associated with this credential.
+     */
     public PrivateKey getClientPrivateKey() {
         return mClientPrivateKey;
     }
index 2247860..d829ea8 100644 (file)
@@ -52,9 +52,19 @@ public final class HomeSp implements Parcelable {
      * FQDN (Fully Qualified Domain Name) of this home service provider.
      */
     private String mFqdn = null;
+    /**
+     * Set the FQDN (Fully Qualified Domain Name) associated with this home service provider.
+     *
+     * @param fqdn The FQDN to set to
+     */
     public void setFqdn(String fqdn) {
         mFqdn = fqdn;
     }
+    /**
+     * Get the FQDN (Fully Qualified Domain Name) associated with this home service provider.
+     *
+     * @return the FQDN associated with this home service provider
+     */
     public String getFqdn() {
         return mFqdn;
     }
@@ -63,9 +73,19 @@ public final class HomeSp implements Parcelable {
      * Friendly name of this home service provider.
      */
     private String mFriendlyName = null;
+    /**
+     * Set the friendly name associated with this home service provider.
+     *
+     * @param friendlyName The friendly name to set to
+     */
     public void setFriendlyName(String friendlyName) {
         mFriendlyName = friendlyName;
     }
+    /**
+     * Get the friendly name associated with this home service provider.
+     *
+     * @return the friendly name associated with this home service provider
+     */
     public String getFriendlyName() {
         return mFriendlyName;
     }
@@ -184,9 +204,21 @@ public final class HomeSp implements Parcelable {
      * which this provider is a member.
      */
     private long[] mRoamingConsortiumOis = null;
+    /**
+     * Set the Organization Identifiers (OIs) identifying a roaming consortium of which this
+     * provider is a member.
+     *
+     * @param roamingConsortiumOis Array of roaming consortium OIs
+     */
     public void setRoamingConsortiumOis(long[] roamingConsortiumOis) {
         mRoamingConsortiumOis = roamingConsortiumOis;
     }
+    /**
+     * Get the Organization Identifiers (OIs) identifying a roaming consortium of which this
+     * provider is a member.
+     *
+     * @return array of roaming consortium OIs
+     */
     public long[] getRoamingConsortiumOis() {
         return mRoamingConsortiumOis;
     }
index c93ac7b..95d0a79 100644 (file)
@@ -17,6 +17,7 @@
 package android.net.wifi.p2p;
 
 import android.annotation.SdkConstant;
+import android.annotation.SystemService;
 import android.annotation.SdkConstant.SdkConstantType;
 import android.content.Context;
 import android.net.wifi.WpsInfo;
@@ -119,9 +120,6 @@ import java.util.Map;
  * {@link android.Manifest.permission#CHANGE_WIFI_STATE} to perform any further peer-to-peer
  * operations.
  *
- * Get an instance of this class by calling {@link android.content.Context#getSystemService(String)
- * Context.getSystemService(Context.WIFI_P2P_SERVICE)}.
- *
  * {@see WifiP2pConfig}
  * {@see WifiP2pInfo}
  * {@see WifiP2pGroup}
@@ -129,6 +127,7 @@ import java.util.Map;
  * {@see WifiP2pDeviceList}
  * {@see android.net.wifi.WpsInfo}
  */
+@SystemService(Context.WIFI_P2P_SERVICE)
 public class WifiP2pManager {
     private static final String TAG = "WifiP2pManager";
     /**
index 84ac118..b235ccc 100644 (file)
@@ -778,4 +778,13 @@ public class WifiManagerTest {
         verify(mWifiService).stopWatchLocalOnlyHotspot();
     }
 
+    /**
+     * Verify that calls to setWifiApEnabled return false.
+     */
+    @Test
+    public void testSetWifiApEnabledReturnsFalse() throws Exception {
+        assertFalse(mWifiManager.setWifiApEnabled(null, true));
+        assertFalse(mWifiManager.setWifiApEnabled(null, false));
+        verify(mWifiService, never()).setWifiApEnabled(any(), anyBoolean());
+    }
 }