summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk2
-rw-r--r--api/current.txt49
-rw-r--r--api/system-current.txt50
-rw-r--r--api/test-current.txt49
-rw-r--r--core/java/android/animation/Animator.java7
-rw-r--r--core/java/android/animation/ObjectAnimator.java6
-rw-r--r--core/java/android/app/ApplicationPackageManager.java15
-rw-r--r--core/java/android/app/DownloadManager.java2
-rw-r--r--core/java/android/app/Fragment.java45
-rw-r--r--core/java/android/app/FragmentManager.java9
-rw-r--r--core/java/android/app/IWallpaperManager.aidl5
-rw-r--r--core/java/android/app/Notification.java44
-rw-r--r--core/java/android/app/SystemServiceRegistry.java4
-rw-r--r--core/java/android/app/WallpaperManager.java32
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java100
-rw-r--r--core/java/android/bluetooth/BluetoothGatt.java282
-rw-r--r--core/java/android/bluetooth/BluetoothGattCallbackWrapper.java44
-rw-r--r--core/java/android/bluetooth/BluetoothGattCharacteristic.aidl (renamed from packages/SystemUI/src/com/android/systemui/recents/events/activity/ClearHistoryEvent.java)11
-rw-r--r--core/java/android/bluetooth/BluetoothGattCharacteristic.java58
-rw-r--r--core/java/android/bluetooth/BluetoothGattDescriptor.aidl (renamed from packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java)13
-rw-r--r--core/java/android/bluetooth/BluetoothGattDescriptor.java42
-rw-r--r--core/java/android/bluetooth/BluetoothGattIncludedService.aidl (renamed from packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryButtonEvent.java)13
-rw-r--r--core/java/android/bluetooth/BluetoothGattIncludedService.java110
-rw-r--r--core/java/android/bluetooth/BluetoothGattService.aidl19
-rw-r--r--core/java/android/bluetooth/BluetoothGattService.java90
-rw-r--r--core/java/android/bluetooth/IBluetoothGatt.aidl25
-rw-r--r--core/java/android/bluetooth/IBluetoothGattCallback.aidl41
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl17
-rw-r--r--core/java/android/content/pm/UserInfo.java1
-rw-r--r--core/java/android/hardware/Sensor.java8
-rw-r--r--core/java/android/hardware/usb/UsbManager.java10
-rw-r--r--core/java/android/net/ConnectivityManager.java28
-rw-r--r--core/java/android/net/ConnectivityThread.java51
-rw-r--r--core/java/android/net/NetworkCapabilities.java12
-rw-r--r--core/java/android/net/NetworkUtils.java17
-rw-r--r--core/java/android/net/TrafficStats.java20
-rw-r--r--core/java/android/os/Debug.java219
-rw-r--r--core/java/android/os/INetworkManagementService.aidl6
-rw-r--r--core/java/android/os/IUserManager.aidl1
-rw-r--r--core/java/android/os/UserManager.java27
-rw-r--r--core/java/android/os/storage/StorageVolume.java11
-rw-r--r--core/java/android/os/storage/VolumeInfo.java4
-rw-r--r--core/java/android/provider/BlockedNumberContract.java7
-rw-r--r--core/java/android/provider/DocumentsContract.java18
-rwxr-xr-xcore/java/android/provider/Settings.java9
-rw-r--r--core/java/android/provider/UserDictionary.java3
-rw-r--r--core/java/android/security/net/config/XmlConfigSource.java4
-rw-r--r--core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java564
-rw-r--r--core/java/android/util/apk/ZipUtils.java127
-rw-r--r--core/java/android/view/IWindowSession.aidl11
-rw-r--r--core/java/android/view/SurfaceControl.java11
-rw-r--r--core/java/android/view/SurfaceView.java8
-rw-r--r--core/java/android/view/View.java16
-rw-r--r--core/java/android/view/ViewRootImpl.java14
-rw-r--r--core/java/android/view/inputmethod/BaseInputConnection.java4
-rw-r--r--core/java/android/view/inputmethod/InputMethodManager.java94
-rw-r--r--core/java/android/widget/FrameLayout.java10
-rw-r--r--core/java/android/widget/GridLayout.java10
-rw-r--r--core/java/android/widget/ImageView.java12
-rw-r--r--core/java/android/widget/LinearLayout.java10
-rw-r--r--core/java/android/widget/PopupWindow.java7
-rw-r--r--core/java/android/widget/RelativeLayout.java10
-rw-r--r--core/java/com/android/internal/app/AlertController.java5
-rw-r--r--core/java/com/android/internal/app/ResolverActivity.java5
-rw-r--r--core/java/com/android/internal/os/InstallerConnection.java32
-rw-r--r--core/java/com/android/internal/os/ZygoteInit.java8
-rw-r--r--core/java/com/android/internal/util/NotificationColorUtil.java422
-rw-r--r--core/java/com/android/internal/view/IInputConnectionWrapper.java59
-rw-r--r--core/java/com/android/internal/widget/EditableInputConnection.java5
-rw-r--r--core/java/com/android/internal/widget/FloatingToolbar.java16
-rw-r--r--core/jni/Android.mk4
-rwxr-xr-xcore/jni/android/graphics/Bitmap.cpp2
-rw-r--r--core/jni/android/graphics/Camera.cpp2
-rw-r--r--core/jni/android/graphics/CanvasProperty.cpp2
-rw-r--r--core/jni/android/graphics/FontFamily.cpp4
-rw-r--r--core/jni/android/graphics/Graphics.cpp2
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h4
-rw-r--r--core/jni/android/graphics/Movie.cpp4
-rw-r--r--core/jni/android/graphics/NinePatch.cpp4
-rw-r--r--core/jni/android/graphics/Paint.cpp46
-rw-r--r--core/jni/android/graphics/Picture.cpp2
-rw-r--r--core/jni/android/graphics/Rasterizer.cpp3
-rw-r--r--core/jni/android/graphics/Typeface.cpp35
-rw-r--r--core/jni/android/graphics/pdf/PdfDocument.cpp3
-rw-r--r--core/jni/android_graphics_Canvas.cpp173
-rw-r--r--core/jni/android_graphics_drawable_VectorDrawable.cpp3
-rw-r--r--core/jni/android_net_NetUtils.cpp17
-rw-r--r--core/jni/android_text_StaticLayout.cpp12
-rw-r--r--core/jni/android_view_DisplayListCanvas.cpp4
-rw-r--r--core/jni/android_view_HardwareLayer.cpp2
-rw-r--r--core/jni/android_view_RenderNode.cpp2
-rw-r--r--core/jni/android_view_SurfaceControl.cpp12
-rw-r--r--core/res/AndroidManifest.xml1
-rw-r--r--core/res/res/layout/notification_material_action_list.xml2
-rw-r--r--core/res/res/values-af/strings.xml3
-rw-r--r--core/res/res/values-am/strings.xml3
-rw-r--r--core/res/res/values-ar/strings.xml3
-rw-r--r--core/res/res/values-az-rAZ/strings.xml3
-rw-r--r--core/res/res/values-b+sr+Latn/strings.xml12
-rw-r--r--core/res/res/values-be-rBY/strings.xml12
-rw-r--r--core/res/res/values-bg/strings.xml3
-rw-r--r--core/res/res/values-bn-rBD/strings.xml12
-rw-r--r--core/res/res/values-bs-rBA/strings.xml12
-rw-r--r--core/res/res/values-ca/strings.xml3
-rw-r--r--core/res/res/values-cs/strings.xml2
-rw-r--r--core/res/res/values-da/strings.xml3
-rw-r--r--core/res/res/values-de/strings.xml12
-rw-r--r--core/res/res/values-el/strings.xml12
-rw-r--r--core/res/res/values-en-rAU/strings.xml2
-rw-r--r--core/res/res/values-en-rGB/strings.xml2
-rw-r--r--core/res/res/values-en-rIN/strings.xml2
-rw-r--r--core/res/res/values-es-rUS/strings.xml12
-rw-r--r--core/res/res/values-es/strings.xml11
-rw-r--r--core/res/res/values-et-rEE/strings.xml2
-rw-r--r--core/res/res/values-eu-rES/strings.xml5
-rw-r--r--core/res/res/values-fa/strings.xml12
-rw-r--r--core/res/res/values-fi/strings.xml12
-rw-r--r--core/res/res/values-fr-rCA/strings.xml12
-rw-r--r--core/res/res/values-fr/strings.xml12
-rw-r--r--core/res/res/values-gl-rES/strings.xml12
-rw-r--r--core/res/res/values-gu-rIN/strings.xml11
-rw-r--r--core/res/res/values-hi/strings.xml2
-rw-r--r--core/res/res/values-hr/strings.xml3
-rw-r--r--core/res/res/values-hu/strings.xml2
-rw-r--r--core/res/res/values-hy-rAM/strings.xml12
-rw-r--r--core/res/res/values-in/strings.xml3
-rw-r--r--core/res/res/values-is-rIS/strings.xml12
-rw-r--r--core/res/res/values-it/strings.xml3
-rw-r--r--core/res/res/values-iw/strings.xml12
-rw-r--r--core/res/res/values-ja/strings.xml3
-rw-r--r--core/res/res/values-ka-rGE/strings.xml12
-rw-r--r--core/res/res/values-kk-rKZ/strings.xml3
-rw-r--r--core/res/res/values-km-rKH/strings.xml3
-rw-r--r--core/res/res/values-kn-rIN/strings.xml3
-rw-r--r--core/res/res/values-ko/strings.xml12
-rw-r--r--core/res/res/values-ky-rKG/strings.xml12
-rw-r--r--core/res/res/values-lo-rLA/strings.xml3
-rw-r--r--core/res/res/values-lt/strings.xml3
-rw-r--r--core/res/res/values-lv/strings.xml11
-rw-r--r--core/res/res/values-mk-rMK/strings.xml12
-rw-r--r--core/res/res/values-ml-rIN/strings.xml12
-rw-r--r--core/res/res/values-mn-rMN/strings.xml3
-rw-r--r--core/res/res/values-mr-rIN/strings.xml3
-rw-r--r--core/res/res/values-ms-rMY/strings.xml12
-rw-r--r--core/res/res/values-my-rMM/strings.xml2
-rw-r--r--core/res/res/values-nb/strings.xml11
-rw-r--r--core/res/res/values-ne-rNP/strings.xml3
-rw-r--r--core/res/res/values-nl/strings.xml2
-rw-r--r--core/res/res/values-pa-rIN/strings.xml3
-rw-r--r--core/res/res/values-pl/strings.xml12
-rw-r--r--core/res/res/values-pt-rBR/strings.xml12
-rw-r--r--core/res/res/values-pt-rPT/strings.xml12
-rw-r--r--core/res/res/values-pt/strings.xml12
-rw-r--r--core/res/res/values-ro/strings.xml12
-rw-r--r--core/res/res/values-ru/strings.xml3
-rw-r--r--core/res/res/values-si-rLK/strings.xml3
-rw-r--r--core/res/res/values-sk/strings.xml12
-rw-r--r--core/res/res/values-sl/strings.xml12
-rw-r--r--core/res/res/values-sq-rAL/strings.xml12
-rw-r--r--core/res/res/values-sr/strings.xml12
-rw-r--r--core/res/res/values-sv/strings.xml12
-rw-r--r--core/res/res/values-sw/strings.xml12
-rw-r--r--core/res/res/values-ta-rIN/strings.xml3
-rw-r--r--core/res/res/values-te-rIN/strings.xml11
-rw-r--r--core/res/res/values-th/strings.xml3
-rw-r--r--core/res/res/values-tl/strings.xml3
-rw-r--r--core/res/res/values-tr/strings.xml12
-rw-r--r--core/res/res/values-uk/strings.xml2
-rw-r--r--core/res/res/values-ur-rPK/strings.xml12
-rw-r--r--core/res/res/values-uz-rUZ/strings.xml12
-rw-r--r--core/res/res/values-vi/strings.xml3
-rw-r--r--core/res/res/values-zh-rCN/strings.xml3
-rw-r--r--core/res/res/values-zh-rHK/strings.xml2
-rw-r--r--core/res/res/values-zh-rTW/strings.xml12
-rw-r--r--core/res/res/values-zu/strings.xml12
-rw-r--r--core/res/res/values/colors.xml4
-rw-r--r--core/res/res/values/strings.xml4
-rw-r--r--core/res/res/values/symbols.xml3
-rw-r--r--core/tests/coretests/src/android/text/StaticLayoutTest.java93
-rw-r--r--core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java2
-rw-r--r--graphics/java/android/graphics/NinePatch.java27
-rw-r--r--graphics/java/android/graphics/Rect.java12
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java72
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java15
-rw-r--r--keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java10
-rw-r--r--libs/hwui/Android.mk10
-rw-r--r--libs/hwui/Canvas.cpp66
-rw-r--r--libs/hwui/CanvasState.cpp2
-rw-r--r--libs/hwui/DeferredLayerUpdater.h7
-rw-r--r--libs/hwui/DisplayListCanvas.cpp4
-rw-r--r--libs/hwui/DisplayListCanvas.h6
-rw-r--r--libs/hwui/FrameBuilder.cpp46
-rw-r--r--libs/hwui/FrameBuilder.h15
-rw-r--r--libs/hwui/Layer.h4
-rw-r--r--libs/hwui/LayerRenderer.cpp2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp2
-rw-r--r--libs/hwui/RecordingCanvas.cpp16
-rw-r--r--libs/hwui/RecordingCanvas.h6
-rw-r--r--libs/hwui/RenderProperties.cpp2
-rw-r--r--libs/hwui/SkiaCanvas.cpp10
-rw-r--r--libs/hwui/SkiaCanvasProxy.cpp6
-rw-r--r--libs/hwui/SkiaCanvasProxy.h2
-rw-r--r--libs/hwui/Snapshot.cpp2
-rw-r--r--libs/hwui/VectorDrawable.h2
-rw-r--r--libs/hwui/hwui/Canvas.cpp220
-rw-r--r--libs/hwui/hwui/Canvas.h (renamed from libs/hwui/Canvas.h)17
-rw-r--r--libs/hwui/hwui/MinikinSkia.cpp (renamed from core/jni/android/graphics/MinikinSkia.cpp)8
-rw-r--r--libs/hwui/hwui/MinikinSkia.h (renamed from core/jni/android/graphics/MinikinSkia.h)6
-rw-r--r--libs/hwui/hwui/MinikinUtils.cpp (renamed from core/jni/android/graphics/MinikinUtils.cpp)24
-rw-r--r--libs/hwui/hwui/MinikinUtils.h (renamed from core/jni/android/graphics/MinikinUtils.h)21
-rw-r--r--libs/hwui/hwui/Paint.h (renamed from core/jni/android/graphics/Paint.h)6
-rw-r--r--libs/hwui/hwui/PaintImpl.cpp (renamed from core/jni/android/graphics/PaintImpl.cpp)4
-rw-r--r--libs/hwui/hwui/Typeface.cpp (renamed from core/jni/android/graphics/TypefaceImpl.cpp)60
-rw-r--r--libs/hwui/hwui/Typeface.h (renamed from core/jni/android/graphics/TypefaceImpl.h)30
-rw-r--r--libs/hwui/hwui_static_deps.mk7
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp6
-rw-r--r--libs/hwui/tests/common/TestUtils.cpp16
-rw-r--r--libs/hwui/tests/common/TestUtils.h6
-rw-r--r--libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp64
-rw-r--r--libs/hwui/tests/common/scenes/ListViewAnimation.cpp4
-rw-r--r--libs/hwui/tests/common/scenes/TextAnimation.cpp4
-rw-r--r--libs/hwui/tests/microbench/FrameBuilderBench.cpp8
-rw-r--r--libs/hwui/tests/unit/CanvasStateTests.cpp2
-rw-r--r--libs/hwui/tests/unit/FrameBuilderTests.cpp136
-rw-r--r--libs/hwui/tests/unit/LeakCheckTests.cpp2
-rw-r--r--libs/hwui/tests/unit/RecordingCanvasTests.cpp69
-rw-r--r--location/java/android/location/GnssClock.java5
-rw-r--r--media/java/android/media/ExifInterface.java196
-rw-r--r--media/java/android/media/IMediaResourceMonitor.aidl2
-rw-r--r--media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java8
-rw-r--r--packages/DocumentsUI/Android.mk6
-rw-r--r--packages/DocumentsUI/AndroidManifest.xml8
-rw-r--r--packages/DocumentsUI/res/color/item_details.xml6
-rw-r--r--packages/DocumentsUI/res/color/item_title.xml5
-rw-r--r--packages/DocumentsUI/res/drawable/ic_files_app.xml5
-rw-r--r--packages/DocumentsUI/res/drawable/icon256.pngbin14014 -> 0 bytes
-rw-r--r--packages/DocumentsUI/res/layout/item_dir_grid.xml8
-rw-r--r--packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.pngbin0 -> 4473 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.pngbin0 -> 2818 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.pngbin0 -> 6351 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.pngbin0 -> 10361 bytes
-rw-r--r--packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.pngbin0 -> 14962 bytes
-rw-r--r--packages/DocumentsUI/res/values-b+sr+Latn/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-bg/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-bn-rBD/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-ca/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-de/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-es-rUS/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-es/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-et-rEE/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-eu-rES/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-fi/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-fr-rCA/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-gl-rES/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-hr/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-is-rIS/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-it/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-ja/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-lt/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-lv/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-mk-rMK/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-ms-rMY/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-nb/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-pl/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-pt-rBR/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-pt/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-ro/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-ru/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-sq-rAL/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-sr/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-ta-rIN/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-tr/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-uk/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-ur-rPK/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values-zh-rCN/strings.xml6
-rw-r--r--packages/DocumentsUI/res/values/config.xml3
-rw-r--r--packages/DocumentsUI/res/values/strings.xml3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java11
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java10
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java8
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/Metrics.java12
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java93
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java11
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java6
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/Shared.java16
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java37
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java4
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java11
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java1
-rw-r--r--packages/Keyguard/res/values-af/strings.xml2
-rw-r--r--packages/Keyguard/res/values-am/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ar/strings.xml2
-rw-r--r--packages/Keyguard/res/values-az-rAZ/strings.xml2
-rw-r--r--packages/Keyguard/res/values-b+sr+Latn/strings.xml2
-rw-r--r--packages/Keyguard/res/values-be-rBY/strings.xml2
-rw-r--r--packages/Keyguard/res/values-bg/strings.xml2
-rw-r--r--packages/Keyguard/res/values-bn-rBD/strings.xml2
-rw-r--r--packages/Keyguard/res/values-bs-rBA/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ca/strings.xml2
-rw-r--r--packages/Keyguard/res/values-cs/strings.xml2
-rw-r--r--packages/Keyguard/res/values-da/strings.xml2
-rw-r--r--packages/Keyguard/res/values-de/strings.xml2
-rw-r--r--packages/Keyguard/res/values-el/strings.xml2
-rw-r--r--packages/Keyguard/res/values-en-rAU/strings.xml2
-rw-r--r--packages/Keyguard/res/values-en-rGB/strings.xml2
-rw-r--r--packages/Keyguard/res/values-en-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-es-rUS/strings.xml2
-rw-r--r--packages/Keyguard/res/values-es/strings.xml2
-rw-r--r--packages/Keyguard/res/values-et-rEE/strings.xml2
-rw-r--r--packages/Keyguard/res/values-eu-rES/strings.xml2
-rw-r--r--packages/Keyguard/res/values-fa/strings.xml2
-rw-r--r--packages/Keyguard/res/values-fi/strings.xml2
-rw-r--r--packages/Keyguard/res/values-fr-rCA/strings.xml2
-rw-r--r--packages/Keyguard/res/values-fr/strings.xml2
-rw-r--r--packages/Keyguard/res/values-gl-rES/strings.xml2
-rw-r--r--packages/Keyguard/res/values-gu-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-hi/strings.xml2
-rw-r--r--packages/Keyguard/res/values-hr/strings.xml2
-rw-r--r--packages/Keyguard/res/values-hu/strings.xml2
-rw-r--r--packages/Keyguard/res/values-hy-rAM/strings.xml2
-rw-r--r--packages/Keyguard/res/values-in/strings.xml2
-rw-r--r--packages/Keyguard/res/values-is-rIS/strings.xml2
-rw-r--r--packages/Keyguard/res/values-it/strings.xml2
-rw-r--r--packages/Keyguard/res/values-iw/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ja/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ka-rGE/strings.xml2
-rw-r--r--packages/Keyguard/res/values-kk-rKZ/strings.xml2
-rw-r--r--packages/Keyguard/res/values-km-rKH/strings.xml2
-rw-r--r--packages/Keyguard/res/values-kn-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ko/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ky-rKG/strings.xml2
-rw-r--r--packages/Keyguard/res/values-lo-rLA/strings.xml2
-rw-r--r--packages/Keyguard/res/values-lt/strings.xml2
-rw-r--r--packages/Keyguard/res/values-lv/strings.xml2
-rw-r--r--packages/Keyguard/res/values-mk-rMK/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ml-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-mn-rMN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-mr-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ms-rMY/strings.xml2
-rw-r--r--packages/Keyguard/res/values-my-rMM/strings.xml2
-rw-r--r--packages/Keyguard/res/values-nb/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ne-rNP/strings.xml2
-rw-r--r--packages/Keyguard/res/values-nl/strings.xml2
-rw-r--r--packages/Keyguard/res/values-pa-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-pl/strings.xml2
-rw-r--r--packages/Keyguard/res/values-pt-rBR/strings.xml2
-rw-r--r--packages/Keyguard/res/values-pt-rPT/strings.xml2
-rw-r--r--packages/Keyguard/res/values-pt/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ro/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ru/strings.xml2
-rw-r--r--packages/Keyguard/res/values-si-rLK/strings.xml2
-rw-r--r--packages/Keyguard/res/values-sk/strings.xml2
-rw-r--r--packages/Keyguard/res/values-sl/strings.xml2
-rw-r--r--packages/Keyguard/res/values-sq-rAL/strings.xml2
-rw-r--r--packages/Keyguard/res/values-sr/strings.xml2
-rw-r--r--packages/Keyguard/res/values-sv/strings.xml2
-rw-r--r--packages/Keyguard/res/values-sw/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ta-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-te-rIN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-th/strings.xml2
-rw-r--r--packages/Keyguard/res/values-tl/strings.xml2
-rw-r--r--packages/Keyguard/res/values-tr/strings.xml2
-rw-r--r--packages/Keyguard/res/values-uk/strings.xml2
-rw-r--r--packages/Keyguard/res/values-ur-rPK/strings.xml2
-rw-r--r--packages/Keyguard/res/values-uz-rUZ/strings.xml2
-rw-r--r--packages/Keyguard/res/values-vi/strings.xml2
-rw-r--r--packages/Keyguard/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/Keyguard/res/values-zh-rHK/strings.xml2
-rw-r--r--packages/Keyguard/res/values-zh-rTW/strings.xml2
-rw-r--r--packages/Keyguard/res/values-zu/strings.xml2
-rw-r--r--packages/MtpDocumentsProvider/Android.mk5
-rw-r--r--packages/MtpDocumentsProvider/AndroidManifest.xml4
-rw-r--r--packages/MtpDocumentsProvider/res/mipmap-hdpi/ic_launcher_download.pngbin0 -> 4473 bytes
-rw-r--r--packages/MtpDocumentsProvider/res/mipmap-mdpi/ic_launcher_download.pngbin0 -> 2818 bytes
-rw-r--r--packages/MtpDocumentsProvider/res/mipmap-xhdpi/ic_launcher_download.pngbin0 -> 6351 bytes
-rw-r--r--packages/MtpDocumentsProvider/res/mipmap-xxhdpi/ic_launcher_download.pngbin0 -> 10361 bytes
-rw-r--r--packages/MtpDocumentsProvider/res/mipmap-xxxhdpi/ic_launcher_download.pngbin0 -> 14962 bytes
-rw-r--r--packages/MtpDocumentsProvider/res/values/strings.xml6
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java248
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java34
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java8
-rw-r--r--packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java11
-rw-r--r--packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java58
-rw-r--r--packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java4
-rw-r--r--packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java13
-rw-r--r--packages/PrintSpooler/AndroidManifest.xml4
-rw-r--r--packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp11
-rw-r--r--packages/PrintSpooler/res/drawable/print_warning.xml (renamed from packages/SystemUI/res/layout/recents_history.xml)22
-rw-r--r--packages/PrintSpooler/res/layout/preview_page_error.xml39
-rw-r--r--packages/PrintSpooler/res/values/strings.xml27
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java49
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java89
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java35
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java8
-rw-r--r--packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java23
-rw-r--r--packages/SettingsLib/res/values-b+sr+Latn/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-bg/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-bn-rBD/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ca/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-de/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-es-rUS/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-es/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-et-rEE/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-eu-rES/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-fi/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-fr-rCA/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-gl-rES/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-hr/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-is-rIS/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-it/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ja/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-lt/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-lv/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-mk-rMK/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ms-rMY/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-nb/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-pl/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-pt-rBR/strings.xml5
-rw-r--r--packages/SettingsLib/res/values-pt/strings.xml5
-rw-r--r--packages/SettingsLib/res/values-ro/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ru/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-sq-rAL/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-sr/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ta-rIN/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-tr/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-uk/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-ur-rPK/strings.xml3
-rw-r--r--packages/SettingsLib/res/values-zh-rCN/strings.xml3
-rw-r--r--packages/SettingsLib/res/values/strings.xml19
-rw-r--r--packages/Shell/src/com/android/shell/BugreportProgressService.java84
-rw-r--r--packages/Shell/src/com/android/shell/BugreportStorageProvider.java2
-rw-r--r--packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java27
-rw-r--r--packages/Shell/tests/src/com/android/shell/UiBot.java6
-rw-r--r--packages/SystemUI/AndroidManifest.xml3
-rw-r--r--packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml28
-rw-r--r--packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml28
-rw-r--r--packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml28
-rw-r--r--packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml28
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.pngbin0 -> 414 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-hdpi/ic_sysbar_docked.pngbin0 -> 1254 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked.pngbin0 -> 1151 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked.pngbin0 -> 1402 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked.pngbin0 -> 1643 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked.pngbin0 -> 995 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-land/ic_sysbar_docked.pngbin0 -> 907 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.pngbin0 -> 304 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-mdpi/ic_sysbar_docked.pngbin0 -> 972 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.pngbin0 -> 536 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked.pngbin0 -> 1346 bytes
-rwxr-xr-xpackages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked.pngbin0 -> 1608 bytes
-rwxr-xr-x[-rw-r--r--]packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.pngbin1755 -> 1096 bytes
-rw-r--r--packages/SystemUI/res/layout/hybrid_notification.xml2
-rw-r--r--packages/SystemUI/res/layout/hybrid_overflow_number.xml26
-rw-r--r--packages/SystemUI/res/layout/notification_guts.xml13
-rw-r--r--packages/SystemUI/res/layout/qs_detail.xml2
-rw-r--r--packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml1
-rw-r--r--packages/SystemUI/res/layout/recents_history_clear_all_button.xml37
-rw-r--r--packages/SystemUI/res/layout/recents_history_date.xml30
-rw-r--r--packages/SystemUI/res/layout/recents_history_task.xml42
-rw-r--r--packages/SystemUI/res/layout/recents_on_tv.xml13
-rw-r--r--packages/SystemUI/res/layout/recents_stack_action_button.xml (renamed from packages/SystemUI/res/layout/recents_history_button.xml)2
-rw-r--r--packages/SystemUI/res/layout/recents_task_view_header.xml10
-rw-r--r--packages/SystemUI/res/layout/recents_task_view_header_overlay.xml8
-rw-r--r--packages/SystemUI/res/layout/recents_tv_task_card_view.xml28
-rw-r--r--packages/SystemUI/res/layout/signal_cluster_view.xml7
-rw-r--r--packages/SystemUI/res/layout/status_bar_expanded_header.xml1
-rw-r--r--packages/SystemUI/res/values-af/strings.xml4
-rw-r--r--packages/SystemUI/res/values-af/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-am/strings.xml4
-rw-r--r--packages/SystemUI/res/values-am/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ar/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-az-rAZ/strings.xml4
-rw-r--r--packages/SystemUI/res/values-az-rAZ/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings.xml7
-rw-r--r--packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-be-rBY/strings.xml4
-rw-r--r--packages/SystemUI/res/values-be-rBY/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml7
-rw-r--r--packages/SystemUI/res/values-bg/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings.xml7
-rw-r--r--packages/SystemUI/res/values-bn-rBD/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-bs-rBA/strings.xml4
-rw-r--r--packages/SystemUI/res/values-bs-rBA/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ca/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml2
-rw-r--r--packages/SystemUI/res/values-cs/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-da/strings.xml4
-rw-r--r--packages/SystemUI/res/values-da/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-de/strings.xml7
-rw-r--r--packages/SystemUI/res/values-de/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-el/strings.xml4
-rw-r--r--packages/SystemUI/res/values-el/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rAU/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml7
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-es/strings.xml5
-rw-r--r--packages/SystemUI/res/values-es/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml5
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings.xml9
-rw-r--r--packages/SystemUI/res/values-eu-rES/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fa/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml7
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings.xml7
-rw-r--r--packages/SystemUI/res/values-gl-rES/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-gu-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-gu-rIN/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hi/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-hr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml2
-rw-r--r--packages/SystemUI/res/values-hu/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-in/strings.xml4
-rw-r--r--packages/SystemUI/res/values-in/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings.xml7
-rw-r--r--packages/SystemUI/res/values-is-rIS/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-it/strings.xml7
-rw-r--r--packages/SystemUI/res/values-it/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml4
-rw-r--r--packages/SystemUI/res/values-iw/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ja/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings.xml4
-rw-r--r--packages/SystemUI/res/values-kk-rKZ/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings.xml4
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings.xml4
-rw-r--r--packages/SystemUI/res/values-kn-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ko/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ky-rKG/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-land/config.xml10
-rw-r--r--packages/SystemUI/res/values-land/dimens.xml3
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml4
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml7
-rw-r--r--packages/SystemUI/res/values-lt/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-lv/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings.xml7
-rw-r--r--packages/SystemUI/res/values-mk-rMK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ml-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings.xml4
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-mr-rIN/strings.xml4
-rw-r--r--packages/SystemUI/res/values-mr-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings.xml2
-rw-r--r--packages/SystemUI/res/values-my-rMM/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml5
-rw-r--r--packages/SystemUI/res/values-nb/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-ne-rNP/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ne-rNP/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml2
-rw-r--r--packages/SystemUI/res/values-nl/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pa-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pt-rBR/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml7
-rw-r--r--packages/SystemUI/res/values-pt/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ro/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ru/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings.xml4
-rw-r--r--packages/SystemUI/res/values-si-rLK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sk/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sq-rAL/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-sr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sv/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sw/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-sw600dp/config.xml10
-rw-r--r--packages/SystemUI/res/values-sw600dp/dimens.xml9
-rw-r--r--packages/SystemUI/res/values-sw720dp/dimens.xml5
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings.xml9
-rw-r--r--packages/SystemUI/res/values-ta-rIN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-te-rIN/strings.xml2
-rw-r--r--packages/SystemUI/res/values-te-rIN/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-th/strings.xml4
-rw-r--r--packages/SystemUI/res/values-th/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml4
-rw-r--r--packages/SystemUI/res/values-tl/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml7
-rw-r--r--packages/SystemUI/res/values-tr/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml5
-rw-r--r--packages/SystemUI/res/values-uk/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings.xml7
-rw-r--r--packages/SystemUI/res/values-ur-rPK/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings.xml4
-rw-r--r--packages/SystemUI/res/values-uz-rUZ/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml4
-rw-r--r--packages/SystemUI/res/values-vi/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml7
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml2
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings_tv.xml1
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml4
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-zu/strings_tv.xml2
-rw-r--r--packages/SystemUI/res/values/attrs.xml2
-rw-r--r--packages/SystemUI/res/values/colors.xml6
-rw-r--r--packages/SystemUI/res/values/colors_tv.xml1
-rw-r--r--packages/SystemUI/res/values/config.xml6
-rw-r--r--packages/SystemUI/res/values/dimens.xml163
-rw-r--r--packages/SystemUI/res/values/dimens_tv.xml19
-rw-r--r--packages/SystemUI/res/values/integers_tv.xml2
-rw-r--r--packages/SystemUI/res/values/strings.xml12
-rw-r--r--packages/SystemUI/res/values/strings_tv.xml12
-rw-r--r--packages/SystemUI/res/values/styles.xml2
-rw-r--r--packages/SystemUI/res/values/values_tv.xml2
-rw-r--r--packages/SystemUI/src/com/android/systemui/Prefs.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/SwipeHelper.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/SystemUIFactory.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Constants.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/Recents.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java184
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java69
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHostView.java68
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java65
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java286
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/activity/AppWidgetProviderChangedEvent.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java31
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java (renamed from packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java)6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java (renamed from packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java)8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java378
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryItemTouchCallbacks.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java253
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java271
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/Task.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java92
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java88
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java137
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java80
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java100
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java42
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java372
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java75
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java379
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java175
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java63
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java17
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java24
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java34
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java46
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java45
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java)61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java18
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java44
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java173
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java52
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java29
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java61
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java211
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java87
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java (renamed from packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java)14
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java189
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java42
-rw-r--r--proto/src/metrics_constants.proto5
-rw-r--r--rs/java/android/renderscript/RenderScript.java27
-rw-r--r--rs/java/android/renderscript/ScriptC.java25
-rw-r--r--rs/java/android/renderscript/ScriptGroup.java2
-rw-r--r--services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java2
-rw-r--r--services/core/java/com/android/server/AppOpsService.java98
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java114
-rw-r--r--services/core/java/com/android/server/DeviceIdleController.java41
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java13
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java75
-rw-r--r--services/core/java/com/android/server/connectivity/ApfFilter.java43
-rw-r--r--services/core/java/com/android/server/connectivity/Tethering.java3
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java73
-rw-r--r--services/core/java/com/android/server/job/StateChangedListener.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/AppIdleController.java2
-rw-r--r--services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java184
-rw-r--r--services/core/java/com/android/server/job/controllers/JobStatus.java18
-rw-r--r--services/core/java/com/android/server/job/controllers/StateController.java5
-rw-r--r--services/core/java/com/android/server/media/MediaResourceMonitorService.java22
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java11
-rw-r--r--services/core/java/com/android/server/pm/BackgroundDexOptService.java8
-rw-r--r--services/core/java/com/android/server/pm/Installer.java27
-rw-r--r--services/core/java/com/android/server/pm/OtaDexoptService.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageDexOptimizer.java83
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java69
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java139
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerShellCommand.java110
-rw-r--r--services/core/java/com/android/server/pm/ShortcutLauncher.java199
-rw-r--r--services/core/java/com/android/server/pm/ShortcutPackage.java520
-rw-r--r--services/core/java/com/android/server/pm/ShortcutService.java958
-rw-r--r--services/core/java/com/android/server/pm/ShortcutUser.java179
-rw-r--r--services/core/java/com/android/server/pm/UserManagerService.java50
-rw-r--r--services/core/java/com/android/server/policy/ShortcutManager.java2
-rw-r--r--services/core/java/com/android/server/wallpaper/WallpaperManagerService.java38
-rw-r--r--services/core/java/com/android/server/wm/Session.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java11
-rw-r--r--services/core/java/com/android/server/wm/WindowState.java8
-rw-r--r--services/core/jni/com_android_server_location_GnssLocationProvider.cpp8
-rw-r--r--services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java61
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java317
-rw-r--r--services/usb/java/com/android/server/usb/UsbDeviceManager.java4
-rw-r--r--telecomm/java/android/telecom/Call.java84
-rw-r--r--telecomm/java/android/telecom/Conference.java164
-rw-r--r--telecomm/java/android/telecom/Connection.java162
-rw-r--r--telecomm/java/android/telecom/ConnectionService.java75
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapter.java82
-rw-r--r--telecomm/java/android/telecom/ConnectionServiceAdapterServant.java30
-rw-r--r--telecomm/java/android/telecom/InCallAdapter.java75
-rw-r--r--telecomm/java/android/telecom/RemoteConference.java26
-rw-r--r--telecomm/java/android/telecom/RemoteConnection.java26
-rw-r--r--telecomm/java/android/telecom/RemoteConnectionService.java19
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionService.aidl2
-rw-r--r--telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl4
-rw-r--r--telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl4
-rw-r--r--telephony/java/android/telephony/PhoneStateListener.java68
-rw-r--r--telephony/java/com/android/ims/ImsExternalCallState.java33
-rw-r--r--telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl2
-rw-r--r--telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl2
-rw-r--r--telephony/java/com/android/internal/telephony/TelephonyProperties.java7
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java217
-rw-r--r--tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml11
-rw-r--r--tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java12
-rwxr-xr-xtools/fonts/fontchain_lint.py5
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java70
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java4
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java70
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java20
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java17
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java3
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java10
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java8
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.pngbin5655 -> 5966 bytes
-rw-r--r--tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml19
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java3
-rw-r--r--tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java2
-rw-r--r--wifi/java/android/net/wifi/WifiEnterpriseConfig.java2
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java72
798 files changed, 10453 insertions, 7459 deletions
diff --git a/Android.mk b/Android.mk
index 6a3168ee7ea4..59b2a46b76af 100644
--- a/Android.mk
+++ b/Android.mk
@@ -1043,7 +1043,7 @@ LOCAL_DROIDDOC_OPTIONS:=\
-hdf android.whichdoc offline \
-referenceonly
-LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk-refonly
+LOCAL_DROIDDOC_CUSTOM_TEMPLATE_DIR:=build/tools/droiddoc/templates-sdk
include $(BUILD_DROIDDOC)
diff --git a/api/current.txt b/api/current.txt
index 936ca882ce14..690fec7fdbb2 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -5723,6 +5723,7 @@ package android.app {
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
+ method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
method public boolean isWallpaperSettingAllowed();
@@ -7101,9 +7102,10 @@ package android.bluetooth {
method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
}
- public class BluetoothGattCharacteristic {
+ public class BluetoothGattCharacteristic implements android.os.Parcelable {
ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
method public java.lang.Float getFloatValue(int, int);
@@ -7121,6 +7123,8 @@ package android.bluetooth {
method public boolean setValue(int, int, int, int);
method public boolean setValue(java.lang.String);
method public void setWriteType(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
field public static final int FORMAT_FLOAT = 52; // 0x34
field public static final int FORMAT_SFLOAT = 50; // 0x32
field public static final int FORMAT_SINT16 = 34; // 0x22
@@ -7151,13 +7155,16 @@ package android.bluetooth {
field protected java.util.List<android.bluetooth.BluetoothGattDescriptor> mDescriptors;
}
- public class BluetoothGattDescriptor {
+ public class BluetoothGattDescriptor implements android.os.Parcelable {
ctor public BluetoothGattDescriptor(java.util.UUID, int);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
method public int getPermissions();
method public java.util.UUID getUuid();
method public byte[] getValue();
method public boolean setValue(byte[]);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
field public static final byte[] DISABLE_NOTIFICATION_VALUE;
field public static final byte[] ENABLE_INDICATION_VALUE;
field public static final byte[] ENABLE_NOTIFICATION_VALUE;
@@ -7200,16 +7207,19 @@ package android.bluetooth {
method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
}
- public class BluetoothGattService {
+ public class BluetoothGattService implements android.os.Parcelable {
ctor public BluetoothGattService(java.util.UUID, int);
method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean addService(android.bluetooth.BluetoothGattService);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
method public int getInstanceId();
method public int getType();
method public java.util.UUID getUuid();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattService> CREATOR;
field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
field protected java.util.List<android.bluetooth.BluetoothGattCharacteristic> mCharacteristics;
@@ -13531,6 +13541,7 @@ package android.hardware {
field public static final int TYPE_ACCELEROMETER = 1; // 0x1
field public static final int TYPE_ALL = -1; // 0xffffffff
field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
+ field public static final int TYPE_DEVICE_PRIVATE_BASE = 65536; // 0x10000
field public static final int TYPE_GAME_ROTATION_VECTOR = 15; // 0xf
field public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20; // 0x14
field public static final int TYPE_GRAVITY = 9; // 0x9
@@ -17750,9 +17761,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
method public android.icu.text.UnicodeSet addAll(T...);
method public T addAllTo(T);
- method public java.lang.String[] addAllTo(java.lang.String[]);
- method public static U addAllTo(java.lang.Iterable<T>, U);
- method public static T[] addAllTo(java.lang.Iterable<T>, T[]);
method public void addMatchSetTo(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -17766,10 +17774,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet cloneAsThawed();
method public android.icu.text.UnicodeSet closeOver(int);
method public android.icu.text.UnicodeSet compact();
- method public static int compare(java.lang.CharSequence, int);
- method public static int compare(int, java.lang.CharSequence);
- method public static int compare(java.lang.Iterable<T>, java.lang.Iterable<T>);
- method public static int compare(java.util.Collection<T>, java.util.Collection<T>, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(android.icu.text.UnicodeSet);
method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(java.lang.Iterable<java.lang.String>);
@@ -17812,7 +17816,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
method public final android.icu.text.UnicodeSet removeAllStrings();
- method public static boolean resemblesPattern(java.lang.String, int);
method public android.icu.text.UnicodeSet retain(int, int);
method public final android.icu.text.UnicodeSet retain(int);
method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
@@ -17827,7 +17830,6 @@ package android.icu.text {
method public int spanBack(java.lang.CharSequence, android.icu.text.UnicodeSet.SpanCondition);
method public int spanBack(java.lang.CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
method public java.util.Collection<java.lang.String> strings();
- method public static java.lang.String[] toArray(android.icu.text.UnicodeSet);
method public java.lang.String toPattern(boolean);
field public static final int ADD_CASE_MAPPINGS = 4; // 0x4
field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS;
@@ -17946,11 +17948,8 @@ package android.icu.util {
ctor protected CECalendar(int, int, int);
ctor protected CECalendar(java.util.Date);
ctor protected CECalendar(int, int, int, int, int, int);
- method public static int ceToJD(long, int, int, int);
- method protected abstract int getJDEpochOffset();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetLimit(int, int);
- method public static void jdToCE(int, int, int[]);
}
public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
@@ -18178,7 +18177,6 @@ package android.icu.util {
ctor public CopticCalendar(int, int, int);
ctor public CopticCalendar(java.util.Date);
ctor public CopticCalendar(int, int, int, int, int, int);
- method protected deprecated int getJDEpochOffset();
method protected deprecated int handleGetExtendedYear();
field public static final int AMSHIR = 5; // 0x5
field public static final int BABA = 1; // 0x1
@@ -18349,11 +18347,11 @@ package android.icu.util {
ctor public IslamicCalendar(java.util.Date);
ctor public IslamicCalendar(int, int, int);
ctor public IslamicCalendar(int, int, int, int, int, int);
+ method public android.icu.util.IslamicCalendar.CalculationType getCalculationType();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetExtendedYear();
method protected int handleGetLimit(int, int);
- method public boolean isCivil();
- method public void setCivil(boolean);
+ method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType);
field public static final int DHU_AL_HIJJAH = 11; // 0xb
field public static final int DHU_AL_QIDAH = 10; // 0xa
field public static final int JUMADA_1 = 4; // 0x4
@@ -18791,7 +18789,6 @@ package android.icu.util {
method public int getMicro();
method public int getMilli();
method public int getMinor();
- method public static void main(java.lang.String[]);
field public static final android.icu.util.VersionInfo ICU_VERSION;
field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
@@ -32354,13 +32351,13 @@ package android.provider {
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
- field public static final java.lang.String ACTION_KEYBOARD_LAYOUT_SETTINGS = "android.settings.KEYBOARD_LAYOUT_SETTINGS";
field public static final java.lang.String ACTION_LOCALE_SETTINGS = "android.settings.LOCALE_SETTINGS";
field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
@@ -36011,9 +36008,11 @@ package android.telecom {
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
method public void pullExternalCall();
+ method public final void putExtras(android.os.Bundle);
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void splitFromConference();
method public void stopDtmfTone();
@@ -36154,6 +36153,7 @@ package android.telecom {
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
+ method public void onExtrasChanged(android.os.Bundle);
method public void onHold();
method public void onMerge(android.telecom.Connection);
method public void onMerge();
@@ -36162,14 +36162,16 @@ package android.telecom {
method public void onStopDtmfTone();
method public void onSwap();
method public void onUnhold();
+ method public final void putExtras(android.os.Bundle);
method public final void removeConnection(android.telecom.Connection);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public final void setActive();
method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
method public final void setConnectionCapabilities(int);
method public final void setConnectionTime(long);
method public final void setDialing();
method public final void setDisconnected(android.telecom.DisconnectCause);
- method public final void setExtras(android.os.Bundle);
+ method public final deprecated void setExtras(android.os.Bundle);
method public final void setOnHold();
method public final void setStatusHints(android.telecom.StatusHints);
method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
@@ -36207,6 +36209,7 @@ package android.telecom {
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallEvent(java.lang.String, android.os.Bundle);
method public void onDisconnect();
+ method public void onExtrasChanged(android.os.Bundle);
method public void onHold();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);
@@ -36217,6 +36220,8 @@ package android.telecom {
method public void onStateChanged(int);
method public void onStopDtmfTone();
method public void onUnhold();
+ method public final void putExtras(android.os.Bundle);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
@@ -36227,7 +36232,7 @@ package android.telecom {
method public final void setConnectionCapabilities(int);
method public final void setDialing();
method public final void setDisconnected(android.telecom.DisconnectCause);
- method public final void setExtras(android.os.Bundle);
+ method public final deprecated void setExtras(android.os.Bundle);
method public final void setInitialized();
method public final void setInitializing();
method public final void setNextPostDialChar(char);
diff --git a/api/system-current.txt b/api/system-current.txt
index f8863e53d8ba..f06e54562867 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -5857,6 +5857,7 @@ package android.app {
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
+ method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
method public boolean isWallpaperSettingAllowed();
@@ -7376,9 +7377,10 @@ package android.bluetooth {
method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
}
- public class BluetoothGattCharacteristic {
+ public class BluetoothGattCharacteristic implements android.os.Parcelable {
ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
method public java.lang.Float getFloatValue(int, int);
@@ -7396,6 +7398,8 @@ package android.bluetooth {
method public boolean setValue(int, int, int, int);
method public boolean setValue(java.lang.String);
method public void setWriteType(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
field public static final int FORMAT_FLOAT = 52; // 0x34
field public static final int FORMAT_SFLOAT = 50; // 0x32
field public static final int FORMAT_SINT16 = 34; // 0x22
@@ -7426,13 +7430,16 @@ package android.bluetooth {
field protected java.util.List<android.bluetooth.BluetoothGattDescriptor> mDescriptors;
}
- public class BluetoothGattDescriptor {
+ public class BluetoothGattDescriptor implements android.os.Parcelable {
ctor public BluetoothGattDescriptor(java.util.UUID, int);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
method public int getPermissions();
method public java.util.UUID getUuid();
method public byte[] getValue();
method public boolean setValue(byte[]);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
field public static final byte[] DISABLE_NOTIFICATION_VALUE;
field public static final byte[] ENABLE_INDICATION_VALUE;
field public static final byte[] ENABLE_NOTIFICATION_VALUE;
@@ -7475,16 +7482,19 @@ package android.bluetooth {
method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
}
- public class BluetoothGattService {
+ public class BluetoothGattService implements android.os.Parcelable {
ctor public BluetoothGattService(java.util.UUID, int);
method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean addService(android.bluetooth.BluetoothGattService);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
method public int getInstanceId();
method public int getType();
method public java.util.UUID getUuid();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattService> CREATOR;
field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
field protected java.util.List<android.bluetooth.BluetoothGattCharacteristic> mCharacteristics;
@@ -13932,6 +13942,7 @@ package android.hardware {
field public static final int TYPE_ACCELEROMETER = 1; // 0x1
field public static final int TYPE_ALL = -1; // 0xffffffff
field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
+ field public static final int TYPE_DEVICE_PRIVATE_BASE = 65536; // 0x10000
field public static final int TYPE_DYNAMIC_SENSOR_META = 32; // 0x20
field public static final int TYPE_GAME_ROTATION_VECTOR = 15; // 0xf
field public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20; // 0x14
@@ -18922,9 +18933,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
method public android.icu.text.UnicodeSet addAll(T...);
method public T addAllTo(T);
- method public java.lang.String[] addAllTo(java.lang.String[]);
- method public static U addAllTo(java.lang.Iterable<T>, U);
- method public static T[] addAllTo(java.lang.Iterable<T>, T[]);
method public void addMatchSetTo(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -18938,10 +18946,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet cloneAsThawed();
method public android.icu.text.UnicodeSet closeOver(int);
method public android.icu.text.UnicodeSet compact();
- method public static int compare(java.lang.CharSequence, int);
- method public static int compare(int, java.lang.CharSequence);
- method public static int compare(java.lang.Iterable<T>, java.lang.Iterable<T>);
- method public static int compare(java.util.Collection<T>, java.util.Collection<T>, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(android.icu.text.UnicodeSet);
method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(java.lang.Iterable<java.lang.String>);
@@ -18984,7 +18988,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
method public final android.icu.text.UnicodeSet removeAllStrings();
- method public static boolean resemblesPattern(java.lang.String, int);
method public android.icu.text.UnicodeSet retain(int, int);
method public final android.icu.text.UnicodeSet retain(int);
method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
@@ -18999,7 +19002,6 @@ package android.icu.text {
method public int spanBack(java.lang.CharSequence, android.icu.text.UnicodeSet.SpanCondition);
method public int spanBack(java.lang.CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
method public java.util.Collection<java.lang.String> strings();
- method public static java.lang.String[] toArray(android.icu.text.UnicodeSet);
method public java.lang.String toPattern(boolean);
field public static final int ADD_CASE_MAPPINGS = 4; // 0x4
field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS;
@@ -19118,11 +19120,8 @@ package android.icu.util {
ctor protected CECalendar(int, int, int);
ctor protected CECalendar(java.util.Date);
ctor protected CECalendar(int, int, int, int, int, int);
- method public static int ceToJD(long, int, int, int);
- method protected abstract int getJDEpochOffset();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetLimit(int, int);
- method public static void jdToCE(int, int, int[]);
}
public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
@@ -19350,7 +19349,6 @@ package android.icu.util {
ctor public CopticCalendar(int, int, int);
ctor public CopticCalendar(java.util.Date);
ctor public CopticCalendar(int, int, int, int, int, int);
- method protected deprecated int getJDEpochOffset();
method protected deprecated int handleGetExtendedYear();
field public static final int AMSHIR = 5; // 0x5
field public static final int BABA = 1; // 0x1
@@ -19521,11 +19519,11 @@ package android.icu.util {
ctor public IslamicCalendar(java.util.Date);
ctor public IslamicCalendar(int, int, int);
ctor public IslamicCalendar(int, int, int, int, int, int);
+ method public android.icu.util.IslamicCalendar.CalculationType getCalculationType();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetExtendedYear();
method protected int handleGetLimit(int, int);
- method public boolean isCivil();
- method public void setCivil(boolean);
+ method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType);
field public static final int DHU_AL_HIJJAH = 11; // 0xb
field public static final int DHU_AL_QIDAH = 10; // 0xa
field public static final int JUMADA_1 = 4; // 0x4
@@ -19963,7 +19961,6 @@ package android.icu.util {
method public int getMicro();
method public int getMilli();
method public int getMinor();
- method public static void main(java.lang.String[]);
field public static final android.icu.util.VersionInfo ICU_VERSION;
field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
@@ -31648,6 +31645,7 @@ package android.os {
method public android.os.Bundle getUserRestrictions(android.os.UserHandle);
method public boolean hasUserRestriction(java.lang.String);
method public boolean isManagedProfile();
+ method public boolean isManagedProfile(int);
method public boolean isQuietModeEnabled(android.os.UserHandle);
method public boolean isSystemUser();
method public boolean isUserAGoat();
@@ -34800,13 +34798,13 @@ package android.provider {
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
- field public static final java.lang.String ACTION_KEYBOARD_LAYOUT_SETTINGS = "android.settings.KEYBOARD_LAYOUT_SETTINGS";
field public static final java.lang.String ACTION_LOCALE_SETTINGS = "android.settings.LOCALE_SETTINGS";
field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
@@ -38573,9 +38571,11 @@ package android.telecom {
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
method public void pullExternalCall();
+ method public final void putExtras(android.os.Bundle);
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public deprecated void removeListener(android.telecom.Call.Listener);
method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void splitFromConference();
@@ -38726,6 +38726,7 @@ package android.telecom {
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
+ method public void onExtrasChanged(android.os.Bundle);
method public void onHold();
method public void onMerge(android.telecom.Connection);
method public void onMerge();
@@ -38734,7 +38735,9 @@ package android.telecom {
method public void onStopDtmfTone();
method public void onSwap();
method public void onUnhold();
+ method public final void putExtras(android.os.Bundle);
method public final void removeConnection(android.telecom.Connection);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public final void setActive();
method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
method public final deprecated void setConnectTimeMillis(long);
@@ -38742,7 +38745,7 @@ package android.telecom {
method public final void setConnectionTime(long);
method public final void setDialing();
method public final void setDisconnected(android.telecom.DisconnectCause);
- method public final void setExtras(android.os.Bundle);
+ method public final deprecated void setExtras(android.os.Bundle);
method public final void setOnHold();
method public final void setStatusHints(android.telecom.StatusHints);
method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
@@ -38782,6 +38785,7 @@ package android.telecom {
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallEvent(java.lang.String, android.os.Bundle);
method public void onDisconnect();
+ method public void onExtrasChanged(android.os.Bundle);
method public void onHold();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);
@@ -38792,6 +38796,8 @@ package android.telecom {
method public void onStateChanged(int);
method public void onStopDtmfTone();
method public void onUnhold();
+ method public final void putExtras(android.os.Bundle);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
@@ -38802,7 +38808,7 @@ package android.telecom {
method public final void setConnectionCapabilities(int);
method public final void setDialing();
method public final void setDisconnected(android.telecom.DisconnectCause);
- method public final void setExtras(android.os.Bundle);
+ method public final deprecated void setExtras(android.os.Bundle);
method public final void setInitialized();
method public final void setInitializing();
method public final void setNextPostDialChar(char);
diff --git a/api/test-current.txt b/api/test-current.txt
index 6327dc2200d1..4afda9cfe65e 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -5727,6 +5727,7 @@ package android.app {
method public android.graphics.drawable.Drawable getFastDrawable();
method public static android.app.WallpaperManager getInstance(android.content.Context);
method public android.os.ParcelFileDescriptor getWallpaperFile(int);
+ method public int getWallpaperId(int);
method public android.app.WallpaperInfo getWallpaperInfo();
method public boolean hasResourceWallpaper(int);
method public boolean isWallpaperSettingAllowed();
@@ -7105,9 +7106,10 @@ package android.bluetooth {
method public void onServicesDiscovered(android.bluetooth.BluetoothGatt, int);
}
- public class BluetoothGattCharacteristic {
+ public class BluetoothGattCharacteristic implements android.os.Parcelable {
ctor public BluetoothGattCharacteristic(java.util.UUID, int, int);
method public boolean addDescriptor(android.bluetooth.BluetoothGattDescriptor);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattDescriptor getDescriptor(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattDescriptor> getDescriptors();
method public java.lang.Float getFloatValue(int, int);
@@ -7125,6 +7127,8 @@ package android.bluetooth {
method public boolean setValue(int, int, int, int);
method public boolean setValue(java.lang.String);
method public void setWriteType(int);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattCharacteristic> CREATOR;
field public static final int FORMAT_FLOAT = 52; // 0x34
field public static final int FORMAT_SFLOAT = 50; // 0x32
field public static final int FORMAT_SINT16 = 34; // 0x22
@@ -7155,13 +7159,16 @@ package android.bluetooth {
field protected java.util.List<android.bluetooth.BluetoothGattDescriptor> mDescriptors;
}
- public class BluetoothGattDescriptor {
+ public class BluetoothGattDescriptor implements android.os.Parcelable {
ctor public BluetoothGattDescriptor(java.util.UUID, int);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic();
method public int getPermissions();
method public java.util.UUID getUuid();
method public byte[] getValue();
method public boolean setValue(byte[]);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattDescriptor> CREATOR;
field public static final byte[] DISABLE_NOTIFICATION_VALUE;
field public static final byte[] ENABLE_INDICATION_VALUE;
field public static final byte[] ENABLE_NOTIFICATION_VALUE;
@@ -7204,16 +7211,19 @@ package android.bluetooth {
method public void onServiceAdded(int, android.bluetooth.BluetoothGattService);
}
- public class BluetoothGattService {
+ public class BluetoothGattService implements android.os.Parcelable {
ctor public BluetoothGattService(java.util.UUID, int);
method public boolean addCharacteristic(android.bluetooth.BluetoothGattCharacteristic);
method public boolean addService(android.bluetooth.BluetoothGattService);
+ method public int describeContents();
method public android.bluetooth.BluetoothGattCharacteristic getCharacteristic(java.util.UUID);
method public java.util.List<android.bluetooth.BluetoothGattCharacteristic> getCharacteristics();
method public java.util.List<android.bluetooth.BluetoothGattService> getIncludedServices();
method public int getInstanceId();
method public int getType();
method public java.util.UUID getUuid();
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final android.os.Parcelable.Creator<android.bluetooth.BluetoothGattService> CREATOR;
field public static final int SERVICE_TYPE_PRIMARY = 0; // 0x0
field public static final int SERVICE_TYPE_SECONDARY = 1; // 0x1
field protected java.util.List<android.bluetooth.BluetoothGattCharacteristic> mCharacteristics;
@@ -13541,6 +13551,7 @@ package android.hardware {
field public static final int TYPE_ACCELEROMETER = 1; // 0x1
field public static final int TYPE_ALL = -1; // 0xffffffff
field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
+ field public static final int TYPE_DEVICE_PRIVATE_BASE = 65536; // 0x10000
field public static final int TYPE_GAME_ROTATION_VECTOR = 15; // 0xf
field public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20; // 0x14
field public static final int TYPE_GRAVITY = 9; // 0x9
@@ -17760,9 +17771,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet addAll(java.lang.Iterable<?>);
method public android.icu.text.UnicodeSet addAll(T...);
method public T addAllTo(T);
- method public java.lang.String[] addAllTo(java.lang.String[]);
- method public static U addAllTo(java.lang.Iterable<T>, U);
- method public static T[] addAllTo(java.lang.Iterable<T>, T[]);
method public void addMatchSetTo(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet applyIntPropertyValue(int, int);
method public final android.icu.text.UnicodeSet applyPattern(java.lang.String);
@@ -17776,10 +17784,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet cloneAsThawed();
method public android.icu.text.UnicodeSet closeOver(int);
method public android.icu.text.UnicodeSet compact();
- method public static int compare(java.lang.CharSequence, int);
- method public static int compare(int, java.lang.CharSequence);
- method public static int compare(java.lang.Iterable<T>, java.lang.Iterable<T>);
- method public static int compare(java.util.Collection<T>, java.util.Collection<T>, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(android.icu.text.UnicodeSet);
method public int compareTo(android.icu.text.UnicodeSet, android.icu.text.UnicodeSet.ComparisonStyle);
method public int compareTo(java.lang.Iterable<java.lang.String>);
@@ -17822,7 +17826,6 @@ package android.icu.text {
method public android.icu.text.UnicodeSet removeAll(android.icu.text.UnicodeSet);
method public android.icu.text.UnicodeSet removeAll(java.lang.Iterable<T>);
method public final android.icu.text.UnicodeSet removeAllStrings();
- method public static boolean resemblesPattern(java.lang.String, int);
method public android.icu.text.UnicodeSet retain(int, int);
method public final android.icu.text.UnicodeSet retain(int);
method public final android.icu.text.UnicodeSet retain(java.lang.CharSequence);
@@ -17837,7 +17840,6 @@ package android.icu.text {
method public int spanBack(java.lang.CharSequence, android.icu.text.UnicodeSet.SpanCondition);
method public int spanBack(java.lang.CharSequence, int, android.icu.text.UnicodeSet.SpanCondition);
method public java.util.Collection<java.lang.String> strings();
- method public static java.lang.String[] toArray(android.icu.text.UnicodeSet);
method public java.lang.String toPattern(boolean);
field public static final int ADD_CASE_MAPPINGS = 4; // 0x4
field public static final android.icu.text.UnicodeSet ALL_CODE_POINTS;
@@ -17956,11 +17958,8 @@ package android.icu.util {
ctor protected CECalendar(int, int, int);
ctor protected CECalendar(java.util.Date);
ctor protected CECalendar(int, int, int, int, int, int);
- method public static int ceToJD(long, int, int, int);
- method protected abstract int getJDEpochOffset();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetLimit(int, int);
- method public static void jdToCE(int, int, int[]);
}
public abstract class Calendar implements java.lang.Cloneable java.lang.Comparable java.io.Serializable {
@@ -18188,7 +18187,6 @@ package android.icu.util {
ctor public CopticCalendar(int, int, int);
ctor public CopticCalendar(java.util.Date);
ctor public CopticCalendar(int, int, int, int, int, int);
- method protected deprecated int getJDEpochOffset();
method protected deprecated int handleGetExtendedYear();
field public static final int AMSHIR = 5; // 0x5
field public static final int BABA = 1; // 0x1
@@ -18359,11 +18357,11 @@ package android.icu.util {
ctor public IslamicCalendar(java.util.Date);
ctor public IslamicCalendar(int, int, int);
ctor public IslamicCalendar(int, int, int, int, int, int);
+ method public android.icu.util.IslamicCalendar.CalculationType getCalculationType();
method protected int handleComputeMonthStart(int, int, boolean);
method protected int handleGetExtendedYear();
method protected int handleGetLimit(int, int);
- method public boolean isCivil();
- method public void setCivil(boolean);
+ method public void setCalculationType(android.icu.util.IslamicCalendar.CalculationType);
field public static final int DHU_AL_HIJJAH = 11; // 0xb
field public static final int DHU_AL_QIDAH = 10; // 0xa
field public static final int JUMADA_1 = 4; // 0x4
@@ -18801,7 +18799,6 @@ package android.icu.util {
method public int getMicro();
method public int getMilli();
method public int getMinor();
- method public static void main(java.lang.String[]);
field public static final android.icu.util.VersionInfo ICU_VERSION;
field public static final android.icu.util.VersionInfo UCOL_BUILDER_VERSION;
field public static final android.icu.util.VersionInfo UCOL_RUNTIME_VERSION;
@@ -32423,13 +32420,13 @@ package android.provider {
field public static final java.lang.String ACTION_DEVICE_INFO_SETTINGS = "android.settings.DEVICE_INFO_SETTINGS";
field public static final java.lang.String ACTION_DISPLAY_SETTINGS = "android.settings.DISPLAY_SETTINGS";
field public static final java.lang.String ACTION_DREAM_SETTINGS = "android.settings.DREAM_SETTINGS";
+ field public static final java.lang.String ACTION_HARD_KEYBOARD_SETTINGS = "android.settings.HARD_KEYBOARD_SETTINGS";
field public static final java.lang.String ACTION_HOME_SETTINGS = "android.settings.HOME_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS = "android.settings.IGNORE_BACKGROUND_DATA_RESTRICTIONS_SETTINGS";
field public static final java.lang.String ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS = "android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SETTINGS = "android.settings.INPUT_METHOD_SETTINGS";
field public static final java.lang.String ACTION_INPUT_METHOD_SUBTYPE_SETTINGS = "android.settings.INPUT_METHOD_SUBTYPE_SETTINGS";
field public static final java.lang.String ACTION_INTERNAL_STORAGE_SETTINGS = "android.settings.INTERNAL_STORAGE_SETTINGS";
- field public static final java.lang.String ACTION_KEYBOARD_LAYOUT_SETTINGS = "android.settings.KEYBOARD_LAYOUT_SETTINGS";
field public static final java.lang.String ACTION_LOCALE_SETTINGS = "android.settings.LOCALE_SETTINGS";
field public static final java.lang.String ACTION_LOCATION_SOURCE_SETTINGS = "android.settings.LOCATION_SOURCE_SETTINGS";
field public static final java.lang.String ACTION_MANAGE_ALL_APPLICATIONS_SETTINGS = "android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS";
@@ -36082,9 +36079,11 @@ package android.telecom {
method public void playDtmfTone(char);
method public void postDialContinue(boolean);
method public void pullExternalCall();
+ method public final void putExtras(android.os.Bundle);
method public void registerCallback(android.telecom.Call.Callback);
method public void registerCallback(android.telecom.Call.Callback, android.os.Handler);
method public void reject(boolean, java.lang.String);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public void sendCallEvent(java.lang.String, android.os.Bundle);
method public void splitFromConference();
method public void stopDtmfTone();
@@ -36225,6 +36224,7 @@ package android.telecom {
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onConnectionAdded(android.telecom.Connection);
method public void onDisconnect();
+ method public void onExtrasChanged(android.os.Bundle);
method public void onHold();
method public void onMerge(android.telecom.Connection);
method public void onMerge();
@@ -36233,14 +36233,16 @@ package android.telecom {
method public void onStopDtmfTone();
method public void onSwap();
method public void onUnhold();
+ method public final void putExtras(android.os.Bundle);
method public final void removeConnection(android.telecom.Connection);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public final void setActive();
method public final void setConferenceableConnections(java.util.List<android.telecom.Connection>);
method public final void setConnectionCapabilities(int);
method public final void setConnectionTime(long);
method public final void setDialing();
method public final void setDisconnected(android.telecom.DisconnectCause);
- method public final void setExtras(android.os.Bundle);
+ method public final deprecated void setExtras(android.os.Bundle);
method public final void setOnHold();
method public final void setStatusHints(android.telecom.StatusHints);
method public final void setVideoProvider(android.telecom.Connection, android.telecom.Connection.VideoProvider);
@@ -36278,6 +36280,7 @@ package android.telecom {
method public void onCallAudioStateChanged(android.telecom.CallAudioState);
method public void onCallEvent(java.lang.String, android.os.Bundle);
method public void onDisconnect();
+ method public void onExtrasChanged(android.os.Bundle);
method public void onHold();
method public void onPlayDtmfTone(char);
method public void onPostDialContinue(boolean);
@@ -36288,6 +36291,8 @@ package android.telecom {
method public void onStateChanged(int);
method public void onStopDtmfTone();
method public void onUnhold();
+ method public final void putExtras(android.os.Bundle);
+ method public final void removeExtras(java.util.List<java.lang.String>);
method public void sendConnectionEvent(java.lang.String, android.os.Bundle);
method public final void setActive();
method public final void setAddress(android.net.Uri, int);
@@ -36298,7 +36303,7 @@ package android.telecom {
method public final void setConnectionCapabilities(int);
method public final void setDialing();
method public final void setDisconnected(android.telecom.DisconnectCause);
- method public final void setExtras(android.os.Bundle);
+ method public final deprecated void setExtras(android.os.Bundle);
method public final void setInitialized();
method public final void setInitializing();
method public final void setNextPostDialChar(char);
diff --git a/core/java/android/animation/Animator.java b/core/java/android/animation/Animator.java
index 8e31d323009f..c51725a2caac 100644
--- a/core/java/android/animation/Animator.java
+++ b/core/java/android/animation/Animator.java
@@ -16,6 +16,7 @@
package android.animation;
+import android.annotation.Nullable;
import android.content.pm.ActivityInfo.Config;
import android.content.res.ConstantState;
@@ -436,10 +437,14 @@ public abstract class Animator implements Cloneable {
* operate on target objects (for example, {@link ValueAnimator}, but this method
* is on the superclass for the convenience of dealing generically with those subclasses
* that do handle targets.
+ * <p>
+ * <strong>Note:</strong> The target is stored as a weak reference internally to avoid leaking
+ * resources by having animators directly reference old targets. Therefore, you should
+ * ensure that animator targets always have a hard reference elsewhere.
*
* @param target The object being animated
*/
- public void setTarget(Object target) {
+ public void setTarget(@Nullable Object target) {
}
// Hide reverse() and canReverse() for now since reverse() only work for simple
diff --git a/core/java/android/animation/ObjectAnimator.java b/core/java/android/animation/ObjectAnimator.java
index efb9192a7583..542ecf41756e 100644
--- a/core/java/android/animation/ObjectAnimator.java
+++ b/core/java/android/animation/ObjectAnimator.java
@@ -898,12 +898,6 @@ public final class ObjectAnimator extends ValueAnimator {
return mTarget == null ? null : mTarget.get();
}
- /**
- * Sets the target object whose property will be animated by this animation. If the
- * animator has been started, it will be canceled.
- *
- * @param target The object being animated
- */
@Override
public void setTarget(@Nullable Object target) {
final Object oldTarget = getTarget();
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 5ef03d1cac6f..5b7dae67392c 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1147,8 +1147,7 @@ public class ApplicationPackageManager extends PackageManager {
}
private Drawable getManagedProfileIconForDensity(UserHandle user, int drawableId, int density) {
- UserInfo userInfo = getUserInfo(user.getIdentifier());
- if (userInfo != null && userInfo.isManagedProfile()) {
+ if (isManagedProfile(user.getIdentifier())) {
return getDrawableForDensity(drawableId, density);
}
return null;
@@ -1156,8 +1155,7 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public CharSequence getUserBadgedLabel(CharSequence label, UserHandle user) {
- UserInfo userInfo = getUserInfo(user.getIdentifier());
- if (userInfo != null && userInfo.isManagedProfile()) {
+ if (isManagedProfile(user.getIdentifier())) {
return Resources.getSystem().getString(
com.android.internal.R.string.managed_profile_label_badge, label);
}
@@ -2259,17 +2257,16 @@ public class ApplicationPackageManager extends PackageManager {
return drawable;
}
- private int getBadgeResIdForUser(int userHandle) {
+ private int getBadgeResIdForUser(int userId) {
// Return the framework-provided badge.
- UserInfo userInfo = getUserInfo(userHandle);
- if (userInfo != null && userInfo.isManagedProfile()) {
+ if (isManagedProfile(userId)) {
return com.android.internal.R.drawable.ic_corp_icon_badge;
}
return 0;
}
- private UserInfo getUserInfo(int userHandle) {
- return getUserManager().getUserInfo(userHandle);
+ private boolean isManagedProfile(int userId) {
+ return getUserManager().isManagedProfile(userId);
}
/** {@hide} */
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index ed4bb28427ae..536c4a865fce 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -1319,7 +1319,7 @@ public class DownloadManager {
return getLocalUri();
case COLUMN_LOCAL_FILENAME:
if (!mAccessFilename) {
- throw new IllegalArgumentException(
+ throw new SecurityException(
"COLUMN_LOCAL_FILENAME is deprecated;"
+ " use ContentResolver.openFileDescriptor() instead");
}
diff --git a/core/java/android/app/Fragment.java b/core/java/android/app/Fragment.java
index 6870bbff48c7..f7a4557f8760 100644
--- a/core/java/android/app/Fragment.java
+++ b/core/java/android/app/Fragment.java
@@ -1429,16 +1429,20 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
final Context context = getContext();
final int version = context != null ? context.getApplicationInfo().targetSdkVersion : 0;
if (version >= Build.VERSION_CODES.N) {
- if (savedInstanceState != null) {
- Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG);
- if (p != null) {
- if (mChildFragmentManager == null) {
- instantiateChildFragmentManager();
- }
- mChildFragmentManager.restoreAllState(p, mChildNonConfig);
- mChildNonConfig = null;
- mChildFragmentManager.dispatchCreate();
+ restoreChildFragmentState(savedInstanceState, true);
+ }
+ }
+
+ void restoreChildFragmentState(@Nullable Bundle savedInstanceState, boolean provideNonConfig) {
+ if (savedInstanceState != null) {
+ Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG);
+ if (p != null) {
+ if (mChildFragmentManager == null) {
+ instantiateChildFragmentManager();
}
+ mChildFragmentManager.restoreAllState(p, provideNonConfig ? mChildNonConfig : null);
+ mChildNonConfig = null;
+ mChildFragmentManager.dispatchCreate();
}
}
}
@@ -1692,6 +1696,18 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
*/
public void onDetach() {
mCalled = true;
+
+ // Destroy the child FragmentManager if we still have it here.
+ // We won't unless we're retaining our instance and if we do,
+ // our child FragmentManager instance state will have already been saved.
+ if (mChildFragmentManager != null) {
+ if (!mRetaining) {
+ throw new IllegalStateException("Child FragmentManager of " + this + " was not "
+ + " destroyed and this fragment is not retaining instance");
+ }
+ mChildFragmentManager.dispatchDestroy();
+ mChildFragmentManager = null;
+ }
}
/**
@@ -2252,16 +2268,7 @@ public class Fragment implements ComponentCallbacks2, OnCreateContextMenuListene
final Context context = getContext();
final int version = context != null ? context.getApplicationInfo().targetSdkVersion : 0;
if (version < Build.VERSION_CODES.N) {
- if (savedInstanceState != null) {
- Parcelable p = savedInstanceState.getParcelable(Activity.FRAGMENTS_TAG);
- if (p != null) {
- if (mChildFragmentManager == null) {
- instantiateChildFragmentManager();
- }
- mChildFragmentManager.restoreAllState(p, null);
- mChildFragmentManager.dispatchCreate();
- }
- }
+ restoreChildFragmentState(savedInstanceState, false);
}
}
diff --git a/core/java/android/app/FragmentManager.java b/core/java/android/app/FragmentManager.java
index 063194310e77..2852baf9c21b 100644
--- a/core/java/android/app/FragmentManager.java
+++ b/core/java/android/app/FragmentManager.java
@@ -941,6 +941,9 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
if (!f.mRetaining) {
f.performCreate(f.mSavedFragmentState);
+ } else {
+ f.restoreChildFragmentState(f.mSavedFragmentState, true);
+ f.mState = Fragment.CREATED;
}
f.mRetaining = false;
if (f.mFromLayout) {
@@ -1009,6 +1012,9 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
f.mSavedFragmentState = null;
}
case Fragment.ACTIVITY_CREATED:
+ if (newState > Fragment.ACTIVITY_CREATED) {
+ f.mState = Fragment.STOPPED;
+ }
case Fragment.STOPPED:
if (newState > Fragment.STOPPED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
@@ -1108,7 +1114,7 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
if (!f.mRetaining) {
f.performDestroy();
} else {
- f.mState = Fragment.INITIALIZING;
+ f.mState = Fragment.CREATED;
}
f.mCalled = false;
@@ -1124,7 +1130,6 @@ final class FragmentManagerImpl extends FragmentManager implements LayoutInflate
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
- f.mChildFragmentManager = null;
}
}
}
diff --git a/core/java/android/app/IWallpaperManager.aidl b/core/java/android/app/IWallpaperManager.aidl
index 1143c6aec7a6..2fc6533f2cd0 100644
--- a/core/java/android/app/IWallpaperManager.aidl
+++ b/core/java/android/app/IWallpaperManager.aidl
@@ -62,6 +62,11 @@ interface IWallpaperManager {
out Bundle outParams, int userId);
/**
+ * Retrieve the given user's current wallpaper ID of the given kind.
+ */
+ int getWallpaperIdForUser(int which, int userId);
+
+ /**
* If the current system wallpaper is a live wallpaper component, return the
* information about that wallpaper. Otherwise, if it is a static image,
* simply return null.
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index cb1bee5c0376..8423de882782 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -24,7 +24,6 @@ import android.annotation.SdkConstant.SdkConstantType;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.ColorStateList;
import android.graphics.Bitmap;
@@ -568,6 +567,12 @@ public class Notification implements Parcelable
public static final int COLOR_DEFAULT = 0; // AKA Color.TRANSPARENT
/**
+ * Special value of {@link #color} used as a place holder for an invalid color.
+ */
+ @ColorInt
+ private static final int COLOR_INVALID = 1;
+
+ /**
* Sphere of visibility of this notification, which affects how and when the SystemUI reveals
* the notification's presence and contents in untrusted situations (namely, on the secure
* lockscreen).
@@ -2092,6 +2097,12 @@ public class Notification implements Parcelable
private boolean mColorUtilInited = false;
/**
+ * Caches a contrast-enhanced version of {@link #mCachedContrastColorIsFor}.
+ */
+ private int mCachedContrastColor = COLOR_INVALID;
+ private int mCachedContrastColorIsFor = COLOR_INVALID;
+
+ /**
* Constructs a new Builder with the defaults:
*
@@ -3074,7 +3085,7 @@ public class Notification implements Parcelable
R.id.progress, ColorStateList.valueOf(mContext.getColor(
R.color.notification_progress_background_color)));
if (mN.color != COLOR_DEFAULT) {
- ColorStateList colorStateList = ColorStateList.valueOf(mN.color);
+ ColorStateList colorStateList = ColorStateList.valueOf(resolveContrastColor());
contentView.setProgressTintList(R.id.progress, colorStateList);
contentView.setProgressIndeterminateTintList(R.id.progress, colorStateList);
}
@@ -3135,10 +3146,10 @@ public class Notification implements Parcelable
}
private void bindExpandButton(RemoteViews contentView) {
- contentView.setDrawableParameters(R.id.expand_button, false, -1, resolveColor(),
+ contentView.setDrawableParameters(R.id.expand_button, false, -1, resolveContrastColor(),
PorterDuff.Mode.SRC_ATOP, -1);
contentView.setInt(R.id.notification_header, "setOriginalNotificationColor",
- resolveColor());
+ resolveContrastColor());
}
private void bindHeaderChronometerAndTime(RemoteViews contentView) {
@@ -3180,7 +3191,7 @@ public class Notification implements Parcelable
return;
}
contentView.setTextViewText(R.id.app_name_text, appName);
- contentView.setTextColor(R.id.app_name_text, resolveColor());
+ contentView.setTextColor(R.id.app_name_text, resolveContrastColor());
}
private void bindSmallIcon(RemoteViews contentView) {
@@ -3405,7 +3416,7 @@ public class Notification implements Parcelable
button.setRemoteInputs(R.id.action0, action.mRemoteInputs);
}
if (mN.color != COLOR_DEFAULT) {
- button.setTextColor(R.id.action0, mN.color);
+ button.setTextColor(R.id.action0, resolveContrastColor());
}
return button;
}
@@ -3432,12 +3443,12 @@ public class Notification implements Parcelable
private void processSmallIconColor(Icon smallIcon, RemoteViews contentView) {
boolean colorable = !isLegacy() || getColorUtil().isGrayscaleIcon(mContext, smallIcon);
if (colorable) {
- contentView.setDrawableParameters(R.id.icon, false, -1, resolveColor(),
+ contentView.setDrawableParameters(R.id.icon, false, -1, resolveContrastColor(),
PorterDuff.Mode.SRC_ATOP, -1);
}
contentView.setInt(R.id.notification_header, "setOriginalIconColor",
- colorable ? resolveColor() : NotificationHeaderView.NO_COLOR);
+ colorable ? resolveContrastColor() : NotificationHeaderView.NO_COLOR);
}
/**
@@ -3449,7 +3460,7 @@ public class Notification implements Parcelable
if (largeIcon != null && isLegacy()
&& getColorUtil().isGrayscaleIcon(mContext, largeIcon)) {
// resolve color will fall back to the default when legacy
- contentView.setDrawableParameters(R.id.icon, false, -1, resolveColor(),
+ contentView.setDrawableParameters(R.id.icon, false, -1, resolveContrastColor(),
PorterDuff.Mode.SRC_ATOP, -1);
}
}
@@ -3460,11 +3471,14 @@ public class Notification implements Parcelable
}
}
- int resolveColor() {
- if (mN.color == COLOR_DEFAULT) {
- return mContext.getColor(R.color.notification_icon_default_color);
+ int resolveContrastColor() {
+ if (mCachedContrastColorIsFor == mN.color && mCachedContrastColor != COLOR_INVALID) {
+ return mCachedContrastColor;
}
- return mN.color;
+ final int contrasted = NotificationColorUtil.resolveContrastColor(mContext, mN.color);
+
+ mCachedContrastColorIsFor = mN.color;
+ return mCachedContrastColor = contrasted;
}
/**
@@ -4427,7 +4441,7 @@ public class Notification implements Parcelable
final Action action = mBuilder.mActions.get(mActionsToShowInCompact[i]);
final RemoteViews button = generateMediaActionButton(action,
- mBuilder.resolveColor());
+ mBuilder.resolveContrastColor());
view.addView(com.android.internal.R.id.media_actions, button);
}
}
@@ -4460,7 +4474,7 @@ public class Notification implements Parcelable
big.removeAllViews(com.android.internal.R.id.media_actions);
for (int i = 0; i < actionCount; i++) {
final RemoteViews button = generateMediaActionButton(mBuilder.mActions.get(i),
- mBuilder.resolveColor());
+ mBuilder.resolveContrastColor());
big.addView(com.android.internal.R.id.media_actions, button);
}
}
diff --git a/core/java/android/app/SystemServiceRegistry.java b/core/java/android/app/SystemServiceRegistry.java
index 9d7f7246a25d..2987fbc4f33d 100644
--- a/core/java/android/app/SystemServiceRegistry.java
+++ b/core/java/android/app/SystemServiceRegistry.java
@@ -69,6 +69,7 @@ import android.media.soundtrigger.SoundTriggerManager;
import android.media.tv.ITvInputManager;
import android.media.tv.TvInputManager;
import android.net.ConnectivityManager;
+import android.net.ConnectivityThread;
import android.net.EthernetManager;
import android.net.IConnectivityManager;
import android.net.IEthernetManager;
@@ -500,7 +501,8 @@ final class SystemServiceRegistry {
public WifiManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.WIFI_SERVICE);
IWifiManager service = IWifiManager.Stub.asInterface(b);
- return new WifiManager(ctx.getOuterContext(), service);
+ return new WifiManager(ctx.getOuterContext(), service,
+ ConnectivityThread.getInstanceLooper());
}});
registerService(Context.WIFI_P2P_SERVICE, WifiP2pManager.class,
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 52e52728c25a..b52af2762fed 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -726,6 +726,38 @@ public class WallpaperManager {
}
/**
+ * Get the ID of the current wallpaper of the given kind. If there is no
+ * such wallpaper configured, returns a negative number.
+ *
+ * @param which The wallpaper whose ID is to be returned. Must be a single
+ * defined kind of wallpaper, either {@link #FLAG_SET_SYSTEM} or
+ * {@link #FLAG_SET_LOCK}.
+ * @return The positive numeric ID of the current wallpaper of the given kind,
+ * or a negative value if no such wallpaper is configured.
+ */
+ public int getWallpaperId(int which) {
+ return getWallpaperIdForUser(which, mContext.getUserId());
+ }
+
+ /**
+ * Get the ID of the given user's current wallpaper of the given kind. If there
+ * is no such wallpaper configured, returns a negative number.
+ * @hide
+ */
+ public int getWallpaperIdForUser(int which, int userId) {
+ try {
+ if (sGlobals.mService == null) {
+ Log.w(TAG, "WallpaperService not running");
+ return -1;
+ } else {
+ return sGlobals.mService.getWallpaperIdForUser(which, userId);
+ }
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
+
+ /**
* Gets an Intent that will launch an activity that crops the given
* image and sets the device's wallpaper. If there is a default HOME activity
* that supports cropping wallpapers, it will be preferred as the default.
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index fe5c45f21ede..e7427bfabe01 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -145,19 +145,23 @@ public class DevicePolicyManager {
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME} instead, although specifying only
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} is still supported.
*
- * <p> The intent may also contain the following extras:
+ * <p>The intent may also contain the following extras:
* <ul>
- * <li> {@link #EXTRA_PROVISIONING_LOGO_URI}, optional </li>
- * <li> {@link #EXTRA_PROVISIONING_MAIN_COLOR}, optional </li>
+ * <li>{@link #EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE}, optional </li>
+ * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional, supported from
+ * {@link android.os.Build.VERSION_CODES#N}</li>
+ * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_LOGO_URI}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_MAIN_COLOR}, optional</li>
* </ul>
*
- * <p> When managed provisioning has completed, broadcasts are sent to the application specified
+ * <p>When managed provisioning has completed, broadcasts are sent to the application specified
* in the provisioning intent. The
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} broadcast is sent in the
* managed profile and the {@link #ACTION_MANAGED_PROFILE_PROVISIONED} broadcast is sent in
* the primary profile.
*
- * <p> If provisioning fails, the managedProfile is removed so the device returns to its
+ * <p>If provisioning fails, the managedProfile is removed so the device returns to its
* previous state.
*
* <p>If launched with {@link android.app.Activity#startActivityForResult(Intent, int)} a
@@ -171,7 +175,6 @@ public class DevicePolicyManager {
= "android.app.action.PROVISION_MANAGED_PROFILE";
/**
- * @hide
* Activity action: Starts the provisioning flow which sets up a managed user.
*
* <p>This intent will typically be sent by a mobile device management application (MDM).
@@ -180,16 +183,24 @@ public class DevicePolicyManager {
* been completed. Use {@link #isProvisioningAllowed(String)} to check if provisioning is
* allowed.
*
- * <p>This intent should contain the extra
- * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}.
+ * <p>The intent contains the following extras:
+ * <ul>
+ * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
+ * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_LOGO_URI}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_MAIN_COLOR}, optional</li>
+ * </ul>
*
- * <p> If provisioning fails, the device returns to its previous state.
+ * <p>If provisioning fails, the device returns to its previous state.
*
* <p>If launched with {@link android.app.Activity#startActivityForResult(Intent, int)} a
* result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part of
* the provisioning flow was successful, although this doesn't guarantee the full flow will
* succeed. Conversely a result code of {@link android.app.Activity#RESULT_CANCELED} implies
* that the user backed-out of provisioning, or some precondition for provisioning wasn't met.
+ *
+ * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_PROVISION_MANAGED_USER
@@ -220,11 +231,11 @@ public class DevicePolicyManager {
* <li>{@link #EXTRA_PROVISIONING_MAIN_COLOR}, optional</li>
* </ul>
*
- * <p> When device owner provisioning has completed, an intent of the type
+ * <p>When device owner provisioning has completed, an intent of the type
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcast to the
* device owner.
*
- * <p> If provisioning fails, the device is factory reset.
+ * <p>If provisioning fails, the device is factory reset.
*
* <p>A result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part
* of the provisioning flow was successful, although this doesn't guarantee the full flow will
@@ -288,14 +299,14 @@ public class DevicePolicyManager {
* The primary benefit is that multiple non-system users are supported when provisioning using
* this form of device management.
*
- * <p> During device owner provisioning a device admin app is set as the owner of the device.
+ * <p>During device owner provisioning a device admin app is set as the owner of the device.
* A device owner has full control over the device. The device owner can not be modified by the
* user.
*
- * <p> A typical use case would be a device that is owned by a company, but used by either an
+ * <p>A typical use case would be a device that is owned by a company, but used by either an
* employee or client.
*
- * <p> An intent with this action can be sent only on an unprovisioned device.
+ * <p>An intent with this action can be sent only on an unprovisioned device.
* It is possible to check if provisioning is allowed or not by querying the method
* {@link #isProvisioningAllowed(String)}.
*
@@ -305,13 +316,15 @@ public class DevicePolicyManager {
* <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}, optional</li>
* <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_LOGO_URI}, optional</li>
+ * <li>{@link #EXTRA_PROVISIONING_MAIN_COLOR}, optional</li>
* </ul>
*
- * <p> When device owner provisioning has completed, an intent of the type
+ * <p>When device owner provisioning has completed, an intent of the type
* {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE} is broadcast to the
* device owner.
*
- * <p> If provisioning fails, the device is factory reset.
+ * <p>If provisioning fails, the device is factory reset.
*
* <p>A result code of {@link android.app.Activity#RESULT_OK} implies that the synchronous part
* of the provisioning flow was successful, although this doesn't guarantee the full flow will
@@ -439,7 +452,7 @@ public class DevicePolicyManager {
*
* <p> When this extra is set, the application must have exactly one device admin receiver.
* This receiver will be set as the profile or device owner and active admin.
-
+ *
* @see DeviceAdminReceiver
* @deprecated Use {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}. This extra is still
* supported, but only if there is only one device admin receiver in the package that requires
@@ -461,7 +474,7 @@ public class DevicePolicyManager {
* <p>This component is set as device owner and active admin when device owner provisioning is
* started by an intent with action {@link #ACTION_PROVISION_MANAGED_DEVICE} or by an NFC
* message containing an NFC record with MIME type
- * {@link #MIME_TYPE_PROVISIONING_NFC}. For the NFC record, the component name should be
+ * {@link #MIME_TYPE_PROVISIONING_NFC}. For the NFC record, the component name must be
* flattened to a string, via {@link ComponentName#flattenToShortString()}.
*
* @see DeviceAdminReceiver
@@ -664,8 +677,8 @@ public class DevicePolicyManager {
* the file at download location specified in
* {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
*
- * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM} should be
- * present. The provided checksum should match the checksum of the file at the download
+ * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM} must be
+ * present. The provided checksum must match the checksum of the file at the download
* location. If the checksum doesn't match an error will be shown to the user and the user will
* be asked to factory reset the device.
*
@@ -689,8 +702,8 @@ public class DevicePolicyManager {
* {@link android.content.pm.PackageManager#getPackageArchiveInfo} with flag
* {@link android.content.pm.PackageManager#GET_SIGNATURES}.
*
- * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM} should be
- * present. The provided checksum should match the checksum of any signature of the file at
+ * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM} must be
+ * present. The provided checksum must match the checksum of any signature of the file at
* the download location. If the checksum does not match an error will be shown to the user and
* the user will be asked to factory reset the device.
*
@@ -715,11 +728,14 @@ public class DevicePolicyManager {
= "android.app.action.MANAGED_PROFILE_PROVISIONED";
/**
- * A boolean extra indicating whether device encryption can be skipped as part of Device Owner
- * provisioning.
+ * A boolean extra indicating whether device encryption can be skipped as part of device owner
+ * or managed profile provisioning.
*
* <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} or an intent with action
* {@link #ACTION_PROVISION_MANAGED_DEVICE} that starts device owner provisioning.
+ *
+ * <p>From {@link android.os.Build.VERSION_CODES#N} onwards, this is also supported for an
+ * intent with action {@link #ACTION_PROVISION_MANAGED_PROFILE}.
*/
public static final String EXTRA_PROVISIONING_SKIP_ENCRYPTION =
"android.app.extra.PROVISIONING_SKIP_ENCRYPTION";
@@ -762,7 +778,7 @@ public class DevicePolicyManager {
"android.app.extra.PROVISIONING_SKIP_USER_SETUP";
/**
- * This MIME type is used for starting the Device Owner provisioning.
+ * This MIME type is used for starting the device owner provisioning.
*
* <p>During device owner provisioning a device admin app is set as the owner of the device.
* A device owner has full control over the device. The device owner can not be modified by the
@@ -772,7 +788,7 @@ public class DevicePolicyManager {
* <p> A typical use case would be a device that is owned by a company, but used by either an
* employee or client.
*
- * <p> The NFC message should be send to an unprovisioned device.
+ * <p> The NFC message must be sent to an unprovisioned device.
*
* <p>The NFC record must contain a serialized {@link java.util.Properties} object which
* contains the following properties:
@@ -5814,14 +5830,6 @@ public class DevicePolicyManager {
}
/**
- * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
- * @hide
- */
- public void setDeviceLoggingEnabled(@NonNull ComponentName admin, boolean enabled) {
- setSecurityLoggingEnabled(admin, enabled);
- }
-
- /**
* Return whether security logging is enabled or not by the device owner.
*
* <p>Can only be called by the device owner, otherwise a {@link SecurityException} will be
@@ -5840,14 +5848,6 @@ public class DevicePolicyManager {
}
/**
- * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
- * @hide
- */
- public boolean getDeviceLoggingEnabled(@NonNull ComponentName admin) {
- return isSecurityLoggingEnabled(admin);
- }
-
- /**
* Called by device owner to retrieve all new security logging entries since the last call to
* this API after device boots.
*
@@ -5877,14 +5877,6 @@ public class DevicePolicyManager {
}
/**
- * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
- * @hide
- */
- public List<SecurityEvent> retrieveDeviceLogs(@NonNull ComponentName admin) {
- return retrieveSecurityLogs(admin);
- }
-
- /**
* Called by the system to obtain a {@link DevicePolicyManager} whose calls act on the parent
* profile.
*
@@ -5925,14 +5917,6 @@ public class DevicePolicyManager {
}
/**
- * Temporary // STOPSHIP TODO(mkarpinski): remove those once change to TestDPC is pushed
- * @hide
- */
- public List<SecurityEvent> retrievePreviousDeviceLogs(@NonNull ComponentName admin) {
- return retrievePreRebootSecurityLogs(admin);
- }
-
- /**
* Called by a profile owner of a managed profile to set the color used for customization. This
* color is used as background color of the confirm credentials screen for that user. The
* default color is {@link android.graphics.Color#GRAY}.
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index ea2dca08fd47..68442ea40701 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -197,109 +197,43 @@ public final class BluetoothGatt implements BluetoothProfile {
}
/**
- * A new GATT service has been discovered.
- * The service is added to the internal list and the search
- * continues.
- * @hide
- */
- public void onGetService(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid) {
- if (VDBG) Log.d(TAG, "onGetService() - Device=" + address + " UUID=" + srvcUuid);
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
- mServices.add(new BluetoothGattService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType));
- }
-
- /**
- * An included service has been found durig GATT discovery.
- * The included service is added to the respective parent.
- * @hide
- */
- public void onGetIncludedService(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int inclSrvcType, int inclSrvcInstId,
- ParcelUuid inclSrvcUuid) {
- if (VDBG) Log.d(TAG, "onGetIncludedService() - Device=" + address
- + " UUID=" + srvcUuid + " Included=" + inclSrvcUuid);
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
- BluetoothGattService service = getService(mDevice,
- srvcUuid.getUuid(), srvcInstId, srvcType);
- BluetoothGattService includedService = getService(mDevice,
- inclSrvcUuid.getUuid(), inclSrvcInstId, inclSrvcType);
-
- if (service != null && includedService != null) {
- service.addIncludedService(includedService);
- }
- }
-
- /**
- * A new GATT characteristic has been discovered.
- * Add the new characteristic to the relevant service and continue
- * the remote device inspection.
- * @hide
- */
- public void onGetCharacteristic(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int charProps) {
- if (VDBG) Log.d(TAG, "onGetCharacteristic() - Device=" + address + " UUID=" +
- charUuid);
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
- BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType);
- if (service != null) {
- service.addCharacteristic(new BluetoothGattCharacteristic(
- service, charUuid.getUuid(), charInstId, charProps, 0));
- }
- }
-
- /**
- * A new GATT descriptor has been discovered.
- * Finally, add the descriptor to the related characteristic.
- * This should conclude the remote device update.
- * @hide
- */
- public void onGetDescriptor(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int descrInstId, ParcelUuid descUuid) {
- if (VDBG) Log.d(TAG, "onGetDescriptor() - Device=" + address + " UUID=" + descUuid);
-
- if (!address.equals(mDevice.getAddress())) {
- return;
- }
- BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType);
- if (service == null) return;
-
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid.getUuid(), charInstId);
- if (characteristic == null) return;
-
- characteristic.addDescriptor(new BluetoothGattDescriptor(
- characteristic, descUuid.getUuid(), descrInstId, 0));
- }
-
- /**
* Remote search has been completed.
* The internal object structure should now reflect the state
* of the remote device database. Let the application know that
* we are done at this point.
* @hide
*/
- public void onSearchComplete(String address, int status) {
+ public void onSearchComplete(String address, List<BluetoothGattService> services,
+ int status) {
if (DBG) Log.d(TAG, "onSearchComplete() = Device=" + address + " Status=" + status);
if (!address.equals(mDevice.getAddress())) {
return;
}
+
+ for (BluetoothGattService s : services) {
+ //services we receive don't have device set properly.
+ s.setDevice(mDevice);
+ }
+
+ mServices.addAll(services);
+
+ // Fix references to included services, as they doesn't point to right objects.
+ for (BluetoothGattService fixedService : mServices) {
+ ArrayList<BluetoothGattService> includedServices =
+ new ArrayList(fixedService.getIncludedServices());
+ fixedService.getIncludedServices().clear();
+
+ for(BluetoothGattService brokenRef : includedServices) {
+ BluetoothGattService includedService = getService(mDevice,
+ brokenRef.getUuid(), brokenRef.getInstanceId(), brokenRef.getType());
+ if (includedService != null) {
+ fixedService.addIncludedService(includedService);
+ } else {
+ Log.e(TAG, "Broken GATT database: can't find included service.");
+ }
+ }
+ }
+
try {
mCallback.onServicesDiscovered(BluetoothGatt.this, status);
} catch (Exception ex) {
@@ -312,11 +246,12 @@ public final class BluetoothGatt implements BluetoothProfile {
* Updates the internal value.
* @hide
*/
- public void onCharacteristicRead(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid, byte[] value) {
+ public void onCharacteristicRead(String address, int status, int handle, byte[] value) {
if (VDBG) Log.d(TAG, "onCharacteristicRead() - Device=" + address
- + " UUID=" + charUuid + " Status=" + status);
+ + " handle=" + handle + " Status=" + status);
+
+ Log.w(TAG, "onCharacteristicRead() - Device=" + address
+ + " handle=" + handle + " Status=" + status);
if (!address.equals(mDevice.getAddress())) {
return;
@@ -331,9 +266,7 @@ public final class BluetoothGatt implements BluetoothProfile {
&& mAuthRetry == false) {
try {
mAuthRetry = true;
- mService.readCharacteristic(mClientIf, address,
- srvcType, srvcInstId, srvcUuid,
- charInstId, charUuid, AUTHENTICATION_MITM);
+ mService.readCharacteristic(mClientIf, address, handle, AUTHENTICATION_MITM);
return;
} catch (RemoteException e) {
Log.e(TAG,"",e);
@@ -342,13 +275,11 @@ public final class BluetoothGatt implements BluetoothProfile {
mAuthRetry = false;
- BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType);
- if (service == null) return;
-
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid.getUuid(), charInstId);
- if (characteristic == null) return;
+ BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
+ if (characteristic == null) {
+ Log.w(TAG, "onCharacteristicRead() failed to find characteristic!");
+ return;
+ }
if (status == 0) characteristic.setValue(value);
@@ -364,11 +295,9 @@ public final class BluetoothGatt implements BluetoothProfile {
* Let the app know how we did...
* @hide
*/
- public void onCharacteristicWrite(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid) {
+ public void onCharacteristicWrite(String address, int status, int handle) {
if (VDBG) Log.d(TAG, "onCharacteristicWrite() - Device=" + address
- + " UUID=" + charUuid + " Status=" + status);
+ + " handle=" + handle + " Status=" + status);
if (!address.equals(mDevice.getAddress())) {
return;
@@ -378,12 +307,7 @@ public final class BluetoothGatt implements BluetoothProfile {
mDeviceBusy = false;
}
- BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType);
- if (service == null) return;
-
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid.getUuid(), charInstId);
+ BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
if (characteristic == null) return;
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
@@ -391,8 +315,7 @@ public final class BluetoothGatt implements BluetoothProfile {
&& mAuthRetry == false) {
try {
mAuthRetry = true;
- mService.writeCharacteristic(mClientIf, address,
- srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
+ mService.writeCharacteristic(mClientIf, address, handle,
characteristic.getWriteType(), AUTHENTICATION_MITM,
characteristic.getValue());
return;
@@ -415,21 +338,14 @@ public final class BluetoothGatt implements BluetoothProfile {
* Updates the internal value.
* @hide
*/
- public void onNotify(String address, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- byte[] value) {
- if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " UUID=" + charUuid);
+ public void onNotify(String address, int handle, byte[] value) {
+ if (VDBG) Log.d(TAG, "onNotify() - Device=" + address + " handle=" + handle);
if (!address.equals(mDevice.getAddress())) {
return;
}
- BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType);
- if (service == null) return;
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid.getUuid(), charInstId);
+ BluetoothGattCharacteristic characteristic = getCharacteristicById(mDevice, handle);
if (characteristic == null) return;
characteristic.setValue(value);
@@ -445,12 +361,8 @@ public final class BluetoothGatt implements BluetoothProfile {
* Descriptor has been read.
* @hide
*/
- public void onDescriptorRead(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int descrInstId, ParcelUuid descrUuid,
- byte[] value) {
- if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " UUID=" + charUuid);
+ public void onDescriptorRead(String address, int status, int handle, byte[] value) {
+ if (VDBG) Log.d(TAG, "onDescriptorRead() - Device=" + address + " handle=" + handle);
if (!address.equals(mDevice.getAddress())) {
return;
@@ -460,16 +372,7 @@ public final class BluetoothGatt implements BluetoothProfile {
mDeviceBusy = false;
}
- BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType);
- if (service == null) return;
-
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid.getUuid(), charInstId);
- if (characteristic == null) return;
-
- BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
- descrUuid.getUuid(), descrInstId);
+ BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
if (descriptor == null) return;
if (status == 0) descriptor.setValue(value);
@@ -479,9 +382,7 @@ public final class BluetoothGatt implements BluetoothProfile {
&& mAuthRetry == false) {
try {
mAuthRetry = true;
- mService.readDescriptor(mClientIf, address,
- srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
- descrInstId, descrUuid, AUTHENTICATION_MITM);
+ mService.readDescriptor(mClientIf, address, handle, AUTHENTICATION_MITM);
return;
} catch (RemoteException e) {
Log.e(TAG,"",e);
@@ -501,11 +402,8 @@ public final class BluetoothGatt implements BluetoothProfile {
* Descriptor write operation complete.
* @hide
*/
- public void onDescriptorWrite(String address, int status, int srvcType,
- int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid,
- int descrInstId, ParcelUuid descrUuid) {
- if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " UUID=" + charUuid);
+ public void onDescriptorWrite(String address, int status, int handle) {
+ if (VDBG) Log.d(TAG, "onDescriptorWrite() - Device=" + address + " handle=" + handle);
if (!address.equals(mDevice.getAddress())) {
return;
@@ -515,16 +413,7 @@ public final class BluetoothGatt implements BluetoothProfile {
mDeviceBusy = false;
}
- BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
- srvcInstId, srvcType);
- if (service == null) return;
-
- BluetoothGattCharacteristic characteristic = service.getCharacteristic(
- charUuid.getUuid(), charInstId);
- if (characteristic == null) return;
-
- BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
- descrUuid.getUuid(), descrInstId);
+ BluetoothGattDescriptor descriptor = getDescriptorById(mDevice, handle);
if (descriptor == null) return;
if ((status == GATT_INSUFFICIENT_AUTHENTICATION
@@ -532,9 +421,8 @@ public final class BluetoothGatt implements BluetoothProfile {
&& mAuthRetry == false) {
try {
mAuthRetry = true;
- mService.writeDescriptor(mClientIf, address,
- srvcType, srvcInstId, srvcUuid, charInstId, charUuid,
- descrInstId, descrUuid, characteristic.getWriteType(),
+ mService.writeDescriptor(mClientIf, address, handle,
+ descriptor.getCharacteristic().getWriteType(),
AUTHENTICATION_MITM, descriptor.getValue());
return;
} catch (RemoteException e) {
@@ -651,6 +539,37 @@ public final class BluetoothGatt implements BluetoothProfile {
/**
+ * Returns a characteristic with id equal to instanceId.
+ * @hide
+ */
+ /*package*/ BluetoothGattCharacteristic getCharacteristicById(BluetoothDevice device, int instanceId) {
+ for(BluetoothGattService svc : mServices) {
+ for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
+ Log.w(TAG, "getCharacteristicById() comparing " + charac.getInstanceId() + " and " + instanceId);
+ if (charac.getInstanceId() == instanceId)
+ return charac;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns a descriptor with id equal to instanceId.
+ * @hide
+ */
+ /*package*/ BluetoothGattDescriptor getDescriptorById(BluetoothDevice device, int instanceId) {
+ for(BluetoothGattService svc : mServices) {
+ for(BluetoothGattCharacteristic charac : svc.getCharacteristics()) {
+ for(BluetoothGattDescriptor desc : charac.getDescriptors()) {
+ if (desc.getInstanceId() == instanceId)
+ return desc;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
* Register an application callback to start using GATT.
*
* <p>This is an asynchronous call. The callback {@link BluetoothGattCallback#onAppRegistered}
@@ -898,9 +817,7 @@ public final class BluetoothGatt implements BluetoothProfile {
try {
mService.readCharacteristic(mClientIf, device.getAddress(),
- service.getType(), service.getInstanceId(),
- new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
- new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
+ characteristic.getInstanceId(), AUTHENTICATION_NONE);
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
@@ -943,11 +860,8 @@ public final class BluetoothGatt implements BluetoothProfile {
try {
mService.writeCharacteristic(mClientIf, device.getAddress(),
- service.getType(), service.getInstanceId(),
- new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
- new ParcelUuid(characteristic.getUuid()),
- characteristic.getWriteType(), AUTHENTICATION_NONE,
- characteristic.getValue());
+ characteristic.getInstanceId(), characteristic.getWriteType(),
+ AUTHENTICATION_NONE, characteristic.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
@@ -988,11 +902,8 @@ public final class BluetoothGatt implements BluetoothProfile {
}
try {
- mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
- service.getInstanceId(), new ParcelUuid(service.getUuid()),
- characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
- descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
- AUTHENTICATION_NONE);
+ mService.readDescriptor(mClientIf, device.getAddress(),
+ descriptor.getInstanceId(), AUTHENTICATION_NONE);
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
@@ -1032,12 +943,8 @@ public final class BluetoothGatt implements BluetoothProfile {
}
try {
- mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
- service.getInstanceId(), new ParcelUuid(service.getUuid()),
- characteristic.getInstanceId(), new ParcelUuid(characteristic.getUuid()),
- descriptor.getInstanceId(), new ParcelUuid(descriptor.getUuid()),
- characteristic.getWriteType(), AUTHENTICATION_NONE,
- descriptor.getValue());
+ mService.writeDescriptor(mClientIf, device.getAddress(), descriptor.getInstanceId(),
+ characteristic.getWriteType(), AUTHENTICATION_NONE, descriptor.getValue());
} catch (RemoteException e) {
Log.e(TAG,"",e);
mDeviceBusy = false;
@@ -1168,10 +1075,7 @@ public final class BluetoothGatt implements BluetoothProfile {
try {
mService.registerForNotification(mClientIf, device.getAddress(),
- service.getType(), service.getInstanceId(),
- new ParcelUuid(service.getUuid()), characteristic.getInstanceId(),
- new ParcelUuid(characteristic.getUuid()),
- enable);
+ characteristic.getInstanceId(), enable);
} catch (RemoteException e) {
Log.e(TAG,"",e);
return false;
diff --git a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
index 01778b3dc40e..17e533a5b32f 100644
--- a/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
+++ b/core/java/android/bluetooth/BluetoothGattCallbackWrapper.java
@@ -18,6 +18,7 @@ package android.bluetooth;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.ScanResult;
+import android.bluetooth.BluetoothGattService;
import android.os.ParcelUuid;
import android.os.RemoteException;
@@ -48,41 +49,17 @@ public class BluetoothGattCallbackWrapper extends IBluetoothGattCallback.Stub {
}
@Override
- public void onGetService(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid)
- throws RemoteException {
- }
-
- @Override
- public void onGetIncludedService(String address, int srvcType, int srvcInstId,
- ParcelUuid srvcUuid, int inclSrvcType, int inclSrvcInstId, ParcelUuid inclSrvcUuid)
- throws RemoteException {
- }
-
- @Override
- public void onGetCharacteristic(String address, int srvcType, int srvcInstId,
- ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int charProps)
- throws RemoteException {
- }
-
- @Override
- public void onGetDescriptor(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid, int descrInstId, ParcelUuid descrUuid)
- throws RemoteException {
- }
-
- @Override
- public void onSearchComplete(String address, int status) throws RemoteException {
+ public void onSearchComplete(String address, List<BluetoothGattService> services,
+ int status) throws RemoteException {
}
@Override
- public void onCharacteristicRead(String address, int status, int srvcType, int srvcInstId,
- ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, byte[] value)
+ public void onCharacteristicRead(String address, int status, int handle, byte[] value)
throws RemoteException {
}
@Override
- public void onCharacteristicWrite(String address, int status, int srvcType, int srvcInstId,
- ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid) throws RemoteException {
+ public void onCharacteristicWrite(String address, int status, int handle) throws RemoteException {
}
@Override
@@ -90,20 +67,15 @@ public class BluetoothGattCallbackWrapper extends IBluetoothGattCallback.Stub {
}
@Override
- public void onDescriptorRead(String address, int status, int srvcType, int srvcInstId,
- ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId,
- ParcelUuid descrUuid, byte[] value) throws RemoteException {
+ public void onDescriptorRead(String address, int status, int handle, byte[] value) throws RemoteException {
}
@Override
- public void onDescriptorWrite(String address, int status, int srvcType, int srvcInstId,
- ParcelUuid srvcUuid, int charInstId, ParcelUuid charUuid, int descrInstId,
- ParcelUuid descrUuid) throws RemoteException {
+ public void onDescriptorWrite(String address, int status, int handle) throws RemoteException {
}
@Override
- public void onNotify(String address, int srvcType, int srvcInstId, ParcelUuid srvcUuid,
- int charInstId, ParcelUuid charUuid, byte[] value) throws RemoteException {
+ public void onNotify(String address, int handle, byte[] value) throws RemoteException {
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ClearHistoryEvent.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.aidl
index 98c0a69cae01..bbb8623e2178 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ClearHistoryEvent.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.aidl
@@ -14,13 +14,6 @@
* limitations under the License.
*/
-package com.android.systemui.recents.events.activity;
+package android.bluetooth;
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the history is to be cleared
- */
-public class ClearHistoryEvent extends EventBus.AnimatedEvent {
- // Simple event
-}
+parcelable BluetoothGattCharacteristic;
diff --git a/core/java/android/bluetooth/BluetoothGattCharacteristic.java b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
index 7cdcc2c9b9ff..7d698b3ef5a6 100644
--- a/core/java/android/bluetooth/BluetoothGattCharacteristic.java
+++ b/core/java/android/bluetooth/BluetoothGattCharacteristic.java
@@ -15,6 +15,9 @@
*/
package android.bluetooth;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelUuid;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -26,7 +29,7 @@ import java.util.UUID;
* {@link BluetoothGattService}. The characteristic contains a value as well as
* additional information and optional GATT descriptors, {@link BluetoothGattDescriptor}.
*/
-public class BluetoothGattCharacteristic {
+public class BluetoothGattCharacteristic implements Parcelable {
/**
* Characteristic proprty: Characteristic is broadcastable.
@@ -242,6 +245,15 @@ public class BluetoothGattCharacteristic {
initCharacteristic(service, uuid, instanceId, properties, permissions);
}
+ /**
+ * Create a new BluetoothGattCharacteristic
+ * @hide
+ */
+ public BluetoothGattCharacteristic(UUID uuid, int instanceId,
+ int properties, int permissions) {
+ initCharacteristic(null, uuid, instanceId, properties, permissions);
+ }
+
private void initCharacteristic(BluetoothGattService service,
UUID uuid, int instanceId,
int properties, int permissions) {
@@ -261,6 +273,50 @@ public class BluetoothGattCharacteristic {
}
/**
+ * @hide
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(new ParcelUuid(mUuid), 0);
+ out.writeInt(mInstance);
+ out.writeInt(mProperties);
+ out.writeInt(mPermissions);
+ out.writeTypedList(mDescriptors);
+ }
+
+ public static final Parcelable.Creator<BluetoothGattCharacteristic> CREATOR
+ = new Parcelable.Creator<BluetoothGattCharacteristic>() {
+ public BluetoothGattCharacteristic createFromParcel(Parcel in) {
+ return new BluetoothGattCharacteristic(in);
+ }
+
+ public BluetoothGattCharacteristic[] newArray(int size) {
+ return new BluetoothGattCharacteristic[size];
+ }
+ };
+
+ private BluetoothGattCharacteristic(Parcel in) {
+ mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid();
+ mInstance = in.readInt();
+ mProperties = in.readInt();
+ mPermissions = in.readInt();
+
+ mDescriptors = new ArrayList<BluetoothGattDescriptor>();
+
+ ArrayList<BluetoothGattDescriptor> descs =
+ in.createTypedArrayList(BluetoothGattDescriptor.CREATOR);
+ if (descs != null) {
+ for (BluetoothGattDescriptor desc: descs) {
+ desc.setCharacteristic(this);
+ mDescriptors.add(desc);
+ }
+ }
+ }
+
+ /**
* Returns the deisred key size.
* @hide
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java b/core/java/android/bluetooth/BluetoothGattDescriptor.aidl
index aaf77afb20f9..439327331671 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ToggleHistoryEvent.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.aidl
@@ -14,15 +14,6 @@
* limitations under the License.
*/
-package com.android.systemui.recents.events.activity;
+package android.bluetooth;
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the history view button is clicked.
- */
-public class ToggleHistoryEvent extends EventBus.AnimatedEvent {
-
- // Simple event
-
-}
+parcelable BluetoothGattDescriptor;
diff --git a/core/java/android/bluetooth/BluetoothGattDescriptor.java b/core/java/android/bluetooth/BluetoothGattDescriptor.java
index 5f525dc609a0..28317c49604f 100644
--- a/core/java/android/bluetooth/BluetoothGattDescriptor.java
+++ b/core/java/android/bluetooth/BluetoothGattDescriptor.java
@@ -16,6 +16,9 @@
package android.bluetooth;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelUuid;
import java.util.UUID;
/**
@@ -25,7 +28,7 @@ import java.util.UUID;
* characteristic, {@link BluetoothGattCharacteristic}. They can be used to describe
* the characteristic's features or to control certain behaviours of the characteristic.
*/
-public class BluetoothGattDescriptor {
+public class BluetoothGattDescriptor implements Parcelable {
/**
* Value used to enable notification for a client configuration descriptor
@@ -138,6 +141,13 @@ public class BluetoothGattDescriptor {
initDescriptor(characteristic, uuid, instance, permissions);
}
+ /**
+ * @hide
+ */
+ public BluetoothGattDescriptor(UUID uuid, int instance, int permissions) {
+ initDescriptor(null, uuid, instance, permissions);
+ }
+
private void initDescriptor(BluetoothGattCharacteristic characteristic, UUID uuid,
int instance, int permissions) {
mCharacteristic = characteristic;
@@ -147,6 +157,36 @@ public class BluetoothGattDescriptor {
}
/**
+ * @hide
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(new ParcelUuid(mUuid), 0);
+ out.writeInt(mInstance);
+ out.writeInt(mPermissions);
+ }
+
+ public static final Parcelable.Creator<BluetoothGattDescriptor> CREATOR
+ = new Parcelable.Creator<BluetoothGattDescriptor>() {
+ public BluetoothGattDescriptor createFromParcel(Parcel in) {
+ return new BluetoothGattDescriptor(in);
+ }
+
+ public BluetoothGattDescriptor[] newArray(int size) {
+ return new BluetoothGattDescriptor[size];
+ }
+ };
+
+ private BluetoothGattDescriptor(Parcel in) {
+ mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid();
+ mInstance = in.readInt();
+ mPermissions = in.readInt();
+ }
+
+ /**
* Returns the characteristic this descriptor belongs to.
* @return The characteristic.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryButtonEvent.java b/core/java/android/bluetooth/BluetoothGattIncludedService.aidl
index 6c767e414450..1ef427edc3a0 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryButtonEvent.java
+++ b/core/java/android/bluetooth/BluetoothGattIncludedService.aidl
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2015 The Android Open Source Project
+ * 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.
@@ -14,13 +14,6 @@
* limitations under the License.
*/
-package com.android.systemui.recents.events.activity;
+package android.bluetooth;
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the history view button should be hidden.
- */
-public class HideHistoryButtonEvent extends EventBus.Event {
- // Simple event
-}
+parcelable BluetoothGattIncludedService;
diff --git a/core/java/android/bluetooth/BluetoothGattIncludedService.java b/core/java/android/bluetooth/BluetoothGattIncludedService.java
new file mode 100644
index 000000000000..155dc571d230
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothGattIncludedService.java
@@ -0,0 +1,110 @@
+/*
+ * 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.
+ */
+package android.bluetooth;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelUuid;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Represents a Bluetooth GATT Included Service
+ * @hide
+ */
+public class BluetoothGattIncludedService implements Parcelable {
+
+ /**
+ * The UUID of this service.
+ */
+ protected UUID mUuid;
+
+ /**
+ * Instance ID for this service.
+ */
+ protected int mInstanceId;
+
+ /**
+ * Service type (Primary/Secondary).
+ */
+ protected int mServiceType;
+
+ /**
+ * Create a new BluetoothGattIncludedService
+ */
+ public BluetoothGattIncludedService(UUID uuid, int instanceId, int serviceType) {
+ mUuid = uuid;
+ mInstanceId = instanceId;
+ mServiceType = serviceType;
+ }
+
+ public int describeContents() {
+ return 0;
+ }
+
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(new ParcelUuid(mUuid), 0);
+ out.writeInt(mInstanceId);
+ out.writeInt(mServiceType);
+ }
+
+ public static final Parcelable.Creator<BluetoothGattIncludedService> CREATOR
+ = new Parcelable.Creator<BluetoothGattIncludedService>() {
+ public BluetoothGattIncludedService createFromParcel(Parcel in) {
+ return new BluetoothGattIncludedService(in);
+ }
+
+ public BluetoothGattIncludedService[] newArray(int size) {
+ return new BluetoothGattIncludedService[size];
+ }
+ };
+
+ private BluetoothGattIncludedService(Parcel in) {
+ mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid();
+ mInstanceId = in.readInt();
+ mServiceType = in.readInt();
+ }
+
+ /**
+ * Returns the UUID of this service
+ *
+ * @return UUID of this service
+ */
+ public UUID getUuid() {
+ return mUuid;
+ }
+
+ /**
+ * Returns the instance ID for this service
+ *
+ * <p>If a remote device offers multiple services with the same UUID
+ * (ex. multiple battery services for different batteries), the instance
+ * ID is used to distuinguish services.
+ *
+ * @return Instance ID of this service
+ */
+ public int getInstanceId() {
+ return mInstanceId;
+ }
+
+ /**
+ * Get the type of this service (primary/secondary)
+ */
+ public int getType() {
+ return mServiceType;
+ }
+}
diff --git a/core/java/android/bluetooth/BluetoothGattService.aidl b/core/java/android/bluetooth/BluetoothGattService.aidl
new file mode 100644
index 000000000000..84314d2072df
--- /dev/null
+++ b/core/java/android/bluetooth/BluetoothGattService.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+package android.bluetooth;
+
+parcelable BluetoothGattService;
diff --git a/core/java/android/bluetooth/BluetoothGattService.java b/core/java/android/bluetooth/BluetoothGattService.java
index 52bc0f796cb5..a4e1dc01d002 100644
--- a/core/java/android/bluetooth/BluetoothGattService.java
+++ b/core/java/android/bluetooth/BluetoothGattService.java
@@ -15,6 +15,9 @@
*/
package android.bluetooth;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.os.ParcelUuid;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
@@ -25,7 +28,7 @@ import java.util.UUID;
* <p> Gatt Service contains a collection of {@link BluetoothGattCharacteristic},
* as well as referenced services.
*/
-public class BluetoothGattService {
+public class BluetoothGattService implements Parcelable {
/**
* Primary service
@@ -117,6 +120,81 @@ public class BluetoothGattService {
}
/**
+ * Create a new BluetoothGattService
+ * @hide
+ */
+ public BluetoothGattService(UUID uuid, int instanceId, int serviceType) {
+ mDevice = null;
+ mUuid = uuid;
+ mInstanceId = instanceId;
+ mServiceType = serviceType;
+ mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
+ mIncludedServices = new ArrayList<BluetoothGattService>();
+ }
+
+ /**
+ * @hide
+ */
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel out, int flags) {
+ out.writeParcelable(new ParcelUuid(mUuid), 0);
+ out.writeInt(mInstanceId);
+ out.writeInt(mServiceType);
+ out.writeTypedList(mCharacteristics);
+
+ ArrayList<BluetoothGattIncludedService> includedServices =
+ new ArrayList<BluetoothGattIncludedService>(mIncludedServices.size());
+ for(BluetoothGattService s : mIncludedServices) {
+ includedServices.add(new BluetoothGattIncludedService(s.getUuid(),
+ s.getInstanceId(), s.getType()));
+ }
+ out.writeTypedList(includedServices);
+ }
+
+ public static final Parcelable.Creator<BluetoothGattService> CREATOR
+ = new Parcelable.Creator<BluetoothGattService>() {
+ public BluetoothGattService createFromParcel(Parcel in) {
+ return new BluetoothGattService(in);
+ }
+
+ public BluetoothGattService[] newArray(int size) {
+ return new BluetoothGattService[size];
+ }
+ };
+
+ private BluetoothGattService(Parcel in) {
+ mUuid = ((ParcelUuid)in.readParcelable(null)).getUuid();
+ mInstanceId = in.readInt();
+ mServiceType = in.readInt();
+
+ mCharacteristics = new ArrayList<BluetoothGattCharacteristic>();
+
+ ArrayList<BluetoothGattCharacteristic> chrcs =
+ in.createTypedArrayList(BluetoothGattCharacteristic.CREATOR);
+ if (chrcs != null) {
+ for (BluetoothGattCharacteristic chrc : chrcs) {
+ chrc.setService(this);
+ mCharacteristics.add(chrc);
+ }
+ }
+
+ mIncludedServices = new ArrayList<BluetoothGattService>();
+
+ ArrayList<BluetoothGattIncludedService> inclSvcs =
+ in.createTypedArrayList(BluetoothGattIncludedService.CREATOR);
+ if (chrcs != null) {
+ for (BluetoothGattIncludedService isvc : inclSvcs) {
+ mIncludedServices.add(new BluetoothGattService(null, isvc.getUuid(),
+ isvc.getInstanceId(), isvc.getType()));
+ }
+ }
+ }
+
+ /**
* Returns the device associated with this service.
* @hide
*/
@@ -125,6 +203,14 @@ public class BluetoothGattService {
}
/**
+ * Returns the device associated with this service.
+ * @hide
+ */
+ /*package*/ void setDevice(BluetoothDevice device) {
+ this.mDevice = device;
+ }
+
+ /**
* Add an included service to this service.
* <p>Requires {@link android.Manifest.permission#BLUETOOTH} permission.
*
@@ -192,7 +278,7 @@ public class BluetoothGattService {
* Add an included service to the internal map.
* @hide
*/
- /*package*/ void addIncludedService(BluetoothGattService includedService) {
+ public void addIncludedService(BluetoothGattService includedService) {
mIncludedServices.add(includedService);
}
diff --git a/core/java/android/bluetooth/IBluetoothGatt.aidl b/core/java/android/bluetooth/IBluetoothGatt.aidl
index 6b5f77faacd3..adb07df29770 100644
--- a/core/java/android/bluetooth/IBluetoothGatt.aidl
+++ b/core/java/android/bluetooth/IBluetoothGatt.aidl
@@ -51,28 +51,13 @@ interface IBluetoothGatt {
void clientDisconnect(in int clientIf, in String address);
void refreshDevice(in int clientIf, in String address);
void discoverServices(in int clientIf, in String address);
- void readCharacteristic(in int clientIf, in String address, in int srvcType,
- in int srvcInstanceId, in ParcelUuid srvcId,
- in int charInstanceId, in ParcelUuid charId,
- in int authReq);
- void writeCharacteristic(in int clientIf, in String address, in int srvcType,
- in int srvcInstanceId, in ParcelUuid srvcId,
- in int charInstanceId, in ParcelUuid charId,
+ void readCharacteristic(in int clientIf, in String address, in int handle, in int authReq);
+ void writeCharacteristic(in int clientIf, in String address, in int handle,
in int writeType, in int authReq, in byte[] value);
- void readDescriptor(in int clientIf, in String address, in int srvcType,
- in int srvcInstanceId, in ParcelUuid srvcId,
- in int charInstanceId, in ParcelUuid charId,
- in int descrInstanceId, in ParcelUuid descrUuid,
- in int authReq);
- void writeDescriptor(in int clientIf, in String address, in int srvcType,
- in int srvcInstanceId, in ParcelUuid srvcId,
- in int charInstanceId, in ParcelUuid charId,
- in int descrInstanceId, in ParcelUuid descrId,
+ void readDescriptor(in int clientIf, in String address, in int handle, in int authReq);
+ void writeDescriptor(in int clientIf, in String address, in int handle,
in int writeType, in int authReq, in byte[] value);
- void registerForNotification(in int clientIf, in String address, in int srvcType,
- in int srvcInstanceId, in ParcelUuid srvcId,
- in int charInstanceId, in ParcelUuid charId,
- in boolean enable);
+ void registerForNotification(in int clientIf, in String address, in int handle, in boolean enable);
void beginReliableWrite(in int clientIf, in String address);
void endReliableWrite(in int clientIf, in String address, in boolean execute);
void readRemoteRssi(in int clientIf, in String address);
diff --git a/core/java/android/bluetooth/IBluetoothGattCallback.aidl b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
index cbba9f021423..7163c370694c 100644
--- a/core/java/android/bluetooth/IBluetoothGattCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothGattCallback.aidl
@@ -16,6 +16,7 @@
package android.bluetooth;
import android.os.ParcelUuid;
+import android.bluetooth.BluetoothGattService;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.ScanResult;
@@ -29,41 +30,13 @@ oneway interface IBluetoothGattCallback {
in boolean connected, in String address);
void onScanResult(in ScanResult scanResult);
void onBatchScanResults(in List<ScanResult> batchResults);
- void onGetService(in String address, in int srvcType, in int srvcInstId,
- in ParcelUuid srvcUuid);
- void onGetIncludedService(in String address, in int srvcType, in int srvcInstId,
- in ParcelUuid srvcUuid, in int inclSrvcType,
- in int inclSrvcInstId, in ParcelUuid inclSrvcUuid);
- void onGetCharacteristic(in String address, in int srvcType,
- in int srvcInstId, in ParcelUuid srvcUuid,
- in int charInstId, in ParcelUuid charUuid,
- in int charProps);
- void onGetDescriptor(in String address, in int srvcType,
- in int srvcInstId, in ParcelUuid srvcUuid,
- in int charInstId, in ParcelUuid charUuid,
- in int descrInstId, in ParcelUuid descrUuid);
- void onSearchComplete(in String address, in int status);
- void onCharacteristicRead(in String address, in int status, in int srvcType,
- in int srvcInstId, in ParcelUuid srvcUuid,
- in int charInstId, in ParcelUuid charUuid,
- in byte[] value);
- void onCharacteristicWrite(in String address, in int status, in int srvcType,
- in int srvcInstId, in ParcelUuid srvcUuid,
- in int charInstId, in ParcelUuid charUuid);
+ void onSearchComplete(in String address, in List<BluetoothGattService> services, in int status);
+ void onCharacteristicRead(in String address, in int status, in int handle, in byte[] value);
+ void onCharacteristicWrite(in String address, in int status, in int handle);
void onExecuteWrite(in String address, in int status);
- void onDescriptorRead(in String address, in int status, in int srvcType,
- in int srvcInstId, in ParcelUuid srvcUuid,
- in int charInstId, in ParcelUuid charUuid,
- in int descrInstId, in ParcelUuid descrUuid,
- in byte[] value);
- void onDescriptorWrite(in String address, in int status, in int srvcType,
- in int srvcInstId, in ParcelUuid srvcUuid,
- in int charInstId, in ParcelUuid charUuid,
- in int descrInstId, in ParcelUuid descrUuid);
- void onNotify(in String address, in int srvcType,
- in int srvcInstId, in ParcelUuid srvcUuid,
- in int charInstId, in ParcelUuid charUuid,
- in byte[] value);
+ void onDescriptorRead(in String address, in int status, in int handle, in byte[] value);
+ void onDescriptorWrite(in String address, in int status, in int handle);
+ void onNotify(in String address, in int handle, in byte[] value);
void onReadRemoteRssi(in String address, in int rssi, in int status);
void onMultiAdvertiseCallback(in int status, boolean isStart,
in AdvertiseSettings advertiseSettings);
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index dabc6524b20f..e3fb161cf0ab 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -454,8 +454,21 @@ interface IPackageManager {
*/
boolean performDexOptIfNeeded(String packageName, String instructionSet);
- boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles,
- boolean extractOnly, boolean force);
+ /**
+ * Ask the package manager to perform a dex-opt for the given reason. The package
+ * manager will map the reason to a compiler filter according to the current system
+ * configuration.
+ */
+ boolean performDexOpt(String packageName, String instructionSet, boolean checkProfiles,
+ int compileReason, boolean force);
+ /**
+ * Ask the package manager to perform a dex-opt with the given compiler filter.
+ *
+ * Note: exposed only for the shell command to allow moving packages explicitly to a
+ * definite state.
+ */
+ boolean performDexOptMode(String packageName, String instructionSet, boolean checkProfiles,
+ String targetCompilerFilter, boolean force);
void forceDexOpt(String packageName);
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index 3139151b78a0..e8a3438dd974 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -216,6 +216,7 @@ public class UserInfo implements Parcelable {
lastLoggedInTime = orig.lastLoggedInTime;
partial = orig.partial;
profileGroupId = orig.profileGroupId;
+ restrictedProfileParentId = orig.restrictedProfileParentId;
guestToRemove = orig.guestToRemove;
}
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 841e5b0c9732..63ee8d2e75d3 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -652,6 +652,14 @@ public final class Sensor {
public static final int TYPE_ALL = -1;
+ /**
+ * The lowest sensor type vendor defined sensors can use.
+ *
+ * All vendor sensor types are greater than or equal to this constant.
+ *
+ */
+ public static final int TYPE_DEVICE_PRIVATE_BASE = 0x10000;
+
// If this flag is set, the sensor defined as a wake up sensor. This field and REPORTING_MODE_*
// constants are defined as flags in sensors.h. Modify at both places if needed.
private static final int SENSOR_FLAG_WAKE_UP_SENSOR = 1;
diff --git a/core/java/android/hardware/usb/UsbManager.java b/core/java/android/hardware/usb/UsbManager.java
index 3792e5c03756..f9a7d192b5bb 100644
--- a/core/java/android/hardware/usb/UsbManager.java
+++ b/core/java/android/hardware/usb/UsbManager.java
@@ -54,6 +54,8 @@ public class UsbManager {
* This is a sticky broadcast for clients that includes USB connected/disconnected state,
* <ul>
* <li> {@link #USB_CONNECTED} boolean indicating whether USB is connected or disconnected.
+ * <li> {@link #USB_HOST_CONNECTED} boolean indicating whether USB is connected or
+ * disconnected as host.
* <li> {@link #USB_CONFIGURED} boolean indicating whether USB is configured.
* currently zero if not configured, one for configured.
* <li> {@link #USB_FUNCTION_ADB} boolean extra indicating whether the
@@ -152,6 +154,14 @@ public class UsbManager {
public static final String USB_CONNECTED = "connected";
/**
+ * Boolean extra indicating whether USB is connected or disconnected as host.
+ * Used in extras for the {@link #ACTION_USB_STATE} broadcast.
+ *
+ * {@hide}
+ */
+ public static final String USB_HOST_CONNECTED = "host_connected";
+
+ /**
* Boolean extra indicating whether USB is configured.
* Used in extras for the {@link #ACTION_USB_STATE} broadcast.
*
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 5f1043ba8f1c..f0673fffc0d8 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -2744,7 +2744,9 @@ public class ConnectivityManager {
if (networkCallback == null) {
throw new IllegalArgumentException("null NetworkCallback");
}
- if (need == null) throw new IllegalArgumentException("null NetworkCapabilities");
+ if (need == null && action != REQUEST) {
+ throw new IllegalArgumentException("null NetworkCapabilities");
+ }
try {
incCallbackHandlerRefCount();
synchronized(sNetworkCallback) {
@@ -2767,7 +2769,7 @@ public class ConnectivityManager {
}
/**
- * Helper function to requests a network with a particular legacy type.
+ * Helper function to request a network with a particular legacy type.
*
* This is temporarily public @hide so it can be called by system code that uses the
* NetworkRequest API to request networks but relies on CONNECTIVITY_ACTION broadcasts for
@@ -3011,6 +3013,28 @@ public class ConnectivityManager {
}
/**
+ * Registers to receive notifications about whichever network currently satisfies the
+ * system default {@link NetworkRequest}. The callbacks will continue to be called until
+ * either the application exits or {@link #unregisterNetworkCallback} is called
+ * <p>This method requires the caller to hold the permission
+ * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.
+ *
+ * @param networkCallback The {@link NetworkCallback} that the system will call as the
+ * system default network changes.
+ * @hide
+ */
+ public void registerDefaultNetworkCallback(NetworkCallback networkCallback) {
+ // This works because if the NetworkCapabilities are null,
+ // ConnectivityService takes them from the default request.
+ //
+ // Since the capabilities are exactly the same as the default request's
+ // capabilities, this request is guaranteed, at all times, to be
+ // satisfied by the same network, if any, that satisfies the default
+ // request, i.e., the system default network.
+ sendRequestForNetwork(null, networkCallback, 0, REQUEST, TYPE_NONE);
+ }
+
+ /**
* Requests bandwidth update for a given {@link Network} and returns whether the update request
* is accepted by ConnectivityService. Once accepted, ConnectivityService will poll underlying
* network connection for updated bandwidth information. The caller will be notified via
diff --git a/core/java/android/net/ConnectivityThread.java b/core/java/android/net/ConnectivityThread.java
new file mode 100644
index 000000000000..55c3402bf39d
--- /dev/null
+++ b/core/java/android/net/ConnectivityThread.java
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+
+package android.net;
+
+import android.os.HandlerThread;
+import android.os.Looper;
+
+/**
+ * Shared singleton connectivity thread for the system. This is a thread for
+ * connectivity operations such as AsyncChannel connections to system services.
+ * Various connectivity manager objects can use this singleton as a common
+ * resource for their handlers instead of creating separate threads of their own.
+ * @hide
+ */
+public final class ConnectivityThread extends HandlerThread {
+ private static ConnectivityThread sInstance;
+
+ private ConnectivityThread() {
+ super("ConnectivityThread");
+ }
+
+ private static synchronized ConnectivityThread getInstance() {
+ if (sInstance == null) {
+ sInstance = new ConnectivityThread();
+ sInstance.start();
+ }
+ return sInstance;
+ }
+
+ public static ConnectivityThread get() {
+ return getInstance();
+ }
+
+ public static Looper getInstanceLooper() {
+ return getInstance().getLooper();
+ }
+}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index e27c0fb2ddea..641861459426 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -248,7 +248,7 @@ public final class NetworkCapabilities implements Parcelable {
* for a network to satisfy a request, all capabilities requested must be satisfied.
*
* @param capability the {@code NetworkCapabilities.NET_CAPABILITY_*} to be added.
- * @return This NetworkCapability to facilitate chaining.
+ * @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
public NetworkCapabilities addCapability(int capability) {
@@ -263,7 +263,7 @@ public final class NetworkCapabilities implements Parcelable {
* Removes (if found) the given capability from this {@code NetworkCapability} instance.
*
* @param capability the {@code NetworkCapabilities.NET_CAPABILTIY_*} to be removed.
- * @return This NetworkCapability to facilitate chaining.
+ * @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
public NetworkCapabilities removeCapability(int capability) {
@@ -418,7 +418,7 @@ public final class NetworkCapabilities implements Parcelable {
* {@code NetworkCapabilities.NET_CAPABILITY_*} listed above.
*
* @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be added.
- * @return This NetworkCapability to facilitate chaining.
+ * @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
public NetworkCapabilities addTransportType(int transportType) {
@@ -434,7 +434,7 @@ public final class NetworkCapabilities implements Parcelable {
* Removes (if found) the given transport from this {@code NetworkCapability} instance.
*
* @param transportType the {@code NetworkCapabilities.TRANSPORT_*} to be removed.
- * @return This NetworkCapability to facilitate chaining.
+ * @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
public NetworkCapabilities removeTransportType(int transportType) {
@@ -578,14 +578,16 @@ public final class NetworkCapabilities implements Parcelable {
* @param networkSpecifier An {@code String} of opaque format used to specify the bearer
* specific network specifier where the bearer has a choice of
* networks.
+ * @return This NetworkCapabilities instance, to facilitate chaining.
* @hide
*/
- public void setNetworkSpecifier(String networkSpecifier) {
+ public NetworkCapabilities setNetworkSpecifier(String networkSpecifier) {
if (TextUtils.isEmpty(networkSpecifier) == false && Long.bitCount(mTransportTypes) != 1) {
throw new IllegalStateException("Must have a single transport specified to use " +
"setNetworkSpecifier");
}
mNetworkSpecifier = networkSpecifier;
+ return this;
}
/**
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 555032d522bf..141af3d49563 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -39,23 +39,6 @@ public class NetworkUtils {
private static final String TAG = "NetworkUtils";
- /** Setting bit 0 indicates reseting of IPv4 addresses required */
- public static final int RESET_IPV4_ADDRESSES = 0x01;
-
- /** Setting bit 1 indicates reseting of IPv4 addresses required */
- public static final int RESET_IPV6_ADDRESSES = 0x02;
-
- /** Reset all addresses */
- public static final int RESET_ALL_ADDRESSES = RESET_IPV4_ADDRESSES | RESET_IPV6_ADDRESSES;
-
- /**
- * Reset IPv6 or IPv4 sockets that are connected via the named interface.
- *
- * @param interfaceName is the interface to reset
- * @param mask {@see #RESET_IPV4_ADDRESSES} and {@see #RESET_IPV6_ADDRESSES}
- */
- public native static int resetConnections(String interfaceName, int mask);
-
/**
* Attaches a socket filter that accepts DHCP packets to the given socket.
*/
diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java
index 95ffb44d22e5..cfd0468a6e27 100644
--- a/core/java/android/net/TrafficStats.java
+++ b/core/java/android/net/TrafficStats.java
@@ -147,8 +147,10 @@ public class TrafficStats {
}
/**
- * System API for backup-related support components to tag network traffic
- * appropriately.
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. The tag used internally is well-defined to
+ * distinguish all backup-related traffic.
+ *
* @hide
*/
@SystemApi
@@ -157,8 +159,10 @@ public class TrafficStats {
}
/**
- * System API for restore-related support components to tag network traffic
- * appropriately.
+ * Set active tag to use when accounting {@link Socket} traffic originating
+ * from the current thread. The tag used internally is well-defined to
+ * distinguish all restore-related traffic.
+ *
* @hide
*/
@SystemApi
@@ -205,7 +209,13 @@ public class TrafficStats {
NetworkManagementSocketTagger.setThreadSocketStatsUid(uid);
}
- /** {@hide} */
+ /**
+ * Clear any active UID set to account {@link Socket} traffic originating
+ * from the current thread.
+ *
+ * @see #setThreadStatsUid(int)
+ * @hide
+ */
@SystemApi
public static void clearThreadStatsUid() {
NetworkManagementSocketTagger.setThreadSocketStatsUid(-1);
diff --git a/core/java/android/os/Debug.java b/core/java/android/os/Debug.java
index f3822413add3..55b107a215e4 100644
--- a/core/java/android/os/Debug.java
+++ b/core/java/android/os/Debug.java
@@ -19,8 +19,11 @@ package android.os;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.TypedProperties;
+import android.app.AppGlobals;
+import android.content.Context;
import android.util.Log;
+import java.io.File;
import java.io.FileDescriptor;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -100,14 +103,6 @@ public final class Debug
*/
private static final String DEFAULT_TRACE_BODY = "dmtrace";
private static final String DEFAULT_TRACE_EXTENSION = ".trace";
- private static class NoPreloadHolder {
- private static final String DEFAULT_TRACE_PATH_PREFIX =
- Environment.getLegacyExternalStorageDirectory().getPath() + "/";
- private static final String DEFAULT_TRACE_FILE_PATH =
- DEFAULT_TRACE_PATH_PREFIX + DEFAULT_TRACE_BODY
- + DEFAULT_TRACE_EXTENSION;
- }
-
/**
* This class is used to retrieved various statistics about the memory mappings for this
@@ -938,109 +933,171 @@ public final class Debug
}
/**
- * Start method tracing with default log name and buffer size. See <a
-href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading these files. Call stopMethodTracing() to stop
- * tracing.
+ * Start method tracing with default log name and buffer size.
+ * <p>
+ * By default, the trace file is called "dmtrace.trace" and it's placed
+ * under your package-specific directory on primary shared/external storage,
+ * as returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
+ * </p>
*/
public static void startMethodTracing() {
- VMDebug.startMethodTracing(fixTraceName(null), 0, 0, false, 0);
+ VMDebug.startMethodTracing(fixTracePath(null), 0, 0, false, 0);
}
/**
- * Start method tracing, specifying the trace log file name. The trace
- * file will be put under "/sdcard" unless an absolute path is given.
- * See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
+ * Start method tracing, specifying the trace log file path.
+ * <p>
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
+ * </p>
*
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
*/
- public static void startMethodTracing(String traceName) {
- startMethodTracing(traceName, 0, 0);
+ public static void startMethodTracing(String tracePath) {
+ startMethodTracing(tracePath, 0, 0);
}
/**
- * Start method tracing, specifying the trace log file name and the
- * buffer size. The trace files will be put under "/sdcard" unless an
- * absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
+ * Start method tracing, specifying the trace log file name and the buffer
+ * size.
+ * <p>
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
+ * </p>
*
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
+ * @param bufferSize The maximum amount of trace data we gather. If not
+ * given, it defaults to 8MB.
*/
- public static void startMethodTracing(String traceName, int bufferSize) {
- startMethodTracing(traceName, bufferSize, 0);
+ public static void startMethodTracing(String tracePath, int bufferSize) {
+ startMethodTracing(tracePath, bufferSize, 0);
}
/**
- * Start method tracing, specifying the trace log file name and the
- * buffer size. The trace files will be put under "/sdcard" unless an
- * absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a> for
- * information about reading trace files.
- *
+ * Start method tracing, specifying the trace log file name, the buffer
+ * size, and flags.
+ * <p>
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
* <p>
- * When method tracing is enabled, the VM will run more slowly than
- * usual, so the timings from the trace files should only be considered
- * in relative terms (e.g. was run #1 faster than run #2). The times
- * for native methods will not change, so don't try to use this to
- * compare the performance of interpreted and native implementations of the
- * same method. As an alternative, consider using sampling-based method
- * tracing via {@link #startMethodTracingSampling(String, int, int)} or
- * "native" tracing in the emulator via {@link #startNativeTracing()}.
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
+ * <p class="note">
+ * When method tracing is enabled, the VM will run more slowly than usual,
+ * so the timings from the trace files should only be considered in relative
+ * terms (e.g. was run #1 faster than run #2). The times for native methods
+ * will not change, so don't try to use this to compare the performance of
+ * interpreted and native implementations of the same method. As an
+ * alternative, consider using sampling-based method tracing via
+ * {@link #startMethodTracingSampling(String, int, int)} or "native" tracing
+ * in the emulator via {@link #startNativeTracing()}.
* </p>
*
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
- * @param flags Flags to control method tracing. The only one that is currently defined is {@link #TRACE_COUNT_ALLOCS}.
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
+ * @param bufferSize The maximum amount of trace data we gather. If not
+ * given, it defaults to 8MB.
+ * @param flags Flags to control method tracing. The only one that is
+ * currently defined is {@link #TRACE_COUNT_ALLOCS}.
*/
- public static void startMethodTracing(String traceName, int bufferSize,
- int flags) {
- VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, flags, false, 0);
+ public static void startMethodTracing(String tracePath, int bufferSize, int flags) {
+ VMDebug.startMethodTracing(fixTracePath(tracePath), bufferSize, flags, false, 0);
}
/**
* Start sampling-based method tracing, specifying the trace log file name,
- * the buffer size, and the sampling interval. The trace files will be put
- * under "/sdcard" unless an absolute path is given. See <a
- href="{@docRoot}guide/developing/tools/traceview.html">Traceview: A Graphical Log Viewer</a>
- * for information about reading trace files.
+ * the buffer size, and the sampling interval.
+ * <p>
+ * When a relative file path is given, the trace file will be placed under
+ * your package-specific directory on primary shared/external storage, as
+ * returned by {@link Context#getExternalFilesDir(String)}.
+ * <p>
+ * See <a href="{@docRoot}guide/developing/tools/traceview.html">Traceview:
+ * A Graphical Log Viewer</a> for information about reading trace files.
*
- * @param traceName Name for the trace log file to create.
- * If {@code traceName} is null, this value defaults to "/sdcard/dmtrace.trace".
- * If the files already exist, they will be truncated.
- * If the trace file given does not end in ".trace", it will be appended for you.
- * @param bufferSize The maximum amount of trace data we gather. If not given, it defaults to 8MB.
- * @param intervalUs The amount of time between each sample in microseconds.
+ * @param tracePath Path to the trace log file to create. If {@code null},
+ * this will default to "dmtrace.trace". If the file already
+ * exists, it will be truncated. If the path given does not end
+ * in ".trace", it will be appended for you.
+ * @param bufferSize The maximum amount of trace data we gather. If not
+ * given, it defaults to 8MB.
+ * @param intervalUs The amount of time between each sample in microseconds.
*/
- public static void startMethodTracingSampling(String traceName,
- int bufferSize, int intervalUs) {
- VMDebug.startMethodTracing(fixTraceName(traceName), bufferSize, 0, true, intervalUs);
+ public static void startMethodTracingSampling(String tracePath, int bufferSize,
+ int intervalUs) {
+ VMDebug.startMethodTracing(fixTracePath(tracePath), bufferSize, 0, true, intervalUs);
}
-
+
/**
* Formats name of trace log file for method tracing.
*/
- private static String fixTraceName(String traceName) {
- if (traceName == null)
- traceName = NoPreloadHolder.DEFAULT_TRACE_FILE_PATH;
- if (traceName.charAt(0) != '/')
- traceName = NoPreloadHolder.DEFAULT_TRACE_PATH_PREFIX + traceName;
- if (!traceName.endsWith(DEFAULT_TRACE_EXTENSION))
- traceName = traceName + DEFAULT_TRACE_EXTENSION;
+ private static String fixTracePath(String tracePath) {
+ if (tracePath == null || tracePath.charAt(0) != '/') {
+ final Context context = AppGlobals.getInitialApplication();
+ final File dir;
+ if (context != null) {
+ dir = context.getExternalFilesDir(null);
+ } else {
+ dir = Environment.getExternalStorageDirectory();
+ }
- return traceName;
+ if (tracePath == null) {
+ tracePath = new File(dir, DEFAULT_TRACE_BODY).getAbsolutePath();
+ } else {
+ tracePath = new File(dir, tracePath).getAbsolutePath();
+ }
+ }
+ if (!tracePath.endsWith(DEFAULT_TRACE_EXTENSION)) {
+ tracePath += DEFAULT_TRACE_EXTENSION;
+ }
+ return tracePath;
}
/**
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index cd84c8fbc9e4..100f6a165b1d 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -97,12 +97,6 @@ interface INetworkManagementService
void setInterfaceIpv6NdOffload(String iface, boolean enable);
/**
- * Retrieves the network routes currently configured on the specified
- * interface
- */
- RouteInfo[] getRoutes(String iface);
-
- /**
* Add the specified route to the interface.
*/
void addRoute(int netId, in RouteInfo route);
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index bc2566b0ef64..c38bf3c74852 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -76,4 +76,5 @@ interface IUserManager {
PersistableBundle getSeedAccountOptions();
void clearSeedAccountData();
boolean someUserHasSeedAccount(in String accountName, in String accountType);
+ boolean isManagedProfile(int userId);
}
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 0ff0154f2ed0..707d5f561ac2 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -822,8 +822,28 @@ public class UserManager {
*/
@SystemApi
public boolean isManagedProfile() {
- UserInfo user = getUserInfo(UserHandle.myUserId());
- return user != null ? user.isManagedProfile() : false;
+ try {
+ return mService.isManagedProfile(UserHandle.myUserId());
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Checks if the specified user is a managed profile.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission, otherwise the caller
+ * must be in the same profile group of specified user.
+ *
+ * @return whether the specified user is a managed profile.
+ * @hide
+ */
+ @SystemApi
+ public boolean isManagedProfile(@UserIdInt int userId) {
+ try {
+ return mService.isManagedProfile(userId);
+ } catch (RemoteException re) {
+ throw re.rethrowFromSystemServer();
+ }
}
/**
@@ -964,8 +984,7 @@ public class UserManager {
/**
* Returns the UserInfo object describing a specific user.
- * Requires {@link android.Manifest.permission#MANAGE_USERS} permission or the caller is
- * in the same profile group of target user.
+ * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
* @param userHandle the user handle of the user whose information is being requested.
* @return the UserInfo object for a specific user.
* @hide
diff --git a/core/java/android/os/storage/StorageVolume.java b/core/java/android/os/storage/StorageVolume.java
index 54d20d361a26..17176ecf1c7c 100644
--- a/core/java/android/os/storage/StorageVolume.java
+++ b/core/java/android/os/storage/StorageVolume.java
@@ -306,8 +306,8 @@ public final class StorageVolume implements Parcelable {
}
/**
- * Builds an intent to give access to a standard storage directory after obtaining the user's
- * approval.
+ * Builds an intent to give access to a standard storage directory or entire volume after
+ * obtaining the user's approval.
* <p>
* When invoked, the system will ask the user to grant access to the requested directory (and
* its descendants). The result of the request will be returned to the activity through the
@@ -322,12 +322,17 @@ public final class StorageVolume implements Parcelable {
* {@link Context#getExternalCacheDirs()}, or
* {@link Context#getExternalMediaDirs()}, which require no permissions to read or write.
*
+ * <strong>NOTE: </strong>requesting access to the entire volume is not recommended and it will
+ * result in a stronger message displayed to the user, which may cause the user to reject
+ * the request.
+ *
* @param directoryName must be one of
* {@link Environment#DIRECTORY_MUSIC}, {@link Environment#DIRECTORY_PODCASTS},
* {@link Environment#DIRECTORY_RINGTONES}, {@link Environment#DIRECTORY_ALARMS},
* {@link Environment#DIRECTORY_NOTIFICATIONS}, {@link Environment#DIRECTORY_PICTURES},
* {@link Environment#DIRECTORY_MOVIES}, {@link Environment#DIRECTORY_DOWNLOADS},
- * {@link Environment#DIRECTORY_DCIM}, or {@link Environment#DIRECTORY_DOCUMENTS}
+ * {@link Environment#DIRECTORY_DCIM}, or {@link Environment#DIRECTORY_DOCUMENTS}, or
+ * {code null} to request access to the entire volume.
*
* @see DocumentsContract
*/
diff --git a/core/java/android/os/storage/VolumeInfo.java b/core/java/android/os/storage/VolumeInfo.java
index ea0597d8c68c..4b706496db20 100644
--- a/core/java/android/os/storage/VolumeInfo.java
+++ b/core/java/android/os/storage/VolumeInfo.java
@@ -438,6 +438,10 @@ public class VolumeInfo implements Parcelable {
final Intent intent = new Intent(DocumentsContract.ACTION_BROWSE);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setData(uri);
+
+ // note that docsui treats this as *force* show advanced. So sending
+ // false permits advanced to be shown based on user preferences.
+ intent.putExtra(DocumentsContract.EXTRA_SHOW_ADVANCED, isPrimary());
intent.putExtra(DocumentsContract.EXTRA_SHOW_FILESIZE, true);
return intent;
}
diff --git a/core/java/android/provider/BlockedNumberContract.java b/core/java/android/provider/BlockedNumberContract.java
index b06d503a209d..6fe01899f144 100644
--- a/core/java/android/provider/BlockedNumberContract.java
+++ b/core/java/android/provider/BlockedNumberContract.java
@@ -68,7 +68,12 @@ import android.os.Bundle;
* Apps can optionally provide the {@link BlockedNumbers#COLUMN_E164_NUMBER} which is the phone
* number's E164 representation. The provider automatically populates this column if the app does
* not provide it. Note that this column is not populated if normalization fails or if the address
- * is not a phone number (eg: email). The provider enforces uniqueness constraint on this column.
+ * is not a phone number (eg: email).
+ * <p>
+ * Attempting to insert an existing blocked number (same
+ * {@link BlockedNumbers#COLUMN_ORIGINAL_NUMBER} column) will result in replacing the existing
+ * blocked number.
+ * <p>
* Examples:
* <pre>
* ContentValues values = new ContentValues();
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 4ad7969d1911..441245956b8d 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -93,6 +93,9 @@ public final class DocumentsContract {
public static final String EXTRA_PACKAGE_NAME = "android.content.extra.PACKAGE_NAME";
/** {@hide} */
+ public static final String EXTRA_SHOW_ADVANCED = "android.content.extra.SHOW_ADVANCED";
+
+ /** {@hide} */
public static final String EXTRA_SHOW_FILESIZE = "android.content.extra.SHOW_FILESIZE";
/** {@hide} */
@@ -556,13 +559,22 @@ public final class DocumentsContract {
public static final int FLAG_EMPTY = 1 << 16;
/**
+ * Flag indicating that this root should only be visible to advanced
+ * users.
+ *
+ * @see #COLUMN_FLAGS
+ * @hide
+ */
+ public static final int FLAG_ADVANCED = 1 << 17;
+
+ /**
* Flag indicating that this root has settings.
*
* @see #COLUMN_FLAGS
* @see DocumentsContract#ACTION_DOCUMENT_ROOT_SETTINGS
* @hide
*/
- public static final int FLAG_HAS_SETTINGS = 1 << 17;
+ public static final int FLAG_HAS_SETTINGS = 1 << 18;
/**
* Flag indicating that this root is on removable SD card storage.
@@ -570,7 +582,7 @@ public final class DocumentsContract {
* @see #COLUMN_FLAGS
* @hide
*/
- public static final int FLAG_REMOVABLE_SD = 1 << 18;
+ public static final int FLAG_REMOVABLE_SD = 1 << 19;
/**
* Flag indicating that this root is on removable USB storage.
@@ -578,7 +590,7 @@ public final class DocumentsContract {
* @see #COLUMN_FLAGS
* @hide
*/
- public static final int FLAG_REMOVABLE_USB = 1 << 19;
+ public static final int FLAG_REMOVABLE_USB = 1 << 20;
}
/**
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 5fc2899877f4..d8937b41eeae 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -517,21 +517,18 @@ public final class Settings {
"android.settings.USER_DICTIONARY_SETTINGS";
/**
- * Activity Action: Show settings to configure the hardware keyboard layout.
+ * Activity Action: Show settings to configure the hardware keyboard.
* <p>
* In some cases, a matching Activity may not exist, so ensure you
* safeguard against this.
* <p>
- *
- * @see android.hardware.input.InputManager#ACTION_QUERY_KEYBOARD_LAYOUTS
- * <p>
* Input: Nothing.
* <p>
* Output: Nothing.
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_KEYBOARD_LAYOUT_SETTINGS =
- "android.settings.KEYBOARD_LAYOUT_SETTINGS";
+ public static final String ACTION_HARD_KEYBOARD_SETTINGS =
+ "android.settings.HARD_KEYBOARD_SETTINGS";
/**
* Activity Action: Adds a word to the user dictionary.
diff --git a/core/java/android/provider/UserDictionary.java b/core/java/android/provider/UserDictionary.java
index a9b106ae7394..c6e58cbb0072 100644
--- a/core/java/android/provider/UserDictionary.java
+++ b/core/java/android/provider/UserDictionary.java
@@ -28,6 +28,9 @@ import android.text.TextUtils;
* A provider of user defined words for input methods to use for predictive text input.
* Applications and input methods may add words into the dictionary. Words can have associated
* frequency information and locale information.
+ *
+ * <p><strong>NOTE: </strong>Starting on API 23, the user dictionary is only accessible through
+ * IME and spellchecker.
*/
public class UserDictionary {
diff --git a/core/java/android/security/net/config/XmlConfigSource.java b/core/java/android/security/net/config/XmlConfigSource.java
index d57d0f561181..4a5f827da129 100644
--- a/core/java/android/security/net/config/XmlConfigSource.java
+++ b/core/java/android/security/net/config/XmlConfigSource.java
@@ -111,7 +111,7 @@ public class XmlConfigSource implements ConfigSource {
if (parser.next() != XmlPullParser.TEXT) {
throw new ParserException(parser, "Missing pin digest");
}
- String digest = parser.getText();
+ String digest = parser.getText().trim();
byte[] decodedDigest = null;
try {
decodedDigest = Base64.decode(digest, 0);
@@ -168,7 +168,7 @@ public class XmlConfigSource implements ConfigSource {
if (parser.next() != XmlPullParser.TEXT) {
throw new ParserException(parser, "Domain name missing");
}
- String domain = parser.getText().toLowerCase(Locale.US);
+ String domain = parser.getText().trim().toLowerCase(Locale.US);
if (parser.next() != XmlPullParser.END_TAG) {
throw new ParserException(parser, "domain contains additional elements");
}
diff --git a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
index dcf987bc3c12..d9227cea3b60 100644
--- a/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
+++ b/core/java/android/util/apk/ApkSignatureSchemeV2Verifier.java
@@ -16,17 +16,20 @@
package android.util.apk;
+import android.system.ErrnoException;
+import android.system.OsConstants;
+import android.util.ArrayMap;
import android.util.Pair;
import java.io.ByteArrayInputStream;
+import java.io.FileDescriptor;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.math.BigInteger;
import java.nio.BufferUnderflowException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
-import java.nio.MappedByteBuffer;
-import java.nio.channels.FileChannel;
+import java.nio.DirectByteBuffer;
import java.security.DigestException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
@@ -52,11 +55,13 @@ import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import libcore.io.Libcore;
+import libcore.io.Os;
+
/**
* APK Signature Scheme v2 verifier.
*
@@ -75,44 +80,17 @@ public class ApkSignatureSchemeV2Verifier {
public static final int SF_ATTRIBUTE_ANDROID_APK_SIGNED_ID = 2;
/**
- * Returns {@code true} if the provided APK contains an APK Signature Scheme V2
- * signature. The signature will not be verified.
+ * Returns {@code true} if the provided APK contains an APK Signature Scheme V2 signature.
+ *
+ * <p><b>NOTE: This method does not verify the signature.</b>
*/
public static boolean hasSignature(String apkFile) throws IOException {
try (RandomAccessFile apk = new RandomAccessFile(apkFile, "r")) {
- long fileSize = apk.length();
- if (fileSize > Integer.MAX_VALUE) {
- return false;
- }
- MappedByteBuffer apkContents;
- try {
- apkContents = apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
- } catch (IOException e) {
- if (e.getCause() instanceof OutOfMemoryError) {
- // TODO: Remove this temporary workaround once verifying large APKs is
- // supported. Very large APKs cannot be memory-mapped. This verification code
- // needs to change to use a different approach for verifying such APKs.
- return false; // Pretend that this APK does not have a v2 signature.
- } else {
- throw new IOException("Failed to memory-map APK", e);
- }
- }
- // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
- apkContents.order(ByteOrder.LITTLE_ENDIAN);
-
- final int centralDirOffset =
- (int) getCentralDirOffset(apkContents, getEocdOffset(apkContents));
- // Find the APK Signing Block.
- int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
- ByteBuffer apkSigningBlock =
- sliceFromTo(apkContents, apkSigningBlockOffset, centralDirOffset);
-
- // Find the APK Signature Scheme v2 Block inside the APK Signing Block.
- findApkSignatureSchemeV2Block(apkSigningBlock);
+ findSignature(apk);
return true;
} catch (SignatureNotFoundException e) {
+ return false;
}
- return false;
}
/**
@@ -135,90 +113,97 @@ public class ApkSignatureSchemeV2Verifier {
* associated with each signer.
*
* @throws SignatureNotFoundException if the APK is not signed using APK Signature Scheme v2.
- * @throws SecurityException if a APK Signature Scheme v2 signature of this APK does not verify.
+ * @throws SecurityException if an APK Signature Scheme v2 signature of this APK does not
+ * verify.
* @throws IOException if an I/O error occurs while reading the APK file.
*/
- public static X509Certificate[][] verify(RandomAccessFile apk)
+ private static X509Certificate[][] verify(RandomAccessFile apk)
throws SignatureNotFoundException, SecurityException, IOException {
+ SignatureInfo signatureInfo = findSignature(apk);
+ return verify(apk.getFD(), signatureInfo);
+ }
- long fileSize = apk.length();
- if (fileSize > Integer.MAX_VALUE) {
- throw new IOException("File too large: " + apk.length() + " bytes");
- }
- MappedByteBuffer apkContents;
- try {
- apkContents = apk.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, fileSize);
- // Attempt to preload the contents into memory for faster overall verification (v2 and
- // older) at the expense of somewhat increased latency for rejecting malformed APKs.
- apkContents.load();
- } catch (IOException e) {
- if (e.getCause() instanceof OutOfMemoryError) {
- // TODO: Remove this temporary workaround once verifying large APKs is supported.
- // Very large APKs cannot be memory-mapped. This verification code needs to change
- // to use a different approach for verifying such APKs.
- // This workaround pretends that this APK does not have a v2 signature. This works
- // fine provided the APK is not actually v2-signed. If the APK is v2 signed, v2
- // signature stripping protection inside v1 signature verification code will reject
- // this APK.
- throw new SignatureNotFoundException("Failed to memory-map APK", e);
- } else {
- throw new IOException("Failed to memory-map APK", e);
- }
+ /**
+ * APK Signature Scheme v2 block and additional information relevant to verifying the signatures
+ * contained in the block against the file.
+ */
+ private static class SignatureInfo {
+ /** Contents of APK Signature Scheme v2 block. */
+ private final ByteBuffer signatureBlock;
+
+ /** Position of the APK Signing Block in the file. */
+ private final long apkSigningBlockOffset;
+
+ /** Position of the ZIP Central Directory in the file. */
+ private final long centralDirOffset;
+
+ /** Position of the ZIP End of Central Directory (EoCD) in the file. */
+ private final long eocdOffset;
+
+ /** Contents of ZIP End of Central Directory (EoCD) of the file. */
+ private final ByteBuffer eocd;
+
+ private SignatureInfo(
+ ByteBuffer signatureBlock,
+ long apkSigningBlockOffset,
+ long centralDirOffset,
+ long eocdOffset,
+ ByteBuffer eocd) {
+ this.signatureBlock = signatureBlock;
+ this.apkSigningBlockOffset = apkSigningBlockOffset;
+ this.centralDirOffset = centralDirOffset;
+ this.eocdOffset = eocdOffset;
+ this.eocd = eocd;
}
- return verify(apkContents);
}
/**
- * Verifies APK Signature Scheme v2 signatures of the provided APK and returns the certificates
- * associated with each signer.
- *
- * @param apkContents contents of the APK. The contents start at the current position and end
- * at the limit of the buffer.
+ * Returns the APK Signature Scheme v2 block contained in the provided APK file and the
+ * additional information relevant for verifying the block against the file.
*
* @throws SignatureNotFoundException if the APK is not signed using APK Signature Scheme v2.
- * @throws SecurityException if a APK Signature Scheme v2 signature of this APK does not verify.
+ * @throws IOException if an I/O error occurs while reading the APK file.
*/
- public static X509Certificate[][] verify(ByteBuffer apkContents)
- throws SignatureNotFoundException, SecurityException {
- // Avoid modifying byte order, position, limit, and mark of the original apkContents.
- apkContents = apkContents.slice();
-
- // ZipUtils and APK Signature Scheme v2 verifier expect little-endian byte order.
- apkContents.order(ByteOrder.LITTLE_ENDIAN);
-
- final int eocdOffset = getEocdOffset(apkContents);
- final int centralDirOffset = (int) getCentralDirOffset(apkContents, eocdOffset);
+ private static SignatureInfo findSignature(RandomAccessFile apk)
+ throws IOException, SignatureNotFoundException {
+ // Find the ZIP End of Central Directory (EoCD) record.
+ Pair<ByteBuffer, Long> eocdAndOffsetInFile = getEocd(apk);
+ ByteBuffer eocd = eocdAndOffsetInFile.first;
+ long eocdOffset = eocdAndOffsetInFile.second;
+ if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apk, eocdOffset)) {
+ throw new SignatureNotFoundException("ZIP64 APK not supported");
+ }
- // Find the APK Signing Block.
- int apkSigningBlockOffset = findApkSigningBlock(apkContents, centralDirOffset);
- ByteBuffer apkSigningBlock =
- sliceFromTo(apkContents, apkSigningBlockOffset, centralDirOffset);
+ // Find the APK Signing Block. The block immediately precedes the Central Directory.
+ long centralDirOffset = getCentralDirOffset(eocd, eocdOffset);
+ Pair<ByteBuffer, Long> apkSigningBlockAndOffsetInFile =
+ findApkSigningBlock(apk, centralDirOffset);
+ ByteBuffer apkSigningBlock = apkSigningBlockAndOffsetInFile.first;
+ long apkSigningBlockOffset = apkSigningBlockAndOffsetInFile.second;
// Find the APK Signature Scheme v2 Block inside the APK Signing Block.
ByteBuffer apkSignatureSchemeV2Block = findApkSignatureSchemeV2Block(apkSigningBlock);
- // Verify the contents of the APK outside of the APK Signing Block using the APK Signature
- // Scheme v2 Block.
- return verify(
- apkContents,
+ return new SignatureInfo(
apkSignatureSchemeV2Block,
apkSigningBlockOffset,
centralDirOffset,
- eocdOffset);
+ eocdOffset,
+ eocd);
}
/**
- * Verifies the contents outside of the APK Signing Block using the provided APK Signature
- * Scheme v2 Block.
+ * Verifies the contents of the provided APK file against the provided APK Signature Scheme v2
+ * Block.
+ *
+ * @param signatureInfo APK Signature Scheme v2 Block and information relevant for verifying it
+ * against the APK file.
*/
private static X509Certificate[][] verify(
- ByteBuffer apkContents,
- ByteBuffer v2Block,
- int apkSigningBlockOffset,
- int centralDirOffset,
- int eocdOffset) throws SecurityException {
+ FileDescriptor apkFileDescriptor,
+ SignatureInfo signatureInfo) throws SecurityException {
int signerCount = 0;
- Map<Integer, byte[]> contentDigests = new HashMap<>();
+ Map<Integer, byte[]> contentDigests = new ArrayMap<>();
List<X509Certificate[]> signerCerts = new ArrayList<>();
CertificateFactory certFactory;
try {
@@ -228,7 +213,7 @@ public class ApkSignatureSchemeV2Verifier {
}
ByteBuffer signers;
try {
- signers = getLengthPrefixedSlice(v2Block);
+ signers = getLengthPrefixedSlice(signatureInfo.signatureBlock);
} catch (IOException e) {
throw new SecurityException("Failed to read list of signers", e);
}
@@ -255,10 +240,11 @@ public class ApkSignatureSchemeV2Verifier {
verifyIntegrity(
contentDigests,
- apkContents,
- apkSigningBlockOffset,
- centralDirOffset,
- eocdOffset);
+ apkFileDescriptor,
+ signatureInfo.apkSigningBlockOffset,
+ signatureInfo.centralDirOffset,
+ signatureInfo.eocdOffset,
+ signatureInfo.eocd);
return signerCerts.toArray(new X509Certificate[signerCerts.size()][]);
}
@@ -401,25 +387,38 @@ public class ApkSignatureSchemeV2Verifier {
private static void verifyIntegrity(
Map<Integer, byte[]> expectedDigests,
- ByteBuffer apkContents,
- int apkSigningBlockOffset,
- int centralDirOffset,
- int eocdOffset) throws SecurityException {
+ FileDescriptor apkFileDescriptor,
+ long apkSigningBlockOffset,
+ long centralDirOffset,
+ long eocdOffset,
+ ByteBuffer eocdBuf) throws SecurityException {
if (expectedDigests.isEmpty()) {
throw new SecurityException("No digests provided");
}
- ByteBuffer beforeApkSigningBlock = sliceFromTo(apkContents, 0, apkSigningBlockOffset);
- ByteBuffer centralDir = sliceFromTo(apkContents, centralDirOffset, eocdOffset);
+ // We need to verify the integrity of the following three sections of the file:
+ // 1. Everything up to the start of the APK Signing Block.
+ // 2. ZIP Central Directory.
+ // 3. ZIP End of Central Directory (EoCD).
+ // Each of these sections is represented as a separate DataSource instance below.
+
+ // To handle large APKs, these sections are read in 1 MB chunks using memory-mapped I/O to
+ // avoid wasting physical memory. In most APK verification scenarios, the contents of the
+ // APK are already there in the OS's page cache and thus mmap does not use additional
+ // physical memory.
+ DataSource beforeApkSigningBlock =
+ new MemoryMappedFileDataSource(apkFileDescriptor, 0, apkSigningBlockOffset);
+ DataSource centralDir =
+ new MemoryMappedFileDataSource(
+ apkFileDescriptor, centralDirOffset, eocdOffset - centralDirOffset);
+
// For the purposes of integrity verification, ZIP End of Central Directory's field Start of
// Central Directory must be considered to point to the offset of the APK Signing Block.
- byte[] eocdBytes = new byte[apkContents.capacity() - eocdOffset];
- apkContents.position(eocdOffset);
- apkContents.get(eocdBytes);
- ByteBuffer eocd = ByteBuffer.wrap(eocdBytes);
- eocd.order(apkContents.order());
- ZipUtils.setZipEocdCentralDirectoryOffset(eocd, apkSigningBlockOffset);
+ eocdBuf = eocdBuf.duplicate();
+ eocdBuf.order(ByteOrder.LITTLE_ENDIAN);
+ ZipUtils.setZipEocdCentralDirectoryOffset(eocdBuf, apkSigningBlockOffset);
+ DataSource eocd = new ByteBufferDataSource(eocdBuf);
int[] digestAlgorithms = new int[expectedDigests.size()];
int digestAlgorithmCount = 0;
@@ -427,30 +426,30 @@ public class ApkSignatureSchemeV2Verifier {
digestAlgorithms[digestAlgorithmCount] = digestAlgorithm;
digestAlgorithmCount++;
}
- Map<Integer, byte[]> actualDigests;
+ byte[][] actualDigests;
try {
actualDigests =
computeContentDigests(
digestAlgorithms,
- new ByteBuffer[] {beforeApkSigningBlock, centralDir, eocd});
+ new DataSource[] {beforeApkSigningBlock, centralDir, eocd});
} catch (DigestException e) {
throw new SecurityException("Failed to compute digest(s) of contents", e);
}
- for (Map.Entry<Integer, byte[]> entry : expectedDigests.entrySet()) {
- int digestAlgorithm = entry.getKey();
- byte[] expectedDigest = entry.getValue();
- byte[] actualDigest = actualDigests.get(digestAlgorithm);
+ for (int i = 0; i < digestAlgorithms.length; i++) {
+ int digestAlgorithm = digestAlgorithms[i];
+ byte[] expectedDigest = expectedDigests.get(digestAlgorithm);
+ byte[] actualDigest = actualDigests[i];
if (!MessageDigest.isEqual(expectedDigest, actualDigest)) {
throw new SecurityException(
getContentDigestAlgorithmJcaDigestAlgorithm(digestAlgorithm)
- + " digest of contents did not verify");
+ + " digest of contents did not verify");
}
}
}
- private static Map<Integer, byte[]> computeContentDigests(
+ private static byte[][] computeContentDigests(
int[] digestAlgorithms,
- ByteBuffer[] contents) throws DigestException {
+ DataSource[] contents) throws DigestException {
// For each digest algorithm the result is computed as follows:
// 1. Each segment of contents is split into consecutive chunks of 1 MB in size.
// The final chunk will be shorter iff the length of segment is not a multiple of 1 MB.
@@ -461,13 +460,18 @@ public class ApkSignatureSchemeV2Verifier {
// chunks (uint32 little-endian) and the concatenation of digests of chunks of all
// segments in-order.
- int totalChunkCount = 0;
- for (ByteBuffer input : contents) {
- totalChunkCount += getChunkCount(input.remaining());
+ long totalChunkCountLong = 0;
+ for (DataSource input : contents) {
+ totalChunkCountLong += getChunkCount(input.size());
+ }
+ if (totalChunkCountLong >= Integer.MAX_VALUE / 1024) {
+ throw new DigestException("Too many chunks: " + totalChunkCountLong);
}
+ int totalChunkCount = (int) totalChunkCountLong;
- Map<Integer, byte[]> digestsOfChunks = new HashMap<>(totalChunkCount);
- for (int digestAlgorithm : digestAlgorithms) {
+ byte[][] digestsOfChunks = new byte[digestAlgorithms.length][];
+ for (int i = 0; i < digestAlgorithms.length; i++) {
+ int digestAlgorithm = digestAlgorithms[i];
int digestOutputSizeBytes = getContentDigestAlgorithmOutputSizeBytes(digestAlgorithm);
byte[] concatenationOfChunkCountAndChunkDigests =
new byte[5 + totalChunkCount * digestOutputSizeBytes];
@@ -476,49 +480,71 @@ public class ApkSignatureSchemeV2Verifier {
totalChunkCount,
concatenationOfChunkCountAndChunkDigests,
1);
- digestsOfChunks.put(digestAlgorithm, concatenationOfChunkCountAndChunkDigests);
+ digestsOfChunks[i] = concatenationOfChunkCountAndChunkDigests;
}
byte[] chunkContentPrefix = new byte[5];
chunkContentPrefix[0] = (byte) 0xa5;
int chunkIndex = 0;
- for (ByteBuffer input : contents) {
- while (input.hasRemaining()) {
- int chunkSize = Math.min(input.remaining(), CHUNK_SIZE_BYTES);
- ByteBuffer chunk = getByteBuffer(input, chunkSize);
- for (int digestAlgorithm : digestAlgorithms) {
- String jcaAlgorithmName =
- getContentDigestAlgorithmJcaDigestAlgorithm(digestAlgorithm);
- MessageDigest md;
- try {
- md = MessageDigest.getInstance(jcaAlgorithmName);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException(jcaAlgorithmName + " digest not supported", e);
- }
- chunk.clear();
- setUnsignedInt32LittleEndian(chunk.remaining(), chunkContentPrefix, 1);
- md.update(chunkContentPrefix);
- md.update(chunk);
- byte[] concatenationOfChunkCountAndChunkDigests =
- digestsOfChunks.get(digestAlgorithm);
+ MessageDigest[] mds = new MessageDigest[digestAlgorithms.length];
+ for (int i = 0; i < digestAlgorithms.length; i++) {
+ String jcaAlgorithmName =
+ getContentDigestAlgorithmJcaDigestAlgorithm(digestAlgorithms[i]);
+ try {
+ mds[i] = MessageDigest.getInstance(jcaAlgorithmName);
+ } catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException(jcaAlgorithmName + " digest not supported", e);
+ }
+ }
+ // TODO: Compute digests of chunks in parallel when beneficial. This requires some research
+ // into how to parallelize (if at all) based on the capabilities of the hardware on which
+ // this code is running and based on the size of input.
+ int dataSourceIndex = 0;
+ for (DataSource input : contents) {
+ long inputOffset = 0;
+ long inputRemaining = input.size();
+ while (inputRemaining > 0) {
+ int chunkSize = (int) Math.min(inputRemaining, CHUNK_SIZE_BYTES);
+ setUnsignedInt32LittleEndian(chunkSize, chunkContentPrefix, 1);
+ for (int i = 0; i < mds.length; i++) {
+ mds[i].update(chunkContentPrefix);
+ }
+ try {
+ input.feedIntoMessageDigests(mds, inputOffset, chunkSize);
+ } catch (IOException e) {
+ throw new DigestException(
+ "Failed to digest chunk #" + chunkIndex + " of section #"
+ + dataSourceIndex,
+ e);
+ }
+ for (int i = 0; i < digestAlgorithms.length; i++) {
+ int digestAlgorithm = digestAlgorithms[i];
+ byte[] concatenationOfChunkCountAndChunkDigests = digestsOfChunks[i];
int expectedDigestSizeBytes =
getContentDigestAlgorithmOutputSizeBytes(digestAlgorithm);
- int actualDigestSizeBytes = md.digest(concatenationOfChunkCountAndChunkDigests,
- 5 + chunkIndex * expectedDigestSizeBytes, expectedDigestSizeBytes);
+ MessageDigest md = mds[i];
+ int actualDigestSizeBytes =
+ md.digest(
+ concatenationOfChunkCountAndChunkDigests,
+ 5 + chunkIndex * expectedDigestSizeBytes,
+ expectedDigestSizeBytes);
if (actualDigestSizeBytes != expectedDigestSizeBytes) {
throw new RuntimeException(
"Unexpected output size of " + md.getAlgorithm() + " digest: "
+ actualDigestSizeBytes);
}
}
+ inputOffset += chunkSize;
+ inputRemaining -= chunkSize;
chunkIndex++;
}
+ dataSourceIndex++;
}
- Map<Integer, byte[]> result = new HashMap<>(digestAlgorithms.length);
- for (Map.Entry<Integer, byte[]> entry : digestsOfChunks.entrySet()) {
- int digestAlgorithm = entry.getKey();
- byte[] input = entry.getValue();
+ byte[][] result = new byte[digestAlgorithms.length][];
+ for (int i = 0; i < digestAlgorithms.length; i++) {
+ int digestAlgorithm = digestAlgorithms[i];
+ byte[] input = digestsOfChunks[i];
String jcaAlgorithmName = getContentDigestAlgorithmJcaDigestAlgorithm(digestAlgorithm);
MessageDigest md;
try {
@@ -527,49 +553,47 @@ public class ApkSignatureSchemeV2Verifier {
throw new RuntimeException(jcaAlgorithmName + " digest not supported", e);
}
byte[] output = md.digest(input);
- result.put(digestAlgorithm, output);
+ result[i] = output;
}
return result;
}
/**
- * Finds the offset of ZIP End of Central Directory (EoCD).
+ * Returns the ZIP End of Central Directory (EoCD) and its offset in the file.
*
- * @throws SignatureNotFoundException If the EoCD could not be found
+ * @throws IOException if an I/O error occurs while reading the file.
+ * @throws SignatureNotFoundException if the EoCD could not be found.
*/
- private static int getEocdOffset(ByteBuffer apkContents) throws SignatureNotFoundException {
- int eocdOffset = ZipUtils.findZipEndOfCentralDirectoryRecord(apkContents);
- if (eocdOffset == -1) {
+ private static Pair<ByteBuffer, Long> getEocd(RandomAccessFile apk)
+ throws IOException, SignatureNotFoundException {
+ Pair<ByteBuffer, Long> eocdAndOffsetInFile =
+ ZipUtils.findZipEndOfCentralDirectoryRecord(apk);
+ if (eocdAndOffsetInFile == null) {
throw new SignatureNotFoundException(
"Not an APK file: ZIP End of Central Directory record not found");
}
- return eocdOffset;
+ return eocdAndOffsetInFile;
}
- private static long getCentralDirOffset(ByteBuffer apkContents, int eocdOffset)
+ private static long getCentralDirOffset(ByteBuffer eocd, long eocdOffset)
throws SignatureNotFoundException {
- if (ZipUtils.isZip64EndOfCentralDirectoryLocatorPresent(apkContents, eocdOffset)) {
- throw new SignatureNotFoundException("ZIP64 APK not supported");
- }
- ByteBuffer eocd = sliceFromTo(apkContents, eocdOffset, apkContents.capacity());
-
// Look up the offset of ZIP Central Directory.
- long centralDirOffsetLong = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
- if (centralDirOffsetLong >= eocdOffset) {
+ long centralDirOffset = ZipUtils.getZipEocdCentralDirectoryOffset(eocd);
+ if (centralDirOffset >= eocdOffset) {
throw new SignatureNotFoundException(
- "ZIP Central Directory offset out of range: " + centralDirOffsetLong
+ "ZIP Central Directory offset out of range: " + centralDirOffset
+ ". ZIP End of Central Directory offset: " + eocdOffset);
}
- long centralDirSizeLong = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
- if (centralDirOffsetLong + centralDirSizeLong != eocdOffset) {
+ long centralDirSize = ZipUtils.getZipEocdCentralDirectorySizeBytes(eocd);
+ if (centralDirOffset + centralDirSize != eocdOffset) {
throw new SignatureNotFoundException(
"ZIP Central Directory is not immediately followed by End of Central"
+ " Directory");
}
- return centralDirOffsetLong;
+ return centralDirOffset;
}
- private static final int getChunkCount(int inputSizeBytes) {
+ private static final long getChunkCount(long inputSizeBytes) {
return (inputSizeBytes + CHUNK_SIZE_BYTES - 1) / CHUNK_SIZE_BYTES;
}
@@ -837,10 +861,9 @@ public class ApkSignatureSchemeV2Verifier {
private static final int APK_SIGNATURE_SCHEME_V2_BLOCK_ID = 0x7109871a;
- private static int findApkSigningBlock(ByteBuffer apkContents, int centralDirOffset)
- throws SignatureNotFoundException {
- checkByteOrderLittleEndian(apkContents);
-
+ private static Pair<ByteBuffer, Long> findApkSigningBlock(
+ RandomAccessFile apk, long centralDirOffset)
+ throws IOException, SignatureNotFoundException {
// FORMAT:
// OFFSET DATA TYPE DESCRIPTION
// * @+0 bytes uint64: size in bytes (excluding this field)
@@ -853,32 +876,42 @@ public class ApkSignatureSchemeV2Verifier {
"APK too small for APK Signing Block. ZIP Central Directory offset: "
+ centralDirOffset);
}
- // Check magic field present
- if ((apkContents.getLong(centralDirOffset - 16) != APK_SIG_BLOCK_MAGIC_LO)
- || (apkContents.getLong(centralDirOffset - 8) != APK_SIG_BLOCK_MAGIC_HI)) {
+ // Read the magic and offset in file from the footer section of the block:
+ // * uint64: size of block
+ // * 16 bytes: magic
+ ByteBuffer footer = ByteBuffer.allocate(24);
+ footer.order(ByteOrder.LITTLE_ENDIAN);
+ apk.seek(centralDirOffset - footer.capacity());
+ apk.readFully(footer.array(), footer.arrayOffset(), footer.capacity());
+ if ((footer.getLong(8) != APK_SIG_BLOCK_MAGIC_LO)
+ || (footer.getLong(16) != APK_SIG_BLOCK_MAGIC_HI)) {
throw new SignatureNotFoundException(
"No APK Signing Block before ZIP Central Directory");
}
// Read and compare size fields
- long apkSigBlockSizeLong = apkContents.getLong(centralDirOffset - 24);
- if ((apkSigBlockSizeLong < 24) || (apkSigBlockSizeLong > Integer.MAX_VALUE - 8)) {
+ long apkSigBlockSizeInFooter = footer.getLong(0);
+ if ((apkSigBlockSizeInFooter < footer.capacity())
+ || (apkSigBlockSizeInFooter > Integer.MAX_VALUE - 8)) {
throw new SignatureNotFoundException(
- "APK Signing Block size out of range: " + apkSigBlockSizeLong);
+ "APK Signing Block size out of range: " + apkSigBlockSizeInFooter);
}
- int apkSigBlockSizeFromFooter = (int) apkSigBlockSizeLong;
- int totalSize = apkSigBlockSizeFromFooter + 8;
- int apkSigBlockOffset = centralDirOffset - totalSize;
+ int totalSize = (int) (apkSigBlockSizeInFooter + 8);
+ long apkSigBlockOffset = centralDirOffset - totalSize;
if (apkSigBlockOffset < 0) {
throw new SignatureNotFoundException(
"APK Signing Block offset out of range: " + apkSigBlockOffset);
}
- long apkSigBlockSizeFromHeader = apkContents.getLong(apkSigBlockOffset);
- if (apkSigBlockSizeFromHeader != apkSigBlockSizeFromFooter) {
+ ByteBuffer apkSigBlock = ByteBuffer.allocate(totalSize);
+ apkSigBlock.order(ByteOrder.LITTLE_ENDIAN);
+ apk.seek(apkSigBlockOffset);
+ apk.readFully(apkSigBlock.array(), apkSigBlock.arrayOffset(), apkSigBlock.capacity());
+ long apkSigBlockSizeInHeader = apkSigBlock.getLong(0);
+ if (apkSigBlockSizeInHeader != apkSigBlockSizeInFooter) {
throw new SignatureNotFoundException(
"APK Signing Block sizes in header and footer do not match: "
- + apkSigBlockSizeFromHeader + " vs " + apkSigBlockSizeFromFooter);
+ + apkSigBlockSizeInHeader + " vs " + apkSigBlockSizeInFooter);
}
- return apkSigBlockOffset;
+ return Pair.create(apkSigBlock, apkSigBlockOffset);
}
private static ByteBuffer findApkSignatureSchemeV2Block(ByteBuffer apkSigningBlock)
@@ -930,6 +963,8 @@ public class ApkSignatureSchemeV2Verifier {
}
public static class SignatureNotFoundException extends Exception {
+ private static final long serialVersionUID = 1L;
+
public SignatureNotFoundException(String message) {
super(message);
}
@@ -940,6 +975,159 @@ public class ApkSignatureSchemeV2Verifier {
}
/**
+ * Source of data to be digested.
+ */
+ private static interface DataSource {
+
+ /**
+ * Returns the size (in bytes) of the data offered by this source.
+ */
+ long size();
+
+ /**
+ * Feeds the specified region of this source's data into the provided digests. Each digest
+ * instance gets the same data.
+ *
+ * @param offset offset of the region inside this data source.
+ * @param size size (in bytes) of the region.
+ */
+ void feedIntoMessageDigests(MessageDigest[] mds, long offset, int size) throws IOException;
+ }
+
+ /**
+ * {@link DataSource} which provides data from a file descriptor by memory-mapping the sections
+ * of the file requested by
+ * {@link DataSource#feedIntoMessageDigests(MessageDigest[], long, int) feedIntoMessageDigests}.
+ */
+ private static final class MemoryMappedFileDataSource implements DataSource {
+ private static final Os OS = Libcore.os;
+ private static final long MEMORY_PAGE_SIZE_BYTES = OS.sysconf(OsConstants._SC_PAGESIZE);
+
+ private final FileDescriptor mFd;
+ private final long mFilePosition;
+ private final long mSize;
+
+ /**
+ * Constructs a new {@code MemoryMappedFileDataSource} for the specified region of the file.
+ *
+ * @param position start position of the region in the file.
+ * @param size size (in bytes) of the region.
+ */
+ public MemoryMappedFileDataSource(FileDescriptor fd, long position, long size) {
+ mFd = fd;
+ mFilePosition = position;
+ mSize = size;
+ }
+
+ @Override
+ public long size() {
+ return mSize;
+ }
+
+ @Override
+ public void feedIntoMessageDigests(
+ MessageDigest[] mds, long offset, int size) throws IOException {
+ // IMPLEMENTATION NOTE: After a lot of experimentation, the implementation of this
+ // method was settled on a straightforward mmap with prefaulting.
+ //
+ // This method is not using FileChannel.map API because that API does not offset a way
+ // to "prefault" the resulting memory pages. Without prefaulting, performance is about
+ // 10% slower on small to medium APKs, but is significantly worse for APKs in 500+ MB
+ // range. FileChannel.load (which currently uses madvise) doesn't help. Finally,
+ // invoking madvise (MADV_SEQUENTIAL) after mmap with prefaulting wastes quite a bit of
+ // time, which is not compensated for by faster reads.
+
+ // We mmap the smallest region of the file containing the requested data. mmap requires
+ // that the start offset in the file must be a multiple of memory page size. We thus may
+ // need to mmap from an offset less than the requested offset.
+ long filePosition = mFilePosition + offset;
+ long mmapFilePosition =
+ (filePosition / MEMORY_PAGE_SIZE_BYTES) * MEMORY_PAGE_SIZE_BYTES;
+ int dataStartOffsetInMmapRegion = (int) (filePosition - mmapFilePosition);
+ long mmapRegionSize = size + dataStartOffsetInMmapRegion;
+ long mmapPtr = 0;
+ try {
+ mmapPtr = OS.mmap(
+ 0, // let the OS choose the start address of the region in memory
+ mmapRegionSize,
+ OsConstants.PROT_READ,
+ OsConstants.MAP_SHARED | OsConstants.MAP_POPULATE, // "prefault" all pages
+ mFd,
+ mmapFilePosition);
+ // Feeding a memory region into MessageDigest requires the region to be represented
+ // as a direct ByteBuffer.
+ ByteBuffer buf = new DirectByteBuffer(
+ size,
+ mmapPtr + dataStartOffsetInMmapRegion,
+ mFd, // not really needed, but just in case
+ null, // no need to clean up -- it's taken care of by the finally block
+ true // read only buffer
+ );
+ for (MessageDigest md : mds) {
+ buf.position(0);
+ md.update(buf);
+ }
+ } catch (ErrnoException e) {
+ throw new IOException("Failed to mmap " + mmapRegionSize + " bytes", e);
+ } finally {
+ if (mmapPtr != 0) {
+ try {
+ OS.munmap(mmapPtr, mmapRegionSize);
+ } catch (ErrnoException ignored) {}
+ }
+ }
+ }
+ }
+
+ /**
+ * {@link DataSource} which provides data from a {@link ByteBuffer}.
+ */
+ private static final class ByteBufferDataSource implements DataSource {
+ /**
+ * Underlying buffer. The data is stored between position 0 and the buffer's capacity.
+ * The buffer's position is 0 and limit is equal to capacity.
+ */
+ private final ByteBuffer mBuf;
+
+ public ByteBufferDataSource(ByteBuffer buf) {
+ // Defensive copy, to avoid changes to mBuf being visible in buf.
+ mBuf = buf.slice();
+ }
+
+ @Override
+ public long size() {
+ return mBuf.capacity();
+ }
+
+ @Override
+ public void feedIntoMessageDigests(
+ MessageDigest[] mds, long offset, int size) throws IOException {
+ // There's no way to tell MessageDigest to read data from ByteBuffer from a position
+ // other than the buffer's current position. We thus need to change the buffer's
+ // position to match the requested offset.
+ //
+ // In the future, it may be necessary to compute digests of multiple regions in
+ // parallel. Given that digest computation is a slow operation, we enable multiple
+ // such requests to be fulfilled by this instance. This is achieved by serially
+ // creating a new ByteBuffer corresponding to the requested data range and then,
+ // potentially concurrently, feeding these buffers into MessageDigest instances.
+ ByteBuffer region;
+ synchronized (mBuf) {
+ mBuf.position((int) offset);
+ mBuf.limit((int) offset + size);
+ region = mBuf.slice();
+ }
+
+ for (MessageDigest md : mds) {
+ // Need to reset position to 0 at the start of each iteration because
+ // MessageDigest.update below sets it to the buffer's limit.
+ region.position(0);
+ md.update(region);
+ }
+ }
+ }
+
+ /**
* For legacy reasons we need to return exactly the original encoded certificate bytes, instead
* of letting the underlying implementation have a shot at re-encoding the data.
*/
diff --git a/core/java/android/util/apk/ZipUtils.java b/core/java/android/util/apk/ZipUtils.java
index a383d5c151dd..cdbac1802377 100644
--- a/core/java/android/util/apk/ZipUtils.java
+++ b/core/java/android/util/apk/ZipUtils.java
@@ -16,13 +16,17 @@
package android.util.apk;
+import android.util.Pair;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Assorted ZIP format helpers.
*
- * <p>NOTE: Most helper methods operating on {@code ByteBuffer} instances except that the byte
+ * <p>NOTE: Most helper methods operating on {@code ByteBuffer} instances expect that the byte
* order of these buffers is little-endian.
*/
abstract class ZipUtils {
@@ -35,9 +39,101 @@ abstract class ZipUtils {
private static final int ZIP_EOCD_COMMENT_LENGTH_FIELD_OFFSET = 20;
private static final int ZIP64_EOCD_LOCATOR_SIZE = 20;
- private static final int ZIP64_EOCD_LOCATOR_SIG = 0x07064b50;
+ private static final int ZIP64_EOCD_LOCATOR_SIG_REVERSE_BYTE_ORDER = 0x504b0607;
- private static final int UINT32_MAX_VALUE = 0xffff;
+ private static final int UINT16_MAX_VALUE = 0xffff;
+
+ /**
+ * Returns the ZIP End of Central Directory record of the provided ZIP file.
+ *
+ * @return contents of the ZIP End of Central Directory record and the record's offset in the
+ * file or {@code null} if the file does not contain the record.
+ *
+ * @throws IOException if an I/O error occurs while reading the file.
+ */
+ static Pair<ByteBuffer, Long> findZipEndOfCentralDirectoryRecord(RandomAccessFile zip)
+ throws IOException {
+ // ZIP End of Central Directory (EOCD) record is located at the very end of the ZIP archive.
+ // The record can be identified by its 4-byte signature/magic which is located at the very
+ // beginning of the record. A complication is that the record is variable-length because of
+ // the comment field.
+ // The algorithm for locating the ZIP EOCD record is as follows. We search backwards from
+ // end of the buffer for the EOCD record signature. Whenever we find a signature, we check
+ // the candidate record's comment length is such that the remainder of the record takes up
+ // exactly the remaining bytes in the buffer. The search is bounded because the maximum
+ // size of the comment field is 65535 bytes because the field is an unsigned 16-bit number.
+
+ long fileSize = zip.length();
+ if (fileSize < ZIP_EOCD_REC_MIN_SIZE) {
+ return null;
+ }
+
+ // Optimization: 99.99% of APKs have a zero-length comment field in the EoCD record and thus
+ // the EoCD record offset is known in advance. Try that offset first to avoid unnecessarily
+ // reading more data.
+ Pair<ByteBuffer, Long> result = findZipEndOfCentralDirectoryRecord(zip, 0);
+ if (result != null) {
+ return result;
+ }
+
+ // EoCD does not start where we expected it to. Perhaps it contains a non-empty comment
+ // field. Expand the search. The maximum size of the comment field in EoCD is 65535 because
+ // the comment length field is an unsigned 16-bit number.
+ return findZipEndOfCentralDirectoryRecord(zip, UINT16_MAX_VALUE);
+ }
+
+ /**
+ * Returns the ZIP End of Central Directory record of the provided ZIP file.
+ *
+ * @param maxCommentSize maximum accepted size (in bytes) of EoCD comment field. The permitted
+ * value is from 0 to 65535 inclusive. The smaller the value, the faster this method
+ * locates the record, provided its comment field is no longer than this value.
+ *
+ * @return contents of the ZIP End of Central Directory record and the record's offset in the
+ * file or {@code null} if the file does not contain the record.
+ *
+ * @throws IOException if an I/O error occurs while reading the file.
+ */
+ private static Pair<ByteBuffer, Long> findZipEndOfCentralDirectoryRecord(
+ RandomAccessFile zip, int maxCommentSize) throws IOException {
+ // ZIP End of Central Directory (EOCD) record is located at the very end of the ZIP archive.
+ // The record can be identified by its 4-byte signature/magic which is located at the very
+ // beginning of the record. A complication is that the record is variable-length because of
+ // the comment field.
+ // The algorithm for locating the ZIP EOCD record is as follows. We search backwards from
+ // end of the buffer for the EOCD record signature. Whenever we find a signature, we check
+ // the candidate record's comment length is such that the remainder of the record takes up
+ // exactly the remaining bytes in the buffer. The search is bounded because the maximum
+ // size of the comment field is 65535 bytes because the field is an unsigned 16-bit number.
+
+ if ((maxCommentSize < 0) || (maxCommentSize > UINT16_MAX_VALUE)) {
+ throw new IllegalArgumentException("maxCommentSize: " + maxCommentSize);
+ }
+
+ long fileSize = zip.length();
+ if (fileSize < ZIP_EOCD_REC_MIN_SIZE) {
+ // No space for EoCD record in the file.
+ return null;
+ }
+ // Lower maxCommentSize if the file is too small.
+ maxCommentSize = (int) Math.min(maxCommentSize, fileSize - ZIP_EOCD_REC_MIN_SIZE);
+
+ ByteBuffer buf = ByteBuffer.allocate(ZIP_EOCD_REC_MIN_SIZE + maxCommentSize);
+ buf.order(ByteOrder.LITTLE_ENDIAN);
+ long bufOffsetInFile = fileSize - buf.capacity();
+ zip.seek(bufOffsetInFile);
+ zip.readFully(buf.array(), buf.arrayOffset(), buf.capacity());
+ int eocdOffsetInBuf = findZipEndOfCentralDirectoryRecord(buf);
+ if (eocdOffsetInBuf == -1) {
+ // No EoCD record found in the buffer
+ return null;
+ }
+ // EoCD found
+ buf.position(eocdOffsetInBuf);
+ ByteBuffer eocd = buf.slice();
+ eocd.order(ByteOrder.LITTLE_ENDIAN);
+ return Pair.create(eocd, bufOffsetInFile + eocdOffsetInBuf);
+ }
/**
* Returns the position at which ZIP End of Central Directory record starts in the provided
@@ -45,7 +141,7 @@ abstract class ZipUtils {
*
* <p>NOTE: Byte order of {@code zipContents} must be little-endian.
*/
- public static int findZipEndOfCentralDirectoryRecord(ByteBuffer zipContents) {
+ private static int findZipEndOfCentralDirectoryRecord(ByteBuffer zipContents) {
assertByteOrderLittleEndian(zipContents);
// ZIP End of Central Directory (EOCD) record is located at the very end of the ZIP archive.
@@ -56,14 +152,13 @@ abstract class ZipUtils {
// end of the buffer for the EOCD record signature. Whenever we find a signature, we check
// the candidate record's comment length is such that the remainder of the record takes up
// exactly the remaining bytes in the buffer. The search is bounded because the maximum
- // size of the comment field is 65535 bytes because the field is an unsigned 32-bit number.
+ // size of the comment field is 65535 bytes because the field is an unsigned 16-bit number.
int archiveSize = zipContents.capacity();
if (archiveSize < ZIP_EOCD_REC_MIN_SIZE) {
- System.out.println("File size smaller than EOCD min size");
return -1;
}
- int maxCommentLength = Math.min(archiveSize - ZIP_EOCD_REC_MIN_SIZE, UINT32_MAX_VALUE);
+ int maxCommentLength = Math.min(archiveSize - ZIP_EOCD_REC_MIN_SIZE, UINT16_MAX_VALUE);
int eocdWithEmptyCommentStartPosition = archiveSize - ZIP_EOCD_REC_MIN_SIZE;
for (int expectedCommentLength = 0; expectedCommentLength < maxCommentLength;
expectedCommentLength++) {
@@ -82,24 +177,28 @@ abstract class ZipUtils {
}
/**
- * Returns {@code true} if the provided buffer contains a ZIP64 End of Central Directory
+ * Returns {@code true} if the provided file contains a ZIP64 End of Central Directory
* Locator.
*
- * <p>NOTE: Byte order of {@code zipContents} must be little-endian.
+ * @param zipEndOfCentralDirectoryPosition offset of the ZIP End of Central Directory record
+ * in the file.
+ *
+ * @throws IOException if an I/O error occurs while reading the file.
*/
public static final boolean isZip64EndOfCentralDirectoryLocatorPresent(
- ByteBuffer zipContents, int zipEndOfCentralDirectoryPosition) {
- assertByteOrderLittleEndian(zipContents);
+ RandomAccessFile zip, long zipEndOfCentralDirectoryPosition) throws IOException {
// ZIP64 End of Central Directory Locator immediately precedes the ZIP End of Central
// Directory Record.
-
- int locatorPosition = zipEndOfCentralDirectoryPosition - ZIP64_EOCD_LOCATOR_SIZE;
+ long locatorPosition = zipEndOfCentralDirectoryPosition - ZIP64_EOCD_LOCATOR_SIZE;
if (locatorPosition < 0) {
return false;
}
- return zipContents.getInt(locatorPosition) == ZIP64_EOCD_LOCATOR_SIG;
+ zip.seek(locatorPosition);
+ // RandomAccessFile.readInt assumes big-endian byte order, but ZIP format uses
+ // little-endian.
+ return zip.readInt() == ZIP64_EOCD_LOCATOR_SIG_REVERSE_BYTE_ORDER;
}
/**
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 6a2cc802e1f1..a1e2e946c48a 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -112,15 +112,18 @@ interface IWindowSession {
*
* @param window The window being modified. Must be attached to a parent window
* or this call will fail.
- * @param x The new x position
- * @param y The new y position
- * @param width The new width
- * @param height The new height
+ * @param left The new left position
+ * @param top The new top position
+ * @param right The new right position
+ * @param bottom The new bottom position
+ * @param requestedWidth The new requested width
+ * @param requestedHeight The new requested height
* @param deferTransactionUntilFrame Frame number from our parent (attached) to
* defer this action until.
* @param outFrame Rect in which is placed the new position/size on screen.
*/
void repositionChild(IWindow childWindow, int left, int top, int right, int bottom,
+ int requestedWidth, int requestedHeight,
long deferTransactionUntilFrame, out Rect outFrame);
/*
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index aa86c03c53c7..c30ede37a4ac 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -57,6 +57,7 @@ public class SurfaceControl {
private static native void nativeSetMatrix(long nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
private static native void nativeSetFlags(long nativeObject, int flags, int mask);
private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
+ private static native void nativeSetFinalCrop(long nativeObject, int l, int t, int r, int b);
private static native void nativeSetLayerStack(long nativeObject, int layerStack);
private static native boolean nativeClearContentFrameStats(long nativeObject);
@@ -456,6 +457,16 @@ public class SurfaceControl {
}
}
+ public void setFinalCrop(Rect crop) {
+ checkNotReleased();
+ if (crop != null) {
+ nativeSetFinalCrop(mNativeObject,
+ crop.left, crop.top, crop.right, crop.bottom);
+ } else {
+ nativeSetFinalCrop(mNativeObject, 0, 0, 0, 0);
+ }
+ }
+
public void setLayerStack(int layerStack) {
checkNotReleased();
nativeSetLayerStack(mNativeObject, layerStack);
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 2c9d691214b0..477ffd9b5ba4 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -665,7 +665,9 @@ public class SurfaceView extends View {
"postion = [%d, %d, %d, %d]", mWindowSpaceLeft, mWindowSpaceTop,
mLocation[0], mLocation[1]));
mSession.repositionChild(mWindow, mWindowSpaceLeft, mWindowSpaceTop,
- mLocation[0], mLocation[1], -1, mWinFrame);
+ mLocation[0], mLocation[1],
+ mWindowSpaceWidth, mWindowSpaceHeight,
+ -1, mWinFrame);
} catch (RemoteException ex) {
Log.e(TAG, "Exception from relayout", ex);
}
@@ -700,7 +702,9 @@ public class SurfaceView extends View {
right, bottom));
}
// Just using mRTLastReportedPosition as a dummy rect here
- session.repositionChild(window, left, top, right, bottom, frameNumber,
+ session.repositionChild(window, left, top, right, bottom,
+ mWindowSpaceWidth, mWindowSpaceHeight,
+ frameNumber,
mRTLastReportedPosition);
// Now overwrite mRTLastReportedPosition with our values
mRTLastReportedPosition.set(left, top, right, bottom);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 358648432863..6d35a58c3be4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -18002,7 +18002,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* to clear the previous drawable. setVisible first while we still have the callback set.
*/
if (mBackground != null) {
- if (isAttachedToWindow()) {
+ // It's possible for this method to be invoked from the View constructor before
+ // subclass constructors have run. Drawables can and should trigger invalidations
+ // and other activity with their callback on visibility changes, which shouldn't
+ // happen before subclass constructors finish. However, we won't have set the
+ // drawable as visible until the view becomes attached. This guard below keeps
+ // multiple calls to this method from constructors from causing issues.
+ if (mBackground.isVisible()) {
mBackground.setVisible(false, false);
}
mBackground.setCallback(null);
@@ -18237,7 +18243,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
if (mForegroundInfo.mDrawable != null) {
- if (isAttachedToWindow()) {
+ // It's possible for this method to be invoked from the View constructor before
+ // subclass constructors have run. Drawables can and should trigger invalidations
+ // and other activity with their callback on visibility changes, which shouldn't
+ // happen before subclass constructors finish. However, we won't have set the
+ // drawable as visible until the view becomes attached. This guard below keeps
+ // multiple calls to this method from constructors from causing issues.
+ if (mForegroundInfo.mDrawable.isVisible()) {
mForegroundInfo.mDrawable.setVisible(false, false);
}
mForegroundInfo.mDrawable.setCallback(null);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index a2295ce5fecf..da7799c1ec3f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -3287,7 +3287,6 @@ public final class ViewRootImpl implements ViewParent,
private final static int MSG_DISPATCH_APP_VISIBILITY = 8;
private final static int MSG_DISPATCH_GET_NEW_SURFACE = 9;
private final static int MSG_DISPATCH_KEY_FROM_IME = 11;
- private final static int MSG_FINISH_INPUT_CONNECTION = 12;
private final static int MSG_CHECK_FOCUS = 13;
private final static int MSG_CLOSE_SYSTEM_DIALOGS = 14;
private final static int MSG_DISPATCH_DRAG_EVENT = 15;
@@ -3327,8 +3326,6 @@ public final class ViewRootImpl implements ViewParent,
return "MSG_DISPATCH_GET_NEW_SURFACE";
case MSG_DISPATCH_KEY_FROM_IME:
return "MSG_DISPATCH_KEY_FROM_IME";
- case MSG_FINISH_INPUT_CONNECTION:
- return "MSG_FINISH_INPUT_CONNECTION";
case MSG_CHECK_FOCUS:
return "MSG_CHECK_FOCUS";
case MSG_CLOSE_SYSTEM_DIALOGS:
@@ -3549,12 +3546,6 @@ public final class ViewRootImpl implements ViewParent,
}
enqueueInputEvent(event, null, QueuedInputEvent.FLAG_DELIVER_POST_IME, true);
} break;
- case MSG_FINISH_INPUT_CONNECTION: {
- InputMethodManager imm = InputMethodManager.peekInstance();
- if (imm != null) {
- imm.reportFinishInputConnection((InputConnection)msg.obj);
- }
- } break;
case MSG_CHECK_FOCUS: {
InputMethodManager imm = InputMethodManager.peekInstance();
if (imm != null) {
@@ -5864,11 +5855,6 @@ public final class ViewRootImpl implements ViewParent,
}
}
- public void dispatchFinishInputConnection(InputConnection connection) {
- Message msg = mHandler.obtainMessage(MSG_FINISH_INPUT_CONNECTION, connection);
- mHandler.sendMessage(msg);
- }
-
public void dispatchResized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, Rect stableInsets, Rect outsets, boolean reportDraw,
Configuration newConfig, Rect backDropFrame, boolean forceLayout,
diff --git a/core/java/android/view/inputmethod/BaseInputConnection.java b/core/java/android/view/inputmethod/BaseInputConnection.java
index 6a830f87de1f..a3c49c5a8457 100644
--- a/core/java/android/view/inputmethod/BaseInputConnection.java
+++ b/core/java/android/view/inputmethod/BaseInputConnection.java
@@ -158,8 +158,8 @@ public class BaseInputConnection implements InputConnection {
*
* @hide
*/
- protected void reportFinish() {
- // Intentionaly empty
+ public void reportFinish() {
+ // Intentionally empty
}
/**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 97cafb713186..4bb0c3cbb5ee 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -317,7 +317,6 @@ public final class InputMethodManager {
/**
* The InputConnection that was last retrieved from the served view.
*/
- InputConnection mServedInputConnection;
ControlledInputConnectionWrapper mServedInputConnectionWrapper;
/**
* The completions that were last provided by the served view.
@@ -498,7 +497,7 @@ public final class InputMethodManager {
// from a thread that created mServedView. That could happen
// the current activity is running in the system process.
// In that case, we really should not call
- // mServedInputConnection.finishComposingText.
+ // mServedInputConnectionWrapper.finishComposingText().
if (checkFocusNoStartInput(mHasBeenInactive, false)) {
final int reason = active ?
InputMethodClient.START_INPUT_REASON_ACTIVATED_BY_IMMS :
@@ -532,22 +531,25 @@ public final class InputMethodManager {
private static class ControlledInputConnectionWrapper extends IInputConnectionWrapper {
private final InputMethodManager mParentInputMethodManager;
- private boolean mActive;
public ControlledInputConnectionWrapper(final Looper mainLooper, final InputConnection conn,
final InputMethodManager inputMethodManager) {
super(mainLooper, conn);
mParentInputMethodManager = inputMethodManager;
- mActive = true;
}
@Override
public boolean isActive() {
- return mParentInputMethodManager.mActive && mActive;
+ return mParentInputMethodManager.mActive && !isFinished();
}
void deactivate() {
- mActive = false;
+ if (isFinished()) {
+ // This is a small performance optimization. Still only the 1st call of
+ // reportFinish() will take effect.
+ return;
+ }
+ reportFinish();
}
@Override
@@ -562,7 +564,9 @@ public final class InputMethodManager {
@Override
public String toString() {
- return "ControlledInputConnectionWrapper{mActive=" + mActive
+ return "ControlledInputConnectionWrapper{"
+ + "connection=" + getInputConnection()
+ + " finished=" + isFinished()
+ " mParentInputMethodManager.mActive=" + mParentInputMethodManager.mActive
+ "}";
}
@@ -780,7 +784,8 @@ public final class InputMethodManager {
*/
public boolean isAcceptingText() {
checkFocus();
- return mServedInputConnection != null;
+ return mServedInputConnectionWrapper != null &&
+ mServedInputConnectionWrapper.getInputConnection() != null;
}
/**
@@ -815,7 +820,6 @@ public final class InputMethodManager {
*/
void clearConnectionLocked() {
mCurrentTextBoxAttribute = null;
- mServedInputConnection = null;
if (mServedInputConnectionWrapper != null) {
mServedInputConnectionWrapper.deactivate();
mServedInputConnectionWrapper = null;
@@ -836,7 +840,6 @@ public final class InputMethodManager {
throw e.rethrowFromSystemServer();
}
}
- notifyInputConnectionFinished();
mServedView = null;
mCompletions = null;
mServedConnecting = false;
@@ -844,37 +847,6 @@ public final class InputMethodManager {
}
}
- /**
- * Notifies the served view that the current InputConnection will no longer be used.
- */
- private void notifyInputConnectionFinished() {
- if (mServedView != null && mServedInputConnection != null) {
- // We need to tell the previously served view that it is no
- // longer the input target, so it can reset its state. Schedule
- // this call on its window's Handler so it will be on the correct
- // thread and outside of our lock.
- ViewRootImpl viewRootImpl = mServedView.getViewRootImpl();
- if (viewRootImpl != null) {
- // This will result in a call to reportFinishInputConnection() below.
- viewRootImpl.dispatchFinishInputConnection(mServedInputConnection);
- }
- }
- }
-
- /**
- * Called from the FINISH_INPUT_CONNECTION message above.
- * @hide
- */
- public void reportFinishInputConnection(InputConnection ic) {
- if (mServedInputConnection != ic) {
- ic.finishComposingText();
- // To avoid modifying the public InputConnection interface
- if (ic instanceof BaseInputConnection) {
- ((BaseInputConnection) ic).reportFinish();
- }
- }
- }
-
public void displayCompletions(View view, CompletionInfo[] completions) {
checkFocus();
synchronized (mH) {
@@ -975,7 +947,17 @@ public final class InputMethodManager {
* shown to the user, if needed. Call this if the user interacts with
* your view in such a way that they have expressed they would like to
* start performing input into it.
- *
+ *
+ * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
+ * this method can be a long-lived object, because it may not be
+ * garbage-collected until all the corresponding {@link ResultReceiver}
+ * objects transferred to different processes get garbage-collected.
+ * Follow the general patterns to avoid memory leaks in Android.
+ * Consider to use {@link java.lang.ref.WeakReference} so that application
+ * logic objects such as {@link android.app.Activity} and {@link Context}
+ * can be garbage collected regardless of the lifetime of
+ * {@link ResultReceiver}.
+ *
* @param view The currently focused view, which would like to receive
* soft keyboard input.
* @param flags Provides additional operating flags. Currently may be
@@ -1044,7 +1026,17 @@ public final class InputMethodManager {
* that is currently accepting input. This should be called as a result
* of the user doing some actually than fairly explicitly requests to
* have the input window hidden.
- *
+ *
+ * <p><strong>Caveat:</strong> {@link ResultReceiver} instance passed to
+ * this method can be a long-lived object, because it may not be
+ * garbage-collected until all the corresponding {@link ResultReceiver}
+ * objects transferred to different processes get garbage-collected.
+ * Follow the general patterns to avoid memory leaks in Android.
+ * Consider to use {@link java.lang.ref.WeakReference} so that application
+ * logic objects such as {@link android.app.Activity} and {@link Context}
+ * can be garbage collected regardless of the lifetime of
+ * {@link ResultReceiver}.
+ *
* @param windowToken The token of the window that is making the request,
* as returned by {@link View#getWindowToken() View.getWindowToken()}.
* @param flags Provides additional operating flags. Currently may be
@@ -1220,9 +1212,10 @@ public final class InputMethodManager {
// Hook 'em up and let 'er rip.
mCurrentTextBoxAttribute = tba;
mServedConnecting = false;
- // Notify the served view that its previous input connection is finished
- notifyInputConnectionFinished();
- mServedInputConnection = ic;
+ if (mServedInputConnectionWrapper != null) {
+ mServedInputConnectionWrapper.deactivate();
+ mServedInputConnectionWrapper = null;
+ }
ControlledInputConnectionWrapper servedContext;
final int missingMethodFlags;
if (ic != null) {
@@ -1247,9 +1240,6 @@ public final class InputMethodManager {
servedContext = null;
missingMethodFlags = 0;
}
- if (mServedInputConnectionWrapper != null) {
- mServedInputConnectionWrapper.deactivate();
- }
mServedInputConnectionWrapper = servedContext;
try {
@@ -1393,7 +1383,7 @@ public final class InputMethodManager {
return false;
}
- InputConnection ic = null;
+ final ControlledInputConnectionWrapper ic;
synchronized (mH) {
if (mServedView == mNextServedView && !forceNewFocus) {
return false;
@@ -1413,7 +1403,7 @@ public final class InputMethodManager {
return false;
}
- ic = mServedInputConnection;
+ ic = mServedInputConnectionWrapper;
mServedView = mNextServedView;
mCurrentTextBoxAttribute = null;
@@ -2262,7 +2252,7 @@ public final class InputMethodManager {
} else {
p.println(" mCurrentTextBoxAttribute: null");
}
- p.println(" mServedInputConnection=" + mServedInputConnection);
+ p.println(" mServedInputConnectionWrapper=" + mServedInputConnectionWrapper);
p.println(" mCompletions=" + Arrays.toString(mCompletions));
p.println(" mCursorRect=" + mCursorRect);
p.println(" mCursorSelStart=" + mCursorSelStart
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 280ff151cd6d..fe8916bf0761 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -400,8 +400,14 @@ public class FrameLayout extends ViewGroup {
}
@Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
+ if (lp instanceof LayoutParams) {
+ return new LayoutParams((LayoutParams) lp);
+ } else if (lp instanceof MarginLayoutParams) {
+ return new LayoutParams((MarginLayoutParams) lp);
+ } else {
+ return new LayoutParams(lp);
+ }
}
@Override
diff --git a/core/java/android/widget/GridLayout.java b/core/java/android/widget/GridLayout.java
index ef6628a20063..726586ee8d5f 100644
--- a/core/java/android/widget/GridLayout.java
+++ b/core/java/android/widget/GridLayout.java
@@ -867,8 +867,14 @@ public class GridLayout extends ViewGroup {
}
@Override
- protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
+ protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
+ if (lp instanceof LayoutParams) {
+ return new LayoutParams((LayoutParams) lp);
+ } else if (lp instanceof MarginLayoutParams) {
+ return new LayoutParams((MarginLayoutParams) lp);
+ } else {
+ return new LayoutParams(lp);
+ }
}
// Draw grid
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 222a040d2b3c..02065779ef91 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -911,11 +911,17 @@ public class ImageView extends View {
}
if (mDrawable != null) {
- mDrawable.setCallback(null);
- unscheduleDrawable(mDrawable);
- if (isAttachedToWindow()) {
+ // It's possible for this method to be invoked from the constructor before
+ // subclass constructors have run. Drawables can and should trigger invalidations
+ // and other activity with their callback on visibility changes, which shouldn't
+ // happen before subclass constructors finish. However, we won't have set the
+ // drawable as visible until the view becomes attached. This guard below keeps
+ // multiple calls to this method from constructors from causing issues.
+ if (mDrawable.isVisible()) {
mDrawable.setVisible(false, false);
}
+ mDrawable.setCallback(null);
+ unscheduleDrawable(mDrawable);
}
mDrawable = d;
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 9e8f778f1819..f75b74bb9a14 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1839,8 +1839,14 @@ public class LinearLayout extends ViewGroup {
}
@Override
- protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
+ protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
+ if (lp instanceof LayoutParams) {
+ return new LayoutParams((LayoutParams) lp);
+ } else if (lp instanceof MarginLayoutParams) {
+ return new LayoutParams((MarginLayoutParams) lp);
+ } else {
+ return new LayoutParams(lp);
+ }
}
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index a1417f0cbb68..d1b5fc8dcd2e 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -2027,21 +2027,24 @@ public class PopupWindow {
mAnchorYoff = yoff;
}
+ final WindowManager.LayoutParams p =
+ (WindowManager.LayoutParams) mDecorView.getLayoutParams();
+
if (updateDimension) {
if (width == -1) {
width = mPopupWidth;
} else {
mPopupWidth = width;
+ p.width = width;
}
if (height == -1) {
height = mPopupHeight;
} else {
mPopupHeight = height;
+ p.height = height;
}
}
- final WindowManager.LayoutParams p =
- (WindowManager.LayoutParams) mDecorView.getLayoutParams();
final int x = p.x;
final int y = p.y;
if (updateLocation) {
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index df01fc159e60..0136542ef4ac 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -1103,8 +1103,14 @@ public class RelativeLayout extends ViewGroup {
}
@Override
- protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams p) {
- return new LayoutParams(p);
+ protected ViewGroup.LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
+ if (lp instanceof LayoutParams) {
+ return new LayoutParams((LayoutParams) lp);
+ } else if (lp instanceof MarginLayoutParams) {
+ return new LayoutParams((MarginLayoutParams) lp);
+ } else {
+ return new LayoutParams(lp);
+ }
}
/** @hide */
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index aac7bc3810e9..753c0691222e 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -204,6 +204,9 @@ public class AlertController {
mShowTitle = a.getBoolean(R.styleable.AlertDialog_showTitle, true);
a.recycle();
+
+ /* We use a custom title so never request a window title */
+ window.requestFeature(Window.FEATURE_NO_TITLE);
}
static boolean canTextInput(View v) {
@@ -229,8 +232,6 @@ public class AlertController {
}
public void installContent() {
- /* We use a custom title so never request a window title */
- mWindow.requestFeature(Window.FEATURE_NO_TITLE);
int contentView = selectContentView();
mWindow.setContentView(contentView);
setupView();
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 80e1db0527a5..5726de1e8c3e 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -76,6 +76,7 @@ import java.util.List;
import java.util.Objects;
import java.util.Set;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
@@ -507,7 +508,9 @@ public class ResolverActivity extends Activity {
mPackageMonitor.unregister();
mRegistered = false;
}
- if ((getIntent().getFlags()&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()) {
+ final Intent intent = getIntent();
+ if ((intent.getFlags() & FLAG_ACTIVITY_NEW_TASK) != 0 && !isVoiceInteraction()
+ && !mResolvingHome) {
// This resolver is in the unusual situation where it has been
// launched at the top of a new task. We don't let it be added
// to the recent tasks shown to the user, and we need to make sure
diff --git a/core/java/com/android/internal/os/InstallerConnection.java b/core/java/com/android/internal/os/InstallerConnection.java
index ed4722d985af..2a9264dccadf 100644
--- a/core/java/com/android/internal/os/InstallerConnection.java
+++ b/core/java/com/android/internal/os/InstallerConnection.java
@@ -21,7 +21,6 @@ import android.net.LocalSocketAddress;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Slog;
-import android.text.TextUtils;
import com.android.internal.util.Preconditions;
@@ -140,14 +139,14 @@ public class InstallerConnection {
}
public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
- int dexFlags, String volumeUuid, boolean useProfiles) throws InstallerException {
+ int dexFlags, String compilerFilter, String volumeUuid) throws InstallerException {
dexopt(apkPath, uid, "*", instructionSet, dexoptNeeded,
- null /*outputPath*/, dexFlags, volumeUuid, useProfiles);
+ null /*outputPath*/, dexFlags, compilerFilter, volumeUuid);
}
public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
- int dexoptNeeded, String outputPath, int dexFlags, String volumeUuid,
- boolean useProfiles) throws InstallerException {
+ int dexoptNeeded, String outputPath, int dexFlags, String compilerFilter,
+ String volumeUuid) throws InstallerException {
execute("dexopt",
apkPath,
uid,
@@ -156,8 +155,27 @@ public class InstallerConnection {
dexoptNeeded,
outputPath,
dexFlags,
- volumeUuid,
- useProfiles ? '1' : '0');
+ compilerFilter,
+ volumeUuid);
+ }
+
+ public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
+ String rawReply = executeForResult("merge_profiles", uid, pkgName);
+ if (rawReply == null) {
+ throw new IllegalStateException("Unexpected null reply");
+ }
+ final String res[] = rawReply.split(" ");
+
+ if ((res == null) || (res.length != 2)) {
+ throw new InstallerException("Invalid size result: " + rawReply);
+ }
+
+ // Just as a sanity check. Anything != "true" will be interpreted as false by parseBoolean.
+ if (!res[1].equals("true") && !res[1].equals("false")) {
+ throw new InstallerException("Invalid boolean result: " + rawReply);
+ }
+
+ return Boolean.parseBoolean(res[1]);
}
private boolean connect() {
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index b658f87a9689..5980ab69d7a4 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -501,12 +501,14 @@ public class ZygoteInit {
for (String classPathElement : classPathElements) {
// System server is fully AOTed and never profiled
// for profile guided compilation.
+ // TODO: Make this configurable between INTERPRET_ONLY, SPEED, SPACE and EVERYTHING?
final int dexoptNeeded = DexFile.getDexOptNeeded(
- classPathElement, instructionSet, DexFile.COMPILATION_TYPE_FULL);
+ classPathElement, instructionSet, "speed",
+ false /* newProfile */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
installer.dexopt(classPathElement, Process.SYSTEM_UID, instructionSet,
- dexoptNeeded, 0 /*dexFlags*/, null /*volumeUuid*/,
- false /*useProfiles*/);
+ dexoptNeeded, 0 /*dexFlags*/, "speed",
+ null /*volumeUuid*/);
}
}
} catch (IOException | InstallerException e) {
diff --git a/core/java/com/android/internal/util/NotificationColorUtil.java b/core/java/com/android/internal/util/NotificationColorUtil.java
index 607697340ca0..48bcc0930164 100644
--- a/core/java/com/android/internal/util/NotificationColorUtil.java
+++ b/core/java/com/android/internal/util/NotificationColorUtil.java
@@ -16,6 +16,11 @@
package com.android.internal.util;
+import android.annotation.ColorInt;
+import android.annotation.FloatRange;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.app.Notification;
import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
@@ -43,6 +48,7 @@ import java.util.WeakHashMap;
public class NotificationColorUtil {
private static final String TAG = "NotificationColorUtil";
+ private static final boolean DEBUG = false;
private static final Object sLock = new Object();
private static NotificationColorUtil sInstance;
@@ -222,4 +228,420 @@ public class NotificationColorUtil {
255 - Color.green(color),
255 - Color.blue(color));
}
+
+ /**
+ * Finds a suitable color such that there's enough contrast.
+ *
+ * @param color the color to start searching from.
+ * @param other the color to ensure contrast against. Assumed to be lighter than {@param color}
+ * @param findFg if true, we assume {@param color} is a foreground, otherwise a background.
+ * @param minRatio the minimum contrast ratio required.
+ * @return a color with the same hue as {@param color}, potentially darkened to meet the
+ * contrast ratio.
+ */
+ private static int findContrastColor(int color, int other, boolean findFg, double minRatio) {
+ int fg = findFg ? color : other;
+ int bg = findFg ? other : color;
+ if (ColorUtilsFromCompat.calculateContrast(fg, bg) >= minRatio) {
+ return color;
+ }
+
+ double[] lab = new double[3];
+ ColorUtilsFromCompat.colorToLAB(findFg ? fg : bg, lab);
+
+ double low = 0, high = lab[0];
+ final double a = lab[1], b = lab[2];
+ for (int i = 0; i < 15 && high - low > 0.00001; i++) {
+ final double l = (low + high) / 2;
+ if (findFg) {
+ fg = ColorUtilsFromCompat.LABToColor(l, a, b);
+ } else {
+ bg = ColorUtilsFromCompat.LABToColor(l, a, b);
+ }
+ if (ColorUtilsFromCompat.calculateContrast(fg, bg) > minRatio) {
+ low = l;
+ } else {
+ high = l;
+ }
+ }
+ return ColorUtilsFromCompat.LABToColor(low, a, b);
+ }
+
+ /**
+ * Finds a text color with sufficient contrast over bg that has the same hue as the original
+ * color, assuming it is for large text.
+ */
+ private static int ensureLargeTextContrast(int color, int bg) {
+ return findContrastColor(color, bg, true, 3);
+ }
+
+ /**
+ * Finds a text color with sufficient contrast over bg that has the same hue as the original
+ * color.
+ */
+ private static int ensureTextContrast(int color, int bg) {
+ return findContrastColor(color, bg, true, 4.5);
+ }
+
+ /** Finds a background color for a text view with given text color and hint text color, that
+ * has the same hue as the original color.
+ */
+ public static int ensureTextBackgroundColor(int color, int textColor, int hintColor) {
+ color = findContrastColor(color, hintColor, false, 3.0);
+ return findContrastColor(color, textColor, false, 4.5);
+ }
+
+ private static String contrastChange(int colorOld, int colorNew, int bg) {
+ return String.format("from %.2f:1 to %.2f:1",
+ ColorUtilsFromCompat.calculateContrast(colorOld, bg),
+ ColorUtilsFromCompat.calculateContrast(colorNew, bg));
+ }
+
+ /**
+ * Resolves {@param color} to an actual color if it is {@link Notification#COLOR_DEFAULT}
+ */
+ public static int resolveColor(Context context, int color) {
+ if (color == Notification.COLOR_DEFAULT) {
+ return context.getColor(com.android.internal.R.color.notification_icon_default_color);
+ }
+ return color;
+ }
+
+ /**
+ * Resolves a Notification's color such that it has enough contrast to be used as the
+ * color for the Notification's action and header text.
+ *
+ * @param notificationColor the color of the notification or {@link Notification#COLOR_DEFAULT}
+ * @return a color of the same hue with enough contrast against the backgrounds.
+ */
+ public static int resolveContrastColor(Context context, int notificationColor) {
+ final int resolvedColor = resolveColor(context, notificationColor);
+
+ final int actionBg = context.getColor(
+ com.android.internal.R.color.notification_action_list);
+ final int notiBg = context.getColor(
+ com.android.internal.R.color.notification_material_background_color);
+
+ int color = resolvedColor;
+ color = NotificationColorUtil.ensureLargeTextContrast(color, actionBg);
+ color = NotificationColorUtil.ensureTextContrast(color, notiBg);
+
+ if (color != resolvedColor) {
+ if (DEBUG){
+ Log.w(TAG, String.format(
+ "Enhanced contrast of notification for %s %s (over action)"
+ + " and %s (over background) by changing #%s to %s",
+ context.getPackageName(),
+ NotificationColorUtil.contrastChange(resolvedColor, color, actionBg),
+ NotificationColorUtil.contrastChange(resolvedColor, color, notiBg),
+ Integer.toHexString(resolvedColor), Integer.toHexString(color)));
+ }
+ }
+ return color;
+ }
+
+ /**
+ * Framework copy of functions needed from android.support.v4.graphics.ColorUtils.
+ */
+ private static class ColorUtilsFromCompat {
+ private static final double XYZ_WHITE_REFERENCE_X = 95.047;
+ private static final double XYZ_WHITE_REFERENCE_Y = 100;
+ private static final double XYZ_WHITE_REFERENCE_Z = 108.883;
+ private static final double XYZ_EPSILON = 0.008856;
+ private static final double XYZ_KAPPA = 903.3;
+
+ private static final int MIN_ALPHA_SEARCH_MAX_ITERATIONS = 10;
+ private static final int MIN_ALPHA_SEARCH_PRECISION = 1;
+
+ private static final ThreadLocal<double[]> TEMP_ARRAY = new ThreadLocal<>();
+
+ private ColorUtilsFromCompat() {}
+
+ /**
+ * Composite two potentially translucent colors over each other and returns the result.
+ */
+ public static int compositeColors(@ColorInt int foreground, @ColorInt int background) {
+ int bgAlpha = Color.alpha(background);
+ int fgAlpha = Color.alpha(foreground);
+ int a = compositeAlpha(fgAlpha, bgAlpha);
+
+ int r = compositeComponent(Color.red(foreground), fgAlpha,
+ Color.red(background), bgAlpha, a);
+ int g = compositeComponent(Color.green(foreground), fgAlpha,
+ Color.green(background), bgAlpha, a);
+ int b = compositeComponent(Color.blue(foreground), fgAlpha,
+ Color.blue(background), bgAlpha, a);
+
+ return Color.argb(a, r, g, b);
+ }
+
+ private static int compositeAlpha(int foregroundAlpha, int backgroundAlpha) {
+ return 0xFF - (((0xFF - backgroundAlpha) * (0xFF - foregroundAlpha)) / 0xFF);
+ }
+
+ private static int compositeComponent(int fgC, int fgA, int bgC, int bgA, int a) {
+ if (a == 0) return 0;
+ return ((0xFF * fgC * fgA) + (bgC * bgA * (0xFF - fgA))) / (a * 0xFF);
+ }
+
+ /**
+ * Returns the luminance of a color as a float between {@code 0.0} and {@code 1.0}.
+ * <p>Defined as the Y component in the XYZ representation of {@code color}.</p>
+ */
+ @FloatRange(from = 0.0, to = 1.0)
+ public static double calculateLuminance(@ColorInt int color) {
+ final double[] result = getTempDouble3Array();
+ colorToXYZ(color, result);
+ // Luminance is the Y component
+ return result[1] / 100;
+ }
+
+ /**
+ * Returns the contrast ratio between {@code foreground} and {@code background}.
+ * {@code background} must be opaque.
+ * <p>
+ * Formula defined
+ * <a href="http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef">here</a>.
+ */
+ public static double calculateContrast(@ColorInt int foreground, @ColorInt int background) {
+ if (Color.alpha(background) != 255) {
+ throw new IllegalArgumentException("background can not be translucent: #"
+ + Integer.toHexString(background));
+ }
+ if (Color.alpha(foreground) < 255) {
+ // If the foreground is translucent, composite the foreground over the background
+ foreground = compositeColors(foreground, background);
+ }
+
+ final double luminance1 = calculateLuminance(foreground) + 0.05;
+ final double luminance2 = calculateLuminance(background) + 0.05;
+
+ // Now return the lighter luminance divided by the darker luminance
+ return Math.max(luminance1, luminance2) / Math.min(luminance1, luminance2);
+ }
+
+ /**
+ * Convert the ARGB color to its CIE Lab representative components.
+ *
+ * @param color the ARGB color to convert. The alpha component is ignored
+ * @param outLab 3-element array which holds the resulting LAB components
+ */
+ public static void colorToLAB(@ColorInt int color, @NonNull double[] outLab) {
+ RGBToLAB(Color.red(color), Color.green(color), Color.blue(color), outLab);
+ }
+
+ /**
+ * Convert RGB components to its CIE Lab representative components.
+ *
+ * <ul>
+ * <li>outLab[0] is L [0 ...1)</li>
+ * <li>outLab[1] is a [-128...127)</li>
+ * <li>outLab[2] is b [-128...127)</li>
+ * </ul>
+ *
+ * @param r red component value [0..255]
+ * @param g green component value [0..255]
+ * @param b blue component value [0..255]
+ * @param outLab 3-element array which holds the resulting LAB components
+ */
+ public static void RGBToLAB(@IntRange(from = 0x0, to = 0xFF) int r,
+ @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+ @NonNull double[] outLab) {
+ // First we convert RGB to XYZ
+ RGBToXYZ(r, g, b, outLab);
+ // outLab now contains XYZ
+ XYZToLAB(outLab[0], outLab[1], outLab[2], outLab);
+ // outLab now contains LAB representation
+ }
+
+ /**
+ * Convert the ARGB color to it's CIE XYZ representative components.
+ *
+ * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+ * 2° Standard Observer (1931).</p>
+ *
+ * <ul>
+ * <li>outXyz[0] is X [0 ...95.047)</li>
+ * <li>outXyz[1] is Y [0...100)</li>
+ * <li>outXyz[2] is Z [0...108.883)</li>
+ * </ul>
+ *
+ * @param color the ARGB color to convert. The alpha component is ignored
+ * @param outXyz 3-element array which holds the resulting LAB components
+ */
+ public static void colorToXYZ(@ColorInt int color, @NonNull double[] outXyz) {
+ RGBToXYZ(Color.red(color), Color.green(color), Color.blue(color), outXyz);
+ }
+
+ /**
+ * Convert RGB components to it's CIE XYZ representative components.
+ *
+ * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+ * 2° Standard Observer (1931).</p>
+ *
+ * <ul>
+ * <li>outXyz[0] is X [0 ...95.047)</li>
+ * <li>outXyz[1] is Y [0...100)</li>
+ * <li>outXyz[2] is Z [0...108.883)</li>
+ * </ul>
+ *
+ * @param r red component value [0..255]
+ * @param g green component value [0..255]
+ * @param b blue component value [0..255]
+ * @param outXyz 3-element array which holds the resulting XYZ components
+ */
+ public static void RGBToXYZ(@IntRange(from = 0x0, to = 0xFF) int r,
+ @IntRange(from = 0x0, to = 0xFF) int g, @IntRange(from = 0x0, to = 0xFF) int b,
+ @NonNull double[] outXyz) {
+ if (outXyz.length != 3) {
+ throw new IllegalArgumentException("outXyz must have a length of 3.");
+ }
+
+ double sr = r / 255.0;
+ sr = sr < 0.04045 ? sr / 12.92 : Math.pow((sr + 0.055) / 1.055, 2.4);
+ double sg = g / 255.0;
+ sg = sg < 0.04045 ? sg / 12.92 : Math.pow((sg + 0.055) / 1.055, 2.4);
+ double sb = b / 255.0;
+ sb = sb < 0.04045 ? sb / 12.92 : Math.pow((sb + 0.055) / 1.055, 2.4);
+
+ outXyz[0] = 100 * (sr * 0.4124 + sg * 0.3576 + sb * 0.1805);
+ outXyz[1] = 100 * (sr * 0.2126 + sg * 0.7152 + sb * 0.0722);
+ outXyz[2] = 100 * (sr * 0.0193 + sg * 0.1192 + sb * 0.9505);
+ }
+
+ /**
+ * Converts a color from CIE XYZ to CIE Lab representation.
+ *
+ * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+ * 2° Standard Observer (1931).</p>
+ *
+ * <ul>
+ * <li>outLab[0] is L [0 ...1)</li>
+ * <li>outLab[1] is a [-128...127)</li>
+ * <li>outLab[2] is b [-128...127)</li>
+ * </ul>
+ *
+ * @param x X component value [0...95.047)
+ * @param y Y component value [0...100)
+ * @param z Z component value [0...108.883)
+ * @param outLab 3-element array which holds the resulting Lab components
+ */
+ public static void XYZToLAB(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
+ @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
+ @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z,
+ @NonNull double[] outLab) {
+ if (outLab.length != 3) {
+ throw new IllegalArgumentException("outLab must have a length of 3.");
+ }
+ x = pivotXyzComponent(x / XYZ_WHITE_REFERENCE_X);
+ y = pivotXyzComponent(y / XYZ_WHITE_REFERENCE_Y);
+ z = pivotXyzComponent(z / XYZ_WHITE_REFERENCE_Z);
+ outLab[0] = Math.max(0, 116 * y - 16);
+ outLab[1] = 500 * (x - y);
+ outLab[2] = 200 * (y - z);
+ }
+
+ /**
+ * Converts a color from CIE Lab to CIE XYZ representation.
+ *
+ * <p>The resulting XYZ representation will use the D65 illuminant and the CIE
+ * 2° Standard Observer (1931).</p>
+ *
+ * <ul>
+ * <li>outXyz[0] is X [0 ...95.047)</li>
+ * <li>outXyz[1] is Y [0...100)</li>
+ * <li>outXyz[2] is Z [0...108.883)</li>
+ * </ul>
+ *
+ * @param l L component value [0...100)
+ * @param a A component value [-128...127)
+ * @param b B component value [-128...127)
+ * @param outXyz 3-element array which holds the resulting XYZ components
+ */
+ public static void LABToXYZ(@FloatRange(from = 0f, to = 100) final double l,
+ @FloatRange(from = -128, to = 127) final double a,
+ @FloatRange(from = -128, to = 127) final double b,
+ @NonNull double[] outXyz) {
+ final double fy = (l + 16) / 116;
+ final double fx = a / 500 + fy;
+ final double fz = fy - b / 200;
+
+ double tmp = Math.pow(fx, 3);
+ final double xr = tmp > XYZ_EPSILON ? tmp : (116 * fx - 16) / XYZ_KAPPA;
+ final double yr = l > XYZ_KAPPA * XYZ_EPSILON ? Math.pow(fy, 3) : l / XYZ_KAPPA;
+
+ tmp = Math.pow(fz, 3);
+ final double zr = tmp > XYZ_EPSILON ? tmp : (116 * fz - 16) / XYZ_KAPPA;
+
+ outXyz[0] = xr * XYZ_WHITE_REFERENCE_X;
+ outXyz[1] = yr * XYZ_WHITE_REFERENCE_Y;
+ outXyz[2] = zr * XYZ_WHITE_REFERENCE_Z;
+ }
+
+ /**
+ * Converts a color from CIE XYZ to its RGB representation.
+ *
+ * <p>This method expects the XYZ representation to use the D65 illuminant and the CIE
+ * 2° Standard Observer (1931).</p>
+ *
+ * @param x X component value [0...95.047)
+ * @param y Y component value [0...100)
+ * @param z Z component value [0...108.883)
+ * @return int containing the RGB representation
+ */
+ @ColorInt
+ public static int XYZToColor(@FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_X) double x,
+ @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Y) double y,
+ @FloatRange(from = 0f, to = XYZ_WHITE_REFERENCE_Z) double z) {
+ double r = (x * 3.2406 + y * -1.5372 + z * -0.4986) / 100;
+ double g = (x * -0.9689 + y * 1.8758 + z * 0.0415) / 100;
+ double b = (x * 0.0557 + y * -0.2040 + z * 1.0570) / 100;
+
+ r = r > 0.0031308 ? 1.055 * Math.pow(r, 1 / 2.4) - 0.055 : 12.92 * r;
+ g = g > 0.0031308 ? 1.055 * Math.pow(g, 1 / 2.4) - 0.055 : 12.92 * g;
+ b = b > 0.0031308 ? 1.055 * Math.pow(b, 1 / 2.4) - 0.055 : 12.92 * b;
+
+ return Color.rgb(
+ constrain((int) Math.round(r * 255), 0, 255),
+ constrain((int) Math.round(g * 255), 0, 255),
+ constrain((int) Math.round(b * 255), 0, 255));
+ }
+
+ /**
+ * Converts a color from CIE Lab to its RGB representation.
+ *
+ * @param l L component value [0...100]
+ * @param a A component value [-128...127]
+ * @param b B component value [-128...127]
+ * @return int containing the RGB representation
+ */
+ @ColorInt
+ public static int LABToColor(@FloatRange(from = 0f, to = 100) final double l,
+ @FloatRange(from = -128, to = 127) final double a,
+ @FloatRange(from = -128, to = 127) final double b) {
+ final double[] result = getTempDouble3Array();
+ LABToXYZ(l, a, b, result);
+ return XYZToColor(result[0], result[1], result[2]);
+ }
+
+ private static int constrain(int amount, int low, int high) {
+ return amount < low ? low : (amount > high ? high : amount);
+ }
+
+ private static double pivotXyzComponent(double component) {
+ return component > XYZ_EPSILON
+ ? Math.pow(component, 1 / 3.0)
+ : (XYZ_KAPPA * component + 16) / 116;
+ }
+
+ private static double[] getTempDouble3Array() {
+ double[] result = TEMP_ARRAY.get();
+ if (result == null) {
+ result = new double[3];
+ TEMP_ARRAY.set(result);
+ }
+ return result;
+ }
+
+ }
}
diff --git a/core/java/com/android/internal/view/IInputConnectionWrapper.java b/core/java/com/android/internal/view/IInputConnectionWrapper.java
index 3be15f3998ec..02b9db347f1a 100644
--- a/core/java/com/android/internal/view/IInputConnectionWrapper.java
+++ b/core/java/com/android/internal/view/IInputConnectionWrapper.java
@@ -16,6 +16,10 @@
package com.android.internal.view;
+import com.android.internal.annotations.GuardedBy;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -23,6 +27,7 @@ import android.os.Message;
import android.os.RemoteException;
import android.util.Log;
import android.view.KeyEvent;
+import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.CorrectionInfo;
import android.view.inputmethod.ExtractedTextRequest;
@@ -56,11 +61,16 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
private static final int DO_PERFORM_PRIVATE_COMMAND = 120;
private static final int DO_CLEAR_META_KEY_STATES = 130;
private static final int DO_REQUEST_UPDATE_CURSOR_ANCHOR_INFO = 140;
+ private static final int DO_REPORT_FINISH = 150;
- private WeakReference<InputConnection> mInputConnection;
+ @NonNull
+ private final WeakReference<InputConnection> mInputConnection;
private Looper mMainLooper;
private Handler mH;
+ private Object mLock = new Object();
+ @GuardedBy("mLock")
+ private boolean mFinished = false;
static class SomeArgs {
Object arg1;
@@ -86,6 +96,17 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
mH = new MyHandler(mMainLooper);
}
+ @Nullable
+ public InputConnection getInputConnection() {
+ return mInputConnection.get();
+ }
+
+ protected boolean isFinished() {
+ synchronized (mLock) {
+ return mFinished;
+ }
+ }
+
abstract protected boolean isActive();
/**
@@ -198,6 +219,10 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
seq, callback));
}
+ public void reportFinish() {
+ dispatchMessage(obtainMessage(DO_REPORT_FINISH));
+ }
+
void dispatchMessage(Message msg) {
// If we are calling this from the main thread, then we can call
// right through. Otherwise, we need to send the message to the
@@ -210,7 +235,7 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
mH.sendMessage(msg);
}
-
+
void executeMessage(Message msg) {
switch (msg.what) {
case DO_GET_TEXT_AFTER_CURSOR: {
@@ -473,6 +498,36 @@ public abstract class IInputConnectionWrapper extends IInputContext.Stub {
}
return;
}
+ case DO_REPORT_FINISH: {
+ // Note that we do not need to worry about race condition here, because 1) mFinished
+ // is updated only inside this block, and 2) the code here is running on a Handler
+ // hence we assume multiple DO_REPORT_FINISH messages will not be handled at the
+ // same time.
+ if (isFinished()) {
+ return;
+ }
+ try {
+ InputConnection ic = mInputConnection.get();
+ // Note we do NOT check isActive() here, because this is safe
+ // for an IME to call at any time, and we need to allow it
+ // through to clean up our state after the IME has switched to
+ // another client.
+ if (ic == null) {
+ return;
+ }
+ ic.finishComposingText();
+ // TODO: Make reportFinish() public method of InputConnection to remove this
+ // check.
+ if (ic instanceof BaseInputConnection) {
+ ((BaseInputConnection) ic).reportFinish();
+ }
+ } finally {
+ synchronized (mLock) {
+ mFinished = true;
+ }
+ }
+ return;
+ }
}
Log.w(TAG, "Unhandled message code: " + msg.what);
}
diff --git a/core/java/com/android/internal/widget/EditableInputConnection.java b/core/java/com/android/internal/widget/EditableInputConnection.java
index f211ff269339..a96b5a0d6ab1 100644
--- a/core/java/com/android/internal/widget/EditableInputConnection.java
+++ b/core/java/com/android/internal/widget/EditableInputConnection.java
@@ -83,8 +83,11 @@ public class EditableInputConnection extends BaseInputConnection {
return false;
}
+ /**
+ * @hide
+ */
@Override
- protected void reportFinish() {
+ public void reportFinish() {
super.reportFinish();
synchronized(this) {
diff --git a/core/java/com/android/internal/widget/FloatingToolbar.java b/core/java/com/android/internal/widget/FloatingToolbar.java
index 86820306d634..da223a64e2e8 100644
--- a/core/java/com/android/internal/widget/FloatingToolbar.java
+++ b/core/java/com/android/internal/widget/FloatingToolbar.java
@@ -41,6 +41,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.View.MeasureSpec;
import android.view.View.OnLayoutChangeListener;
+import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
@@ -878,6 +879,10 @@ public final class FloatingToolbar {
.start();
}
+ /**
+ * Defines the position of the floating toolbar popup panels when transition animation has
+ * stopped.
+ */
private void setPanelsStatesAtRestingPosition() {
mOverflowButton.setEnabled(true);
mOverflowPanel.awakenScrollBars();
@@ -1236,7 +1241,15 @@ public final class FloatingToolbar {
Math.min(
Math.max(MIN_OVERFLOW_SIZE, maxItemSize),
mOverflowPanel.getCount()));
- return actualSize * getLineHeight(mContext) + mOverflowButtonSize.getHeight();
+ int extension = 0;
+ if (actualSize < mOverflowPanel.getCount()) {
+ // The overflow will require scrolling to get to all the items.
+ // Extend the height so that part of the hidden items is displayed.
+ extension = (int) (getLineHeight(mContext) * 0.5f);
+ }
+ return actualSize * getLineHeight(mContext)
+ + mOverflowButtonSize.getHeight()
+ + extension;
}
private void setButtonTagAndClickListener(View menuItemButton, MenuItem menuItem) {
@@ -1446,6 +1459,7 @@ public final class FloatingToolbar {
OverflowPanel(FloatingToolbarPopup popup) {
super(Preconditions.checkNotNull(popup).mContext);
this.mPopup = popup;
+ setScrollBarDefaultDelayBeforeFade(ViewConfiguration.getScrollDefaultDelay() * 3);
}
@Override
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index c6db0ed6cb69..c685b0c14e2f 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -117,13 +117,10 @@ LOCAL_SRC_FILES:= \
android/graphics/Interpolator.cpp \
android/graphics/MaskFilter.cpp \
android/graphics/Matrix.cpp \
- android/graphics/MinikinSkia.cpp \
- android/graphics/MinikinUtils.cpp \
android/graphics/Movie.cpp \
android/graphics/NinePatch.cpp \
android/graphics/NinePatchPeeker.cpp \
android/graphics/Paint.cpp \
- android/graphics/PaintImpl.cpp \
android/graphics/Path.cpp \
android/graphics/PathMeasure.cpp \
android/graphics/PathEffect.cpp \
@@ -135,7 +132,6 @@ LOCAL_SRC_FILES:= \
android/graphics/Shader.cpp \
android/graphics/SurfaceTexture.cpp \
android/graphics/Typeface.cpp \
- android/graphics/TypefaceImpl.cpp \
android/graphics/Utils.cpp \
android/graphics/Xfermode.cpp \
android/graphics/YuvToJpegEncoder.cpp \
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 43e26b332f11..27b98306b72b 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -1,7 +1,6 @@
#define LOG_TAG "Bitmap"
#include "Bitmap.h"
-#include "Paint.h"
#include "SkBitmap.h"
#include "SkPixelRef.h"
#include "SkImageEncoder.h"
@@ -18,6 +17,7 @@
#include "android_nio_utils.h"
#include "CreateJavaOutputStreamAdaptor.h"
#include <Caches.h>
+#include <hwui/Paint.h>
#include "core_jni_helpers.h"
diff --git a/core/jni/android/graphics/Camera.cpp b/core/jni/android/graphics/Camera.cpp
index 6fcf6892d490..76d685149ec4 100644
--- a/core/jni/android/graphics/Camera.cpp
+++ b/core/jni/android/graphics/Camera.cpp
@@ -3,8 +3,8 @@
#include "SkCamera.h"
-#include "Canvas.h"
#include "GraphicsJNI.h"
+#include <hwui/Canvas.h>
static jfieldID gNativeInstanceFieldID;
diff --git a/core/jni/android/graphics/CanvasProperty.cpp b/core/jni/android/graphics/CanvasProperty.cpp
index 728bc1c3677e..c841d6a5125a 100644
--- a/core/jni/android/graphics/CanvasProperty.cpp
+++ b/core/jni/android/graphics/CanvasProperty.cpp
@@ -16,9 +16,9 @@
#include "jni.h"
#include "GraphicsJNI.h"
-#include "Paint.h"
#include <core_jni_helpers.h>
+#include <hwui/Paint.h>
#include <utils/RefBase.h>
#include <CanvasProperty.h>
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 2e974a3ecaa3..6dc251c87e5e 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -31,9 +31,9 @@
#include <androidfw/AssetManager.h>
#include "Utils.h"
-#include "TypefaceImpl.h"
+#include <hwui/MinikinSkia.h>
+#include <hwui/Typeface.h>
#include <minikin/FontFamily.h>
-#include "MinikinSkia.h"
#include <memory>
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index bd01c73adf80..1ead6188a8aa 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -7,13 +7,13 @@
#include "JNIHelp.h"
#include "GraphicsJNI.h"
-#include "Canvas.h"
#include "SkCanvas.h"
#include "SkDevice.h"
#include "SkMath.h"
#include "SkRegion.h"
#include <android_runtime/AndroidRuntime.h>
#include <cutils/ashmem.h>
+#include <hwui/Canvas.h>
#include <Caches.h>
#include <TextureCache.h>
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index e99a3ffa2a47..5baa8f8740c2 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -11,15 +11,15 @@
#include "SkPoint.h"
#include "SkRect.h"
#include "SkImageDecoder.h"
-#include <Canvas.h>
#include <jni.h>
+#include <hwui/Canvas.h>
class SkBitmapRegionDecoder;
class SkCanvas;
namespace android {
class Paint;
-struct TypefaceImpl;
+struct Typeface;
}
class GraphicsJNI {
diff --git a/core/jni/android/graphics/Movie.cpp b/core/jni/android/graphics/Movie.cpp
index 498c5902e5fd..71988f9cf44d 100644
--- a/core/jni/android/graphics/Movie.cpp
+++ b/core/jni/android/graphics/Movie.cpp
@@ -1,7 +1,5 @@
-#include "Canvas.h"
#include "CreateJavaOutputStreamAdaptor.h"
#include "GraphicsJNI.h"
-#include "Paint.h"
#include "ScopedLocalRef.h"
#include "SkFrontBufferedStream.h"
#include "SkMovie.h"
@@ -12,6 +10,8 @@
#include <androidfw/Asset.h>
#include <androidfw/ResourceTypes.h>
+#include <hwui/Canvas.h>
+#include <hwui/Paint.h>
#include <jni.h>
#include <netinet/in.h>
diff --git a/core/jni/android/graphics/NinePatch.cpp b/core/jni/android/graphics/NinePatch.cpp
index 3ccbb35cc960..4f2f3897469c 100644
--- a/core/jni/android/graphics/NinePatch.cpp
+++ b/core/jni/android/graphics/NinePatch.cpp
@@ -19,12 +19,12 @@
#define LOG_NDEBUG 1
#include <androidfw/ResourceTypes.h>
+#include <hwui/Canvas.h>
+#include <hwui/Paint.h>
#include <utils/Log.h>
#include <ResourceCache.h>
-#include "Paint.h"
-#include "Canvas.h"
#include "SkCanvas.h"
#include "SkRegion.h"
#include "GraphicsJNI.h"
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index d00e94ca4fd9..27d8fed51e8a 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -37,13 +37,13 @@
#include "unicode/ushape.h"
#include "utils/Blur.h"
+#include <hwui/MinikinSkia.h>
+#include <hwui/MinikinUtils.h>
+#include <hwui/Paint.h>
+#include <hwui/Typeface.h>
#include <minikin/GraphemeBreak.h>
#include <minikin/Measurement.h>
#include <unicode/utf16.h>
-#include "MinikinSkia.h"
-#include "MinikinUtils.h"
-#include "Paint.h"
-#include "TypefaceImpl.h"
#include <cassert>
#include <cstring>
@@ -402,8 +402,8 @@ namespace PaintGlue {
const int kElegantDescent = -500;
const int kElegantLeading = 0;
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
- typeface = TypefaceImpl_resolveDefault(typeface);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
+ typeface = Typeface::resolveDefault(typeface);
FakedFont baseFont = typeface->fFontCollection->baseFontFaked(typeface->fStyle);
float saveSkewX = paint->getTextSkewX();
bool savefakeBold = paint->isFakeBoldText();
@@ -474,7 +474,7 @@ namespace PaintGlue {
return descent - ascent + leading;
}
- static jfloat doTextAdvances(JNIEnv *env, Paint *paint, TypefaceImpl* typeface,
+ static jfloat doTextAdvances(JNIEnv *env, Paint *paint, Typeface* typeface,
const jchar *text, jint start, jint count, jint contextCount, jint bidiFlags,
jfloatArray advances, jint advancesIndex) {
NPE_CHECK_RETURN_ZERO(env, text);
@@ -510,7 +510,7 @@ namespace PaintGlue {
jcharArray text, jint index, jint count, jint contextIndex, jint contextCount,
jint bidiFlags, jfloatArray advances, jint advancesIndex) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
jchar* textArray = env->GetCharArrayElements(text, NULL);
jfloat result = doTextAdvances(env, paint, typeface, textArray + contextIndex,
index - contextIndex, count, contextCount, bidiFlags, advances, advancesIndex);
@@ -523,7 +523,7 @@ namespace PaintGlue {
jstring text, jint start, jint end, jint contextStart, jint contextEnd, jint bidiFlags,
jfloatArray advances, jint advancesIndex) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
jfloat result = doTextAdvances(env, paint, typeface, textArray + contextStart,
start - contextStart, end - start, contextEnd - contextStart, bidiFlags,
@@ -590,7 +590,7 @@ namespace PaintGlue {
SkPath tmpPath;
};
- static void getTextPath(JNIEnv* env, Paint* paint, TypefaceImpl* typeface, const jchar* text,
+ static void getTextPath(JNIEnv* env, Paint* paint, Typeface* typeface, const jchar* text,
jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
Layout layout;
MinikinUtils::doLayout(&layout, paint, bidiFlags, typeface, text, 0, count, count);
@@ -613,7 +613,7 @@ namespace PaintGlue {
jlong typefaceHandle, jint bidiFlags,
jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
const jchar* textArray = env->GetCharArrayElements(text, NULL);
getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path);
@@ -624,7 +624,7 @@ namespace PaintGlue {
jlong typefaceHandle, jint bidiFlags,
jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path);
@@ -648,7 +648,7 @@ namespace PaintGlue {
return paint->getLooper() && paint->getLooper()->asABlurShadow(NULL);
}
- static int breakText(JNIEnv* env, const Paint& paint, TypefaceImpl* typeface, const jchar text[],
+ static int breakText(JNIEnv* env, const Paint& paint, Typeface* typeface, const jchar text[],
int count, float maxWidth, jint bidiFlags, jfloatArray jmeasured,
const bool forwardScan) {
size_t measuredCount = 0;
@@ -685,7 +685,7 @@ namespace PaintGlue {
NPE_CHECK_RETURN_ZERO(env, jtext);
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
bool forwardTextDirection;
if (count < 0) {
@@ -714,7 +714,7 @@ namespace PaintGlue {
NPE_CHECK_RETURN_ZERO(env, jtext);
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
int count = env->GetStringLength(jtext);
const jchar* text = env->GetStringChars(jtext, NULL);
@@ -724,7 +724,7 @@ namespace PaintGlue {
}
static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds,
- const Paint& paint, TypefaceImpl* typeface, jint bidiFlags) {
+ const Paint& paint, Typeface* typeface, jint bidiFlags) {
SkRect r;
SkIRect ir;
@@ -743,7 +743,7 @@ namespace PaintGlue {
static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags);
env->ReleaseStringChars(text, textArray);
@@ -752,7 +752,7 @@ namespace PaintGlue {
static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
const jchar* textArray = env->GetCharArrayElements(text, NULL);
doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags);
env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
@@ -771,7 +771,7 @@ namespace PaintGlue {
static jboolean hasGlyph(JNIEnv *env, jclass, jlong paintHandle, jlong typefaceHandle,
jint bidiFlags, jstring string) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
ScopedStringChars str(env, string);
/* Start by rejecting unsupported base code point and variation selector pairs. */
@@ -820,7 +820,7 @@ namespace PaintGlue {
return nGlyphs > 0 && !layoutContainsNotdef(layout);
}
- static jfloat doRunAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
+ static jfloat doRunAdvance(const Paint* paint, Typeface* typeface, const jchar buf[],
jint start, jint count, jint bufSize, jboolean isRtl, jint offset) {
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
if (offset == count) {
@@ -837,7 +837,7 @@ namespace PaintGlue {
jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
jint contextEnd, jboolean isRtl, jint offset) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, NULL);
jfloat result = doRunAdvance(paint, typeface, textArray + contextStart,
start - contextStart, end - start, contextEnd - contextStart, isRtl,
@@ -846,7 +846,7 @@ namespace PaintGlue {
return result;
}
- static jint doOffsetForAdvance(const Paint* paint, TypefaceImpl* typeface, const jchar buf[],
+ static jint doOffsetForAdvance(const Paint* paint, Typeface* typeface, const jchar buf[],
jint start, jint count, jint bufSize, jboolean isRtl, jfloat advance) {
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
std::unique_ptr<float[]> advancesArray(new float[count]);
@@ -859,7 +859,7 @@ namespace PaintGlue {
jlong typefaceHandle, jcharArray text, jint start, jint end, jint contextStart,
jint contextEnd, jboolean isRtl, jfloat advance) {
const Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
jchar* textArray = (jchar*) env->GetPrimitiveArrayCritical(text, NULL);
jint result = doOffsetForAdvance(paint, typeface, textArray + contextStart,
start - contextStart, end - start, contextEnd - contextStart, isRtl, advance);
diff --git a/core/jni/android/graphics/Picture.cpp b/core/jni/android/graphics/Picture.cpp
index 6e83f1b19f5f..07e14a211e64 100644
--- a/core/jni/android/graphics/Picture.cpp
+++ b/core/jni/android/graphics/Picture.cpp
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-#include "Canvas.h"
#include "Picture.h"
#include "SkStream.h"
#include <memory>
+#include <hwui/Canvas.h>
namespace android {
diff --git a/core/jni/android/graphics/Rasterizer.cpp b/core/jni/android/graphics/Rasterizer.cpp
index a106ecfeb65f..3784f0d8a220 100644
--- a/core/jni/android/graphics/Rasterizer.cpp
+++ b/core/jni/android/graphics/Rasterizer.cpp
@@ -22,10 +22,11 @@
#include "jni.h"
#include "GraphicsJNI.h"
-#include "Paint.h"
#include "SkLayerRasterizer.h"
#include "core_jni_helpers.h"
+#include <hwui/Paint.h>
+
// Rasterizer.java holds a pointer (jlong) to this guy
class NativeRasterizer {
public:
diff --git a/core/jni/android/graphics/Typeface.cpp b/core/jni/android/graphics/Typeface.cpp
index e97b768dd0cc..9a53cadf355b 100644
--- a/core/jni/android/graphics/Typeface.cpp
+++ b/core/jni/android/graphics/Typeface.cpp
@@ -20,50 +20,57 @@
#include "GraphicsJNI.h"
#include "ScopedPrimitiveArray.h"
#include "SkTypeface.h"
-#include "TypefaceImpl.h"
#include <android_runtime/android_util_AssetManager.h>
#include <androidfw/AssetManager.h>
+#include <hwui/Typeface.h>
using namespace android;
static jlong Typeface_createFromTypeface(JNIEnv* env, jobject, jlong familyHandle, jint style) {
- TypefaceImpl* family = reinterpret_cast<TypefaceImpl*>(familyHandle);
- TypefaceImpl* face = TypefaceImpl_createFromTypeface(family, (SkTypeface::Style)style);
+ Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
+ Typeface* face = Typeface::createFromTypeface(family, (SkTypeface::Style)style);
// TODO: the following logic shouldn't be necessary, the above should always succeed.
// Try to find the closest matching font, using the standard heuristic
if (NULL == face) {
- face = TypefaceImpl_createFromTypeface(family, (SkTypeface::Style)(style ^ SkTypeface::kItalic));
+ face = Typeface::createFromTypeface(family, (SkTypeface::Style)(style ^ SkTypeface::kItalic));
}
for (int i = 0; NULL == face && i < 4; i++) {
- face = TypefaceImpl_createFromTypeface(family, (SkTypeface::Style)i);
+ face = Typeface::createFromTypeface(family, (SkTypeface::Style)i);
}
return reinterpret_cast<jlong>(face);
}
static jlong Typeface_createWeightAlias(JNIEnv* env, jobject, jlong familyHandle, jint weight) {
- TypefaceImpl* family = reinterpret_cast<TypefaceImpl*>(familyHandle);
- TypefaceImpl* face = TypefaceImpl_createWeightAlias(family, weight);
+ Typeface* family = reinterpret_cast<Typeface*>(familyHandle);
+ Typeface* face = Typeface::createWeightAlias(family, weight);
return reinterpret_cast<jlong>(face);
}
static void Typeface_unref(JNIEnv* env, jobject obj, jlong faceHandle) {
- TypefaceImpl* face = reinterpret_cast<TypefaceImpl*>(faceHandle);
- TypefaceImpl_unref(face);
+ Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+ if (face != NULL) {
+ face->unref();
+ }
}
static jint Typeface_getStyle(JNIEnv* env, jobject obj, jlong faceHandle) {
- TypefaceImpl* face = reinterpret_cast<TypefaceImpl*>(faceHandle);
- return TypefaceImpl_getStyle(face);
+ Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+ return face->fSkiaStyle;
}
static jlong Typeface_createFromArray(JNIEnv *env, jobject, jlongArray familyArray) {
ScopedLongArrayRO families(env, familyArray);
- return reinterpret_cast<jlong>(TypefaceImpl_createFromFamilies(families.get(), families.size()));
+ std::vector<FontFamily*> familyVec;
+ for (size_t i = 0; i < families.size(); i++) {
+ FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
+ familyVec.push_back(family);
+ }
+ return reinterpret_cast<jlong>(Typeface::createFromFamilies(familyVec));
}
static void Typeface_setDefault(JNIEnv *env, jobject, jlong faceHandle) {
- TypefaceImpl* face = reinterpret_cast<TypefaceImpl*>(faceHandle);
- return TypefaceImpl_setDefault(face);
+ Typeface* face = reinterpret_cast<Typeface*>(faceHandle);
+ return Typeface::setDefault(face);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/core/jni/android/graphics/pdf/PdfDocument.cpp b/core/jni/android/graphics/pdf/PdfDocument.cpp
index 5d496e5ccae9..88e37e5545b5 100644
--- a/core/jni/android/graphics/pdf/PdfDocument.cpp
+++ b/core/jni/android/graphics/pdf/PdfDocument.cpp
@@ -19,7 +19,6 @@
#include "core_jni_helpers.h"
#include <vector>
-#include "Canvas.h"
#include "CreateJavaOutputStreamAdaptor.h"
#include "SkDocument.h"
@@ -28,6 +27,8 @@
#include "SkStream.h"
#include "SkRect.h"
+#include <hwui/Canvas.h>
+
namespace android {
struct PageRecord {
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index cf73316d494b..ded4daca0707 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -19,15 +19,14 @@
#include "core_jni_helpers.h"
#include <androidfw/ResourceTypes.h>
-#include <Canvas.h>
+#include <hwui/Canvas.h>
+#include <hwui/Paint.h>
+#include <hwui/Typeface.h>
+#include <minikin/Layout.h>
#include "Bitmap.h"
#include "SkDrawFilter.h"
#include "SkGraphics.h"
-#include "Paint.h"
-#include "TypefaceImpl.h"
-
-#include "MinikinUtils.h"
namespace android {
@@ -475,111 +474,13 @@ static void drawBitmapMesh(JNIEnv* env, jobject, jlong canvasHandle, jobject jbi
vertA.ptr(), colorA.ptr(), paint);
}
-static void simplifyPaint(int color, SkPaint* paint) {
- paint->setColor(color);
- paint->setShader(nullptr);
- paint->setColorFilter(nullptr);
- paint->setLooper(nullptr);
- paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
- paint->setStrokeJoin(SkPaint::kRound_Join);
- paint->setLooper(nullptr);
-}
-
-class DrawTextFunctor {
-public:
- DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
- const SkPaint& paint, float x, float y, MinikinRect& bounds,
- float totalAdvance)
- : layout(layout), canvas(canvas), glyphs(glyphs), pos(pos), paint(paint),
- x(x), y(y), bounds(bounds), totalAdvance(totalAdvance) { }
-
- void operator()(size_t start, size_t end) {
- if (canvas->drawTextAbsolutePos()) {
- for (size_t i = start; i < end; i++) {
- glyphs[i] = layout.getGlyphId(i);
- pos[2 * i] = x + layout.getX(i);
- pos[2 * i + 1] = y + layout.getY(i);
- }
- } else {
- for (size_t i = start; i < end; i++) {
- glyphs[i] = layout.getGlyphId(i);
- pos[2 * i] = layout.getX(i);
- pos[2 * i + 1] = layout.getY(i);
- }
- }
-
- size_t glyphCount = end - start;
-
- if (CC_UNLIKELY(canvas->isHighContrastText() && paint.getAlpha() != 0)) {
- // high contrast draw path
- int color = paint.getColor();
- int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
- bool darken = channelSum < (128 * 3);
-
- // outline
- SkPaint outlinePaint(paint);
- simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
- outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
- canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
- bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
-
- // inner
- SkPaint innerPaint(paint);
- simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
- innerPaint.setStyle(SkPaint::kFill_Style);
- canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
- bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
- } else {
- // standard draw path
- canvas->drawText(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
- bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom,
- totalAdvance);
- }
- }
-private:
- const Layout& layout;
- Canvas* canvas;
- uint16_t* glyphs;
- float* pos;
- const SkPaint& paint;
- float x;
- float y;
- MinikinRect& bounds;
- float totalAdvance;
-};
-
-void drawText(Canvas* canvas, const uint16_t* text, int start, int count, int contextCount,
- float x, float y, int bidiFlags, const Paint& origPaint, TypefaceImpl* typeface) {
- // minikin may modify the original paint
- Paint paint(origPaint);
-
- Layout layout;
- MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
-
- size_t nGlyphs = layout.nGlyphs();
- std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
- std::unique_ptr<float[]> pos(new float[nGlyphs * 2]);
-
- x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
-
- MinikinRect bounds;
- layout.getBounds(&bounds);
- if (!canvas->drawTextAbsolutePos()) {
- bounds.offset(x, y);
- }
-
- DrawTextFunctor f(layout, canvas, glyphs.get(), pos.get(),
- paint, x, y, bounds, layout.getAdvance());
- MinikinUtils::forFontRun(layout, &paint, f);
-}
-
static void drawTextChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
jint index, jint count, jfloat x, jfloat y, jint bidiFlags,
jlong paintHandle, jlong typefaceHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
jchar* jchars = env->GetCharArrayElements(text, NULL);
- drawText(get_canvas(canvasHandle), jchars + index, 0, count, count, x, y,
+ get_canvas(canvasHandle)->drawText(jchars + index, 0, count, count, x, y,
bidiFlags, *paint, typeface);
env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
}
@@ -588,10 +489,10 @@ static void drawTextString(JNIEnv* env, jobject, jlong canvasHandle, jstring tex
jint start, jint end, jfloat x, jfloat y, jint bidiFlags,
jlong paintHandle, jlong typefaceHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
const int count = end - start;
const jchar* jchars = env->GetStringChars(text, NULL);
- drawText(get_canvas(canvasHandle), jchars + start, 0, count, count, x, y,
+ get_canvas(canvasHandle)->drawText(jchars + start, 0, count, count, x, y,
bidiFlags, *paint, typeface);
env->ReleaseStringChars(text, jchars);
}
@@ -600,11 +501,11 @@ static void drawTextRunChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArra
jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y,
jboolean isRtl, jlong paintHandle, jlong typefaceHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
const int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
jchar* jchars = env->GetCharArrayElements(text, NULL);
- drawText(get_canvas(canvasHandle), jchars + contextIndex, index - contextIndex, count,
+ get_canvas(canvasHandle)->drawText(jchars + contextIndex, index - contextIndex, count,
contextCount, x, y, bidiFlags, *paint, typeface);
env->ReleaseCharArrayElements(text, jchars, JNI_ABORT);
}
@@ -614,70 +515,28 @@ static void drawTextRunString(JNIEnv* env, jobject obj, jlong canvasHandle, jstr
jfloat x, jfloat y, jboolean isRtl, jlong paintHandle,
jlong typefaceHandle) {
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
int bidiFlags = isRtl ? kBidi_Force_RTL : kBidi_Force_LTR;
jint count = end - start;
jint contextCount = contextEnd - contextStart;
const jchar* jchars = env->GetStringChars(text, NULL);
- drawText(get_canvas(canvasHandle), jchars + contextStart, start - contextStart, count,
+ get_canvas(canvasHandle)->drawText(jchars + contextStart, start - contextStart, count,
contextCount, x, y, bidiFlags, *paint, typeface);
env->ReleaseStringChars(text, jchars);
}
-class DrawTextOnPathFunctor {
-public:
- DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
- float vOffset, const Paint& paint, const SkPath& path)
- : layout(layout), canvas(canvas), hOffset(hOffset), vOffset(vOffset),
- paint(paint), path(path) {
- }
- void operator()(size_t start, size_t end) {
- uint16_t glyphs[1];
- for (size_t i = start; i < end; i++) {
- glyphs[0] = layout.getGlyphId(i);
- float x = hOffset + layout.getX(i);
- float y = vOffset + layout.getY(i);
- canvas->drawTextOnPath(glyphs, 1, path, x, y, paint);
- }
- }
-private:
- const Layout& layout;
- Canvas* canvas;
- float hOffset;
- float vOffset;
- const Paint& paint;
- const SkPath& path;
-};
-
-static void drawTextOnPath(Canvas* canvas, const uint16_t* text, int count, int bidiFlags,
- const SkPath& path, float hOffset, float vOffset,
- const Paint& paint, TypefaceImpl* typeface) {
- Paint paintCopy(paint);
- Layout layout;
- MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
- hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
-
- // Set align to left for drawing, as we don't want individual
- // glyphs centered or right-aligned; the offset above takes
- // care of all alignment.
- paintCopy.setTextAlign(Paint::kLeft_Align);
-
- DrawTextOnPathFunctor f(layout, canvas, hOffset, vOffset, paintCopy, path);
- MinikinUtils::forFontRun(layout, &paintCopy, f);
-}
-
static void drawTextOnPathChars(JNIEnv* env, jobject, jlong canvasHandle, jcharArray text,
jint index, jint count, jlong pathHandle, jfloat hOffset,
jfloat vOffset, jint bidiFlags, jlong paintHandle,
jlong typefaceHandle) {
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
jchar* jchars = env->GetCharArrayElements(text, NULL);
- drawTextOnPath(get_canvas(canvasHandle), jchars + index, count, bidiFlags, *path,
+ get_canvas(canvasHandle)->drawTextOnPath(jchars + index, count, bidiFlags, *path,
hOffset, vOffset, *paint, typeface);
env->ReleaseCharArrayElements(text, jchars, 0);
@@ -688,12 +547,12 @@ static void drawTextOnPathString(JNIEnv* env, jobject, jlong canvasHandle, jstri
jint bidiFlags, jlong paintHandle, jlong typefaceHandle) {
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
Paint* paint = reinterpret_cast<Paint*>(paintHandle);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
+ Typeface* typeface = reinterpret_cast<Typeface*>(typefaceHandle);
const jchar* jchars = env->GetStringChars(text, NULL);
int count = env->GetStringLength(text);
- drawTextOnPath(get_canvas(canvasHandle), jchars, count, bidiFlags, *path,
+ get_canvas(canvasHandle)->drawTextOnPath(jchars, count, bidiFlags, *path,
hOffset, vOffset, *paint, typeface);
env->ReleaseStringChars(text, jchars);
diff --git a/core/jni/android_graphics_drawable_VectorDrawable.cpp b/core/jni/android_graphics_drawable_VectorDrawable.cpp
index e17de17e06cc..a2662f9e81c7 100644
--- a/core/jni/android_graphics_drawable_VectorDrawable.cpp
+++ b/core/jni/android_graphics_drawable_VectorDrawable.cpp
@@ -19,9 +19,10 @@
#include "core_jni_helpers.h"
#include "log/log.h"
-#include "Paint.h"
#include "VectorDrawable.h"
+#include <hwui/Paint.h>
+
namespace android {
using namespace uirenderer;
using namespace uirenderer::VectorDrawable;
diff --git a/core/jni/android_net_NetUtils.cpp b/core/jni/android_net_NetUtils.cpp
index 880a79cc4f6d..23647871df87 100644
--- a/core/jni/android_net_NetUtils.cpp
+++ b/core/jni/android_net_NetUtils.cpp
@@ -41,7 +41,6 @@
extern "C" {
int ifc_enable(const char *ifname);
int ifc_disable(const char *ifname);
-int ifc_reset_connections(const char *ifname, int reset_mask);
}
#define NETUTILS_PKG_NAME "android/net/NetworkUtils"
@@ -50,21 +49,6 @@ namespace android {
static const uint16_t kDhcpClientPort = 68;
-static jint android_net_utils_resetConnections(JNIEnv* env, jobject clazz,
- jstring ifname, jint mask)
-{
- int result;
-
- const char *nameStr = env->GetStringUTFChars(ifname, NULL);
-
- ALOGD("android_net_utils_resetConnections in env=%p clazz=%p iface=%s mask=0x%x\n",
- env, clazz, nameStr, mask);
-
- result = ::ifc_reset_connections(nameStr, mask);
- env->ReleaseStringUTFChars(ifname, nameStr);
- return (jint)result;
-}
-
static void android_net_utils_attachDhcpFilter(JNIEnv *env, jobject clazz, jobject javaFd)
{
uint32_t ip_offset = sizeof(ether_header);
@@ -181,7 +165,6 @@ static jboolean android_net_utils_queryUserAccess(JNIEnv *env, jobject thiz, jin
*/
static const JNINativeMethod gNetworkUtilMethods[] = {
/* name, signature, funcPtr */
- { "resetConnections", "(Ljava/lang/String;I)I", (void *)android_net_utils_resetConnections },
{ "bindProcessToNetwork", "(I)Z", (void*) android_net_utils_bindProcessToNetwork },
{ "getBoundNetworkForProcess", "()I", (void*) android_net_utils_getBoundNetworkForProcess },
{ "bindProcessToNetworkForHostResolution", "(I)Z", (void*) android_net_utils_bindProcessToNetworkForHostResolution },
diff --git a/core/jni/android_text_StaticLayout.cpp b/core/jni/android_text_StaticLayout.cpp
index 83f76eab053d..13e4f1a59fd8 100644
--- a/core/jni/android_text_StaticLayout.cpp
+++ b/core/jni/android_text_StaticLayout.cpp
@@ -32,10 +32,12 @@
#include "SkPaint.h"
#include "SkTypeface.h"
-#include "MinikinSkia.h"
-#include "MinikinUtils.h"
-#include "Paint.h"
-#include "minikin/LineBreaker.h"
+#include <hwui/MinikinSkia.h>
+#include <hwui/MinikinUtils.h>
+#include <hwui/Paint.h>
+#include <minikin/FontCollection.h>
+#include <minikin/LineBreaker.h>
+#include <minikin/MinikinFont.h>
namespace android {
@@ -154,7 +156,7 @@ static jfloat nAddStyleRun(JNIEnv* env, jclass, jlong nativePtr,
jlong nativePaint, jlong nativeTypeface, jint start, jint end, jboolean isRtl) {
LineBreaker* b = reinterpret_cast<LineBreaker*>(nativePtr);
Paint* paint = reinterpret_cast<Paint*>(nativePaint);
- TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(nativeTypeface);
+ Typeface* typeface = reinterpret_cast<Typeface*>(nativeTypeface);
FontCollection *font;
MinikinPaint minikinPaint;
FontStyle style = MinikinUtils::prepareMinikinPaint(&minikinPaint, &font, paint, typeface);
diff --git a/core/jni/android_view_DisplayListCanvas.cpp b/core/jni/android_view_DisplayListCanvas.cpp
index c87a7701786c..6aac0e4975e8 100644
--- a/core/jni/android_view_DisplayListCanvas.cpp
+++ b/core/jni/android_view_DisplayListCanvas.cpp
@@ -28,11 +28,11 @@
#include <SkRegion.h>
-#include <Canvas.h>
#include <Rect.h>
#include <RenderNode.h>
#include <CanvasProperty.h>
-#include <Paint.h>
+#include <hwui/Canvas.h>
+#include <hwui/Paint.h>
#include <renderthread/RenderProxy.h>
#include "core_jni_helpers.h"
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 3a0ddc9fa825..6b774e8f23e3 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -24,8 +24,8 @@
#include <android_runtime/android_graphics_SurfaceTexture.h>
#include <gui/GLConsumer.h>
+#include <hwui/Paint.h>
-#include <Paint.h>
#include <SkBitmap.h>
#include <SkCanvas.h>
#include <SkMatrix.h>
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index a7ac5b8aae66..79b518fe53ee 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -30,7 +30,7 @@
#include <RenderNode.h>
#include <renderthread/CanvasContext.h>
#include <TreeInfo.h>
-#include <Paint.h>
+#include <hwui/Paint.h>
#include "core_jni_helpers.h"
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index c838d038c4c2..d8233a0ea34b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -309,6 +309,16 @@ static void nativeSetWindowCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
}
}
+static void nativeSetFinalCrop(JNIEnv* env, jclass clazz, jlong nativeObject,
+ jint l, jint t, jint r, jint b) {
+ SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+ Rect crop(l, t, r, b);
+ status_t err = ctrl->setFinalCrop(crop);
+ if (err < 0 && err != NO_INIT) {
+ doThrowIAE(env);
+ }
+}
+
static void nativeSetLayerStack(JNIEnv* env, jclass clazz, jlong nativeObject, jint layerStack) {
SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
status_t err = ctrl->setLayerStack(layerStack);
@@ -630,6 +640,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
(void*)nativeSetFlags },
{"nativeSetWindowCrop", "(JIIII)V",
(void*)nativeSetWindowCrop },
+ {"nativeSetFinalCrop", "(JIIII)V",
+ (void*)nativeSetFinalCrop },
{"nativeSetLayerStack", "(JI)V",
(void*)nativeSetLayerStack },
{"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 30607dd71efa..60f0544859bd 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -417,6 +417,7 @@
<protected-broadcast android:name="android.os.action.ACTION_EFFECTS_SUPPRESSOR_CHANGED" />
<protected-broadcast android:name="android.os.action.LIGHT_DEVICE_IDLE_MODE_CHANGED" />
<protected-broadcast android:name="android.os.storage.action.VOLUME_STATE_CHANGED" />
+ <protected-broadcast android:name="android.os.storage.action.DISK_SCANNED" />
<protected-broadcast android:name="com.android.server.action.UPDATE_TWILIGHT_STATE" />
<protected-broadcast android:name="com.android.server.device_idle.STEP_IDLE_STATE" />
<protected-broadcast android:name="com.android.server.device_idle.STEP_LIGHT_IDLE_STATE" />
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index 2a4aa9670fc6..30b5a790c1ae 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -28,7 +28,7 @@
android:orientation="horizontal"
android:gravity="center_vertical"
android:visibility="gone"
- android:background="#ffeeeeee"
+ android:background="@color/notification_action_list"
>
<!-- actions will be added here -->
</LinearLayout>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 50c6f0cdfd01..be140a515ae6 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Meer opsies"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s - %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s-%2$s%3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interne geheue"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kaart"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g>-SD-kaart"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-datastokkie"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 4a13c7c7630a..a87090a1ec3f 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ተጨማሪ አማራጮች"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s፣ %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s፣ %2$s፣ %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"ውስጣዊ ማከማቻ"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD ካርድ"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> ኤስዲ ካርድ"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"የዩኤስቢ አንጻፊ"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index f32cec85a252..01d47cfef78e 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -1260,7 +1260,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"المزيد من الخيارات"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s، %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s، %2$s، %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"وحدة تخزين داخلية"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"‏بطاقة SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"‏بطاقة SD من <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"‏محرك أقراص USB"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 39e56b68a6a2..58d81b2d790a 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Əlavə seçimlər"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Daxili yaddaş"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD kart"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD kart"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB drayv"</string>
diff --git a/core/res/res/values-b+sr+Latn/strings.xml b/core/res/res/values-b+sr+Latn/strings.xml
index 4aba580345b6..b8c6fd392787 100644
--- a/core/res/res/values-b+sr+Latn/strings.xml
+++ b/core/res/res/values-b+sr+Latn/strings.xml
@@ -905,10 +905,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Izmenite pomoću aplikacije %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Delite pomoću"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Delite pomoću aplikacije %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Pošaljite pomoću:"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Pošaljite pomoću: %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Izaberite aplikaciju za početnu stranicu"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Koristite %1$s za početnu"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Podrazumevano koristi za ovu radnju."</string>
@@ -1070,8 +1068,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBIJ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promenite tastaturu"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Druge tastature"</string>
<string name="show_ime" msgid="2506087537466597099">"Zadrži ga na ekranu dok je fizička tastatura aktivna"</string>
<string name="hardware" msgid="194658061510127999">"Prikaži virtuelnu tastaturu"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Izbor rasporeda tastature"</string>
@@ -1236,7 +1233,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Još opcija"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interna memorija"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD kartica"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD kartica"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB disk"</string>
diff --git a/core/res/res/values-be-rBY/strings.xml b/core/res/res/values-be-rBY/strings.xml
index 03d6f89bf608..502e1e92108e 100644
--- a/core/res/res/values-be-rBY/strings.xml
+++ b/core/res/res/values-be-rBY/strings.xml
@@ -911,10 +911,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Рэдагаваць з дапамогай %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Падзяліцца праз"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Падзяліцца праз %s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Адправіць з дапамогай"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Адправіць з дапамогай %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Выберыце праграму Галоўнай старонкі"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Выкарыстоўваць %1$s у якасці праграмы Галоўнай старонкі"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Выкарыстоўваць па змаўчанні для гэтага дзеяння."</string>
@@ -1078,8 +1076,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"АБАГУЛІЦЬ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"АДХІЛІЦЬ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Змяніць клавіятуру"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Іншыя праграмныя клавіятуры"</string>
<string name="show_ime" msgid="2506087537466597099">"Захоўваць яе на экране ў той час, калі фізічная клавіятура актыўная"</string>
<string name="hardware" msgid="194658061510127999">"Паказаць віртуальную клавіятуру"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Выбраць раскладку клавіятуры"</string>
@@ -1245,7 +1242,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Больш налад"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Унутраная памяць"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-карта"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD-карта <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-дыск"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 21b5590a6b05..62d0d3725abc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Още опции"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"„%1$s“ – %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"„%1$s“, „%2$s“ – %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Вътрешно хранилище"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD карта"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD карта от <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB устройство"</string>
diff --git a/core/res/res/values-bn-rBD/strings.xml b/core/res/res/values-bn-rBD/strings.xml
index f63f9ce36ada..cbe8ecaa9dd6 100644
--- a/core/res/res/values-bn-rBD/strings.xml
+++ b/core/res/res/values-bn-rBD/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s দিয়ে সম্পাদনা করুন"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"এর সাথে শেয়ার করুন"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s এর সাথে শেয়ার করুন"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"এটি ব্যবহার করে পাঠান"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s ব্যবহার করে পাঠান"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"একটি হোম অ্যাপ্লিকেশন নির্বাচন করুন"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"হোম হিসাবে %1$s ব্যবহার করুন"</string>
<string name="alwaysUse" msgid="4583018368000610438">"এই ক্রিয়াটির জন্য এটিকে ডিফল্টরুপে ব্যবহার করুন৷"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"শেয়ার করুন"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"অস্বীকার করুন"</string>
<string name="select_input_method" msgid="8547250819326693584">"কীবোর্ড পরিবর্তন করুন"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"অন্যান্য কীবোর্ড"</string>
<string name="show_ime" msgid="2506087537466597099">"ফিজিক্যাল কীবোর্ড সক্রিয় থাকার সময় এটিকে স্ক্রীনে রাখুন"</string>
<string name="hardware" msgid="194658061510127999">"ভার্চুয়াল কীবোর্ড দেখান"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"কীবোর্ডের লেআউট নির্বাচন করুন"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"আরো বিকল্প"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"অভ্যন্তরীণ সঞ্চয়স্থান"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD কার্ড"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD কার্ড"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ড্রাইভ"</string>
diff --git a/core/res/res/values-bs-rBA/strings.xml b/core/res/res/values-bs-rBA/strings.xml
index 631a62716f32..6e7d8d2a2320 100644
--- a/core/res/res/values-bs-rBA/strings.xml
+++ b/core/res/res/values-bs-rBA/strings.xml
@@ -905,10 +905,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Uredi koristeći %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Podijeli koristeći"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Podijeli koristeći %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Pošalji koristeći"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Pošalji koristeći %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Odaberi glavnu aplikaciju"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Koristi %1$s kao glavnu aplikaciju"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Koristiti kao zadanu rezoluciju za ovu akciju."</string>
@@ -1070,8 +1068,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PODIJELI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODBACI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Promijeni tastaturu"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Ostale tastature"</string>
<string name="show_ime" msgid="2506087537466597099">"Prikaži na ekranu dok je fizička tastatura aktivna"</string>
<string name="hardware" msgid="194658061510127999">"Prikaži virtualnu tastaturu"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Odaberite raspored tastature"</string>
@@ -1236,7 +1233,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Više opcija"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interna pohrana"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD kartica"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD kartica"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB disk"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 7183f4b67b6d..9044a1ae4faf 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Més opcions"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Emmagatzematge intern"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Targeta SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Targeta SD de: <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unitat USB"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index a2315314367e..237d44d3645e 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -1242,7 +1242,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Další možnosti"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s – %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s – %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interní úložiště"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Interní sdílené úložiště"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"Karta SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD karta <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Jednotka USB"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 60a1764b9b3d..8875eade3315 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Flere valgmuligheder"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Intern lagerplads"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kort"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD-kort fra <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-drev"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 9a73e2a2d8bd..a1183e9cfcc5 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Mit %1$s bearbeiten"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Freigeben über"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Für %1$s freigeben"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Senden via"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Senden via %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Start-App auswählen"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"%1$s als Start-App verwenden"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Immer für diese Aktion verwenden"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"TEILEN"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ABLEHNEN"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatur ändern"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Weitere Tastaturen"</string>
<string name="show_ime" msgid="2506087537466597099">"Auf dem Display einblenden, wenn die physische Tastatur aktiv ist"</string>
<string name="hardware" msgid="194658061510127999">"Virtuelle Tastatur einblenden"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Tastaturlayout auswählen"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Weitere Optionen"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s. %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s. %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interner Speicher"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-Karte"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD-Karte von <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-Speichergerät"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index e3f8d3384efd..4e5f8fb4a80d 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Επεξεργασία με %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Κοινή χρήση με"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Κοινή χρήση με %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Αποστολή μέσω"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Αποστολή μέσω %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Επιλέξτε μια εφαρμογή Αρχικής σελίδας"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Χρήση %1$s ως Αρχικής σελίδας"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Χρήση από προεπιλογή για αυτήν την ενέργεια."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ΚΟΙΝΟΠΟΙΗΣΗ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ΑΠΟΡΡΙΨΗ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Αλλαγή πληκτρολογίου"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Άλλα πληκτρολόγια"</string>
<string name="show_ime" msgid="2506087537466597099">"Να παραμένει στην οθόνη όταν είναι ενεργό το φυσικό πληκτρολόγιο"</string>
<string name="hardware" msgid="194658061510127999">"Εμφάνιση εικονικού πληκτρολ."</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Επιλογή διάταξης πληκτρολογίου"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Περισσότερες επιλογές"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Εσωτερικός αποθηκευτικός χώρος"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Κάρτα SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Κάρτα SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Μονάδα USB"</string>
diff --git a/core/res/res/values-en-rAU/strings.xml b/core/res/res/values-en-rAU/strings.xml
index 1ae8d457584e..335f1f0c8d34 100644
--- a/core/res/res/values-en-rAU/strings.xml
+++ b/core/res/res/values-en-rAU/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"More options"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Internal storage"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Internal shared storage"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD card"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD card"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB drive"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 1ae8d457584e..335f1f0c8d34 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"More options"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Internal storage"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Internal shared storage"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD card"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD card"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB drive"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 1ae8d457584e..335f1f0c8d34 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"More options"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Internal storage"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Internal shared storage"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD card"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD card"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB drive"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index e818930182a3..2484fe538740 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar con %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Compartir con"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Compartir con %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Enviar con"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Enviar con %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Seleccionar una aplicación de la pantalla principal"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utilizar %1$s como aplicación de la pantalla principal"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utilizar de manera predeterminada en esta acción."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECHAZAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar el teclado"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Otros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Mantener en la pantalla cuando el teclado físico está activo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona un diseño de teclado"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Más opciones"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Almacenamiento interno"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Tarjeta SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Tarjeta SD de <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unidad USB"</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index dfc6a5005753..6521ccada950 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar con %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Compartir con"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Compartir con %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Enviar con"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Enviar con %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Selecciona una aplicación de inicio"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Usar %1$s como aplicación de inicio"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Usar siempre para esta acción"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECHAZAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Otros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Debe seguir en pantalla mientras el teclado físico esté activo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecciona un diseño de teclado"</string>
@@ -1227,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Más opciones"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Almacenamiento interno"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Almacenamiento interno compartido"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"Tarjeta SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Tarjeta SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unidad USB"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 2b15fbe9d887..3905a558238a 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Rohkem valikuid"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Sisemine salvestusruum"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Sisemine jagatud mäluruum"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kaart"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Tootja <xliff:g id="MANUFACTURER">%s</xliff:g> SD-kaart"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-ketas"</string>
diff --git a/core/res/res/values-eu-rES/strings.xml b/core/res/res/values-eu-rES/strings.xml
index 4c61bb26058a..ed5db6c36a79 100644
--- a/core/res/res/values-eu-rES/strings.xml
+++ b/core/res/res/values-eu-rES/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Aukera gehiago"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Barneko memoria"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD txartela"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD txartela"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB unitatea"</string>
@@ -1564,6 +1565,6 @@
<string name="unpin_target" msgid="3556545602439143442">"Kendu aingura"</string>
<string name="app_info" msgid="6856026610594615344">"Aplikazioari buruzko informazioa"</string>
<string name="negative_duration" msgid="5688706061127375131">"−<xliff:g id="TIME">%1$s</xliff:g>"</string>
- <string name="audit_safemode_notification" msgid="6416076898350685856">"Berrezarri jatorrizko egoerara gailua murriztapenik gabe erabili ahal izateko"</string>
+ <string name="audit_safemode_notification" msgid="6416076898350685856">"Berrezarri jatorrizko ezarpenak gailua murriztapenik gabe erabili ahal izateko"</string>
<string name="audit_safemode_notification_details" msgid="1860601176690176413">"Sakatu informazio gehiago lortzeko."</string>
</resources>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index dafe904c4c72..b1430389f97b 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"‏ویرایش با %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"اشتراک‌گذاری با"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"‏اشتراک‌گذاری با %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"ارسال با استفاده از"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"‏ارسال با استفاده از %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"انتخاب یک برنامه صفحه اصلی"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"‏استفاده از %1$s به عنوان برنامه صفحه اصلی"</string>
<string name="alwaysUse" msgid="4583018368000610438">"استفاده به صورت پیش‌فرض برای این عملکرد."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"اشتراک‌گذاری"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"نپذیرفتن"</string>
<string name="select_input_method" msgid="8547250819326693584">"تغییر صفحه‌کلید"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"صفحه‌کلیدهای دیگر"</string>
<string name="show_ime" msgid="2506087537466597099">"وقتی صفحه‌کلید فیزیکی فعال است این ویرایشگر را روی صفحه نگه‌می‌دارد"</string>
<string name="hardware" msgid="194658061510127999">"نمایش صفحه‌کلید مجازی"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"انتخاب طرح‌بندی صفحه‌کلید"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"سایر گزینه‌ها"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"‎%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"‎%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"حافظهٔ داخلی"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"‏کارت SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"‏کارت SD ‏<xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"‏درایو USB"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index e373dde6d2bd..8bb613e2170b 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Muokkaa sovelluksessa %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Jaa sovelluksessa"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Jaa sovelluksessa %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Lähetä sovelluksella"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Lähetä sovelluksella %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Valitse aloitusruutusovellus"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Käytä aloitusruutuna: %1$s"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Käytä oletuksena tälle toiminnolle."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"JAA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"HYLKÄÄ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Vaihda näppäimistö"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Muut näppäimistöt"</string>
<string name="show_ime" msgid="2506087537466597099">"Pidä näytöllä, kun fyysinen näppäimistö on aktiivinen."</string>
<string name="hardware" msgid="194658061510127999">"Näytä virtuaalinen näppäimistö"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Valitse näppäimistöasettelu"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Lisää asetuksia"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Sisäinen tallennustila"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kortti"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD-kortti: <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-asema"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 028a9fda9038..3375e1854e9a 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Modifier avec %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Partager"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Partager avec %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Envoyer avec"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Envoyer avec %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Sélectionner une application pour l\'écran d\'accueil"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utiliser %1$s comme écran d\'accueil"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utiliser cette application par défaut pour cette action"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTAGER"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUSER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Autres claviers"</string>
<string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
<string name="hardware" msgid="194658061510127999">"Afficher le clavier virtuel"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Sélectionnez la disposition du clavier"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Plus d\'options"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Mémoire de stockage interne"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Carte SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Carte mémoire SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Clé USB"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 0053d384f5e3..741d0e1bea33 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Modifier avec %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Partager avec"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Partager avec %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Envoyer avec"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Envoyer avec %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Sélectionner une application de l\'écran d\'accueil"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utiliser %1$s comme écran d\'accueil"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utiliser cette application par défaut pour cette action"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTAGER"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUSER"</string>
<string name="select_input_method" msgid="8547250819326693584">"Changer de clavier"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Autres claviers"</string>
<string name="show_ime" msgid="2506087537466597099">"Afficher lorsque le clavier physique est activé"</string>
<string name="hardware" msgid="194658061510127999">"Afficher le clavier virtuel"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Sélectionnez la disposition du clavier"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Plus d\'options"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Mémoire de stockage interne"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Carte SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Carte SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Clé USB"</string>
diff --git a/core/res/res/values-gl-rES/strings.xml b/core/res/res/values-gl-rES/strings.xml
index 3f4150c5f7ba..be83dabcf7b0 100644
--- a/core/res/res/values-gl-rES/strings.xml
+++ b/core/res/res/values-gl-rES/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar con %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Compartir con"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Compartir con %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Enviar a través de"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Enviar a través de %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Selecciona unha aplicación de Inicio"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utiliza %1$s como aplicación de Inicio"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Usar de forma predeterminada para esta acción."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTIR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ANULAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Cambiar teclado"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manteno na pantalla mentres o teclado físico estea activo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Seleccionar deseño de teclado"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Máis opcións"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Almacenamento interno"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Tarxeta SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Tarxeta SD de <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unidade USB"</string>
diff --git a/core/res/res/values-gu-rIN/strings.xml b/core/res/res/values-gu-rIN/strings.xml
index a0fd8f0f1e4a..4389cffa9141 100644
--- a/core/res/res/values-gu-rIN/strings.xml
+++ b/core/res/res/values-gu-rIN/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s સાથે સંપાદિત કરો"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"આની સાથે શેર કરો"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s સાથે શેર કરો"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"આનો ઉપયોગ કરીને મોકલો"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s નો ઉપયોગ કરીને મોકલો"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"હોમ એપ્લિકેશન પસંદ કરો"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"હોમ તરીકે %1$s નો ઉપયોગ કરો"</string>
<string name="alwaysUse" msgid="4583018368000610438">"આ ક્રિયા માટે ડિફોલ્ટ તરીકે ઉપયોગમાં લો."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"શેર કરો"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"નકારો"</string>
<string name="select_input_method" msgid="8547250819326693584">"કીબોર્ડ બદલો"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"અન્ય કીબોર્ડ્સ"</string>
<string name="show_ime" msgid="2506087537466597099">"જ્યારે ભૌતિક કીબોર્ડ સક્રિય હોય ત્યારે તેને સ્ક્રીન પર રાખો"</string>
<string name="hardware" msgid="194658061510127999">"વર્ચ્યુઅલ કીબોર્ડ બતાવો"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"કીબોર્ડ લેઆઉટ પસંદ કરો."</string>
@@ -1227,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"વધુ વિકલ્પો"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"આંતરિક સંગ્રહ"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"આંતરિક શેર કરેલો સ્ટોરેજ"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD કાર્ડ"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD કાર્ડ"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ડ્રાઇવ"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 5de2ec2aee0a..18c40073f167 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"अधिक विकल्प"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"मोबाइल मेमोरी"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"आंतरिक साझा मेमोरी"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD कार्ड"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD कार्ड"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB डिस्‍क"</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index 2bb6f4c80f03..2ce73f433d1d 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -1233,7 +1233,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Više opcija"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interna pohrana"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD kartica"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD kartica"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB pogon"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 46fbe89200c6..bf23b71b1c17 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"További lehetőségek"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Belső tárhely"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Belső közös tárhely"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kártya"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD-kártya"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-meghajtó"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index eb289422f4d7..8921e88dba10 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Խմբագրել հետևյալով՝ %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Տարածել"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Տարածել ըստ %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Ուղարկել այս հավելվածով"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Ուղարկել %1$s հավելվածով"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Ընտրեք Հիմնական հավելվածը"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Օգտագործել %1$s-ը՝ որպես Հիմնական"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Օգտագործել լռելյայն այս գործողության համար:"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ՏՐԱՄԱԴՐԵԼ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ՄԵՐԺԵԼ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Փոխել ստեղնաշարը"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Այլ ստեղնաշարեր"</string>
<string name="show_ime" msgid="2506087537466597099">"Պահել էկրանին մինչդեռ ֆիզիկական ստեղնաշարն ակտիվ է"</string>
<string name="hardware" msgid="194658061510127999">"Ցույց տալ վիրտուալ ստեղնաշարը"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Ընտրեք ստեղնաշարի դիրքը"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Ավելի շատ ընտրանքներ"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Ներքին պահոց"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD քարտ"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD քարտ <xliff:g id="MANUFACTURER">%s</xliff:g>-ից"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB սարքավար"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 9e0c091c3cbf..e7c706dc792f 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Opsi lainnya"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Penyimpanan internal"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Kartu SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Kartu SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Drive USB"</string>
diff --git a/core/res/res/values-is-rIS/strings.xml b/core/res/res/values-is-rIS/strings.xml
index a1b921a57b76..5edb125c49b6 100644
--- a/core/res/res/values-is-rIS/strings.xml
+++ b/core/res/res/values-is-rIS/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Breyta með %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Deila með"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Deila með %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Senda með því að nota"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Senda með því að nota %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Veldu heimaforrit"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Nota %1$s sem heimaforrit"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Nota sjálfgefið fyrir þessa aðgerð."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEILA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"HAFNA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Skipta um lyklaborð"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Önnur lyklaborð"</string>
<string name="show_ime" msgid="2506087537466597099">"Haltu því á skjánum meðan vélbúnaðarlyklaborðið er virkt"</string>
<string name="hardware" msgid="194658061510127999">"Sýna sýndarlyklaborð"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Veldu lyklaskipan"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Fleiri valkostir"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Innbyggð geymsla"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kort"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD-kort frá <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-drif"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index a282adec04f5..73775a0e35c5 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Altre opzioni"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Memoria interna"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Scheda SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Scheda SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unità USB"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index cba89f1c3f5b..b06434ec1070 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -911,10 +911,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"‏ערוך באמצעות %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"שתף באמצעות"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"‏שתף באמצעות %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"שליחה באמצעות"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"‏שליחה באמצעות %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"בחר אפליקציה שתשמש כדף הבית"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"‏השתמש ב-%1$s כדף הבית"</string>
<string name="alwaysUse" msgid="4583018368000610438">"השתמש כברירת מחדל עבור פעולה זו."</string>
@@ -1078,8 +1076,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"שתף"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"דחה"</string>
<string name="select_input_method" msgid="8547250819326693584">"שינוי מקלדת"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"מקלדות אחרות"</string>
<string name="show_ime" msgid="2506087537466597099">"השאר אותו במסך בזמן שהמקלדת הפיזית פעילה"</string>
<string name="hardware" msgid="194658061510127999">"הצג מקלדת וירטואלית"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"בחירת פריסת מקלדת"</string>
@@ -1245,7 +1242,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"אפשרויות נוספות"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"‏%1$s‏, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"‏%1$s‏, %2$s‏, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"אחסון פנימי"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"‏כרטיס SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"‏כרטיס SD של <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"‏כונן USB"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index b3e15df44231..14d64b01c61d 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"その他のオプション"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s、%2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s、%2$s、%3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"内部ストレージ"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SDカード"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g>製SDカード"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USBドライブ"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 8d199d215e3c..92e57b7138a5 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"რედაქტირება %1$s-ით"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"გაზიარება:"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s-თან გაზიარება"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"გაგზავნა:"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"გაგზავნა %1$s-ის მეშვეობით"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"აირჩიეთ Home აპი"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"%1$s-ის გამოყენება ......Home-ად"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ამ ქმედებისთვის ნაგულისხმევად გამოყენება."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"გაზიარება"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"უარყოფა"</string>
<string name="select_input_method" msgid="8547250819326693584">"კლავიატურის შეცვლა"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"სხვა კლავიატურები"</string>
<string name="show_ime" msgid="2506087537466597099">"აქტიური ფიზიკური კლავიატურისას ეკრანზე შენარჩუნება"</string>
<string name="hardware" msgid="194658061510127999">"ვირტუალური კლავიატურის ჩვენება"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"შეარჩიეთ კლავიატურის განლაგება."</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"მეტი ვარიანტები"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"შიდა მეხსიერება"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD ბარათი"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD ბარათი"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB დისკი"</string>
diff --git a/core/res/res/values-kk-rKZ/strings.xml b/core/res/res/values-kk-rKZ/strings.xml
index 1af7bc385a52..85621ede4460 100644
--- a/core/res/res/values-kk-rKZ/strings.xml
+++ b/core/res/res/values-kk-rKZ/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Басқа опциялар"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Ішкі жад"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD картасы"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD картасы"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB дискі"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index a13541cc8eab..e9be6b6b8ee4 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -1226,7 +1226,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ជម្រើស​ច្រើន​ទៀត"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"ឧបករណ៍​ផ្ទុក​ខាង​ក្នុង"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"កាត​អេសឌី"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"កាត SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"ឧបករណ៍ផ្ទុក USB"</string>
diff --git a/core/res/res/values-kn-rIN/strings.xml b/core/res/res/values-kn-rIN/strings.xml
index 4915b9fbcaca..2e04419b963d 100644
--- a/core/res/res/values-kn-rIN/strings.xml
+++ b/core/res/res/values-kn-rIN/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ಇನ್ನಷ್ಟು ಆಯ್ಕೆಗಳು"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"ಆಂತರಿಕ ಸಂಗ್ರಹಣೆ"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD ಕಾರ್ಡ್"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD ಕಾರ್ಡ್"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ಡ್ರೈವ್"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index e9eee8ab67d0..b61df80a53b8 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s(으)로 수정"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"공유 대상"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s와(과) 공유"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"전송 시 사용할 앱"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"전송 시 사용할 앱: %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"홈 앱 선택"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"%1$s을(를) 홈 앱으로 사용"</string>
<string name="alwaysUse" msgid="4583018368000610438">"이 작업에 대해 기본값으로 사용"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"공유"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"거부"</string>
<string name="select_input_method" msgid="8547250819326693584">"키보드 변경"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"기타 키보드"</string>
<string name="show_ime" msgid="2506087537466597099">"물리적 키보드가 활성 상태인 경우 화면에 켜 둠"</string>
<string name="hardware" msgid="194658061510127999">"가상 키보드 표시"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"키보드 레이아웃 선택"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"옵션 더보기"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"내부 저장소"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD 카드"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 카드"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB 드라이브"</string>
diff --git a/core/res/res/values-ky-rKG/strings.xml b/core/res/res/values-ky-rKG/strings.xml
index e02a5ce2cc6e..55b2b7c2babe 100644
--- a/core/res/res/values-ky-rKG/strings.xml
+++ b/core/res/res/values-ky-rKG/strings.xml
@@ -900,10 +900,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s менен түзөтүү"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Төмөнкү менен бөлүшүү"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s менен бөлүшүү"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Колдонуп жөнөтүү"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s колдонуп жөнөтүү"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Башкы бет колдонмосун тандаңыз"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Башкы бет колдонмосу катары %1$s пайдалануу"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Бул аракет үчүн демейки боюнча колдонулсун."</string>
@@ -1063,8 +1061,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"БӨЛҮШҮҮ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ЧЕТКЕ КАГУУ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Баскычтопту өзгөртүү"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Башка баскычтоптор"</string>
<string name="show_ime" msgid="2506087537466597099">"Баскычтоп иштетилгенде экранда көрүнүп турсун"</string>
<string name="hardware" msgid="194658061510127999">"Виртуалдык баскычтоп"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Тергичтин жайгашуусун тандоо"</string>
@@ -1228,7 +1225,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Дагы параметрлер"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Ички сактагыч"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-карта"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD карта"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB түзмөк"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index cafb430748c5..5d1c37eabea1 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ໂຕເລືອກອື່ນ"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"ບ່ອນຈັດເກັບຂໍ້ມູນພາຍໃນ"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD card"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> ແຜ່ນ SD"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ດ​ຣ້າຍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 7715e4f15ab4..1460b9b0707e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -1242,7 +1242,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Daugiau parinkčių"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Vidinė atmintis"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD kortelė"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"„<xliff:g id="MANUFACTURER">%s</xliff:g>“ SD kortelė"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Atmintukas"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 87b2be73f383..566180f70af8 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -905,10 +905,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Rediģēt, izmantojot %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Kopīgot, izmantojot"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Kopīgot, izmantojot %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Sūtīšana, izmantojot..."</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Sūtīšana, izmantojot: %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Sākuma lietotnes atlase"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"“%1$s” kā sākuma lietotnes izmantošana"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Pēc noklusējuma izmantot šai darbībai."</string>
@@ -1070,8 +1068,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"KOPĪGOT"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"NORAIDĪT"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tastatūras maiņa"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Citas tastatūras"</string>
<string name="show_ime" msgid="2506087537466597099">"Paturēt ekrānā, kamēr ir aktīva fiziskā tastatūra"</string>
<string name="hardware" msgid="194658061510127999">"Virtuālās tastatūras rādīšana"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Atlasiet tastatūras izkārtojumu"</string>
@@ -1236,7 +1233,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Vairāk opciju"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s: %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s: %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Iekšējā atmiņa"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Iekšējā kopīgotā krātuve"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD karte"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD karte"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB disks"</string>
diff --git a/core/res/res/values-mk-rMK/strings.xml b/core/res/res/values-mk-rMK/strings.xml
index 75d28f5f2951..c4ef82cb434b 100644
--- a/core/res/res/values-mk-rMK/strings.xml
+++ b/core/res/res/values-mk-rMK/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Уреди со %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Сподели со"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Сподели со %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Испрати преку"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Испрати преку %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Изберете ја апликацијата Почетен"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Користете ја %1$s како Почетен"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Користи ја стандардно за ова дејство."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"СПОДЕЛИ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОДБИЈ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Измени тастатура"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Други тастатури"</string>
<string name="show_ime" msgid="2506087537466597099">"Прикажувај го на екранот додека е активна физичката тастатура"</string>
<string name="hardware" msgid="194658061510127999">"Прикажи виртуелна тастатура"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избери изглед на тастатура"</string>
@@ -1229,7 +1226,8 @@
<!-- no translation found for action_bar_home_description_format (7965984360903693903) -->
<skip />
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Внатрешна меморија"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"СД картичка"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> СД-картичка"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"УСБ-меморија"</string>
diff --git a/core/res/res/values-ml-rIN/strings.xml b/core/res/res/values-ml-rIN/strings.xml
index d67f8136d5f9..9b9650115040 100644
--- a/core/res/res/values-ml-rIN/strings.xml
+++ b/core/res/res/values-ml-rIN/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ഉപയോഗിച്ച് എഡിറ്റുചെയ്യുക"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"ഇതുമായി പങ്കിടുക"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s എന്നതുമായി പങ്കിടുക"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"ഇനിപ്പറയുന്നത് ഉപയോഗിച്ച് അയയ്ക്കുക"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s ഉപയോഗിച്ച് അയയ്ക്കുക"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"ഒരു ഹോം അപ്ലിക്കേഷൻ തിരഞ്ഞെടുക്കുക"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"ഹോമായി %1$s എന്നത് ഉപയോഗിക്കുക"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ഈ പ്രവർത്തനത്തിന് സ്ഥിരമായി ഉപയോഗിക്കുക."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"പങ്കിടുക"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"നിരസിക്കുക"</string>
<string name="select_input_method" msgid="8547250819326693584">"കീബോഡ് മാറ്റുക"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"മറ്റ് കീബോർഡുകൾ"</string>
<string name="show_ime" msgid="2506087537466597099">"ഫിസിക്കൽ കീബോർഡ് സജീവമായിരിക്കുമ്പോൾ സ്ക്രീനിൽ നിലനിർത്തുക"</string>
<string name="hardware" msgid="194658061510127999">"വെർച്വൽ കീബോർഡ് കാണിക്കുക"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"കീബോർഡ് ലേഔട്ട് തിരഞ്ഞെടുക്കുക"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"കൂടുതൽ‍ ഓപ്‌ഷനുകള്‍"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"ആന്തരിക സ്റ്റോറേജ്"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD കാർഡ്"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD കാർഡ്"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ഡ്രൈവ്"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index fc776636d426..ef34b466fab5 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Нэмэлт сонголтууд"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Дотоод сан"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD карт"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD карт"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB диск"</string>
diff --git a/core/res/res/values-mr-rIN/strings.xml b/core/res/res/values-mr-rIN/strings.xml
index b7010d0ca74e..7baa543491e6 100644
--- a/core/res/res/values-mr-rIN/strings.xml
+++ b/core/res/res/values-mr-rIN/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"अधिक पर्याय"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"अंतर्गत संचयन"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD कार्ड"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD कार्ड"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ड्राइव्‍ह"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index d51355a8fe9c..c2e3bfe4c243 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edit dengan %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Kongsi dengan"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Kongsi dengan %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Hantar menggunakan"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Hantar menggunakan %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Pilih apl Laman Utama"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Gunakan %1$s sebagai Laman Utama"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Gunakannya secara lalai untuk tindakan ini."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"KONGSI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"TOLAK"</string>
<string name="select_input_method" msgid="8547250819326693584">"Tukar papan kekunci"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Papan kekunci lain"</string>
<string name="show_ime" msgid="2506087537466597099">"Pastikannya pada skrin, semasa papan kekunci fizikal aktif"</string>
<string name="hardware" msgid="194658061510127999">"Tunjukkan papan kekunci maya"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Pilih susun atur papan kekunci"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Lagi pilihan"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Storan dalaman"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Kad SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Kad SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Pemacu USB"</string>
diff --git a/core/res/res/values-my-rMM/strings.xml b/core/res/res/values-my-rMM/strings.xml
index 2ad411f77085..0c55986e5c0e 100644
--- a/core/res/res/values-my-rMM/strings.xml
+++ b/core/res/res/values-my-rMM/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ပိုမိုရွေးချယ်စရာများ"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s ၊ %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s ၊ %2$s ၊ %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"စက်တွင်း သိုလှောင်ထားမှု"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"စက်တွင်းမျှဝေထားသည့် သိုလှောင်ခန်း"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD ကဒ်"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD ကဒ်"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ဒရိုက်ဗ်"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 3384e77f0b07..78173216c2a4 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Rediger med %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Del med"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Del med %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Send via"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Send via %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Velg en startsideapp"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Bruk %1$s som startside"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Bruk som standardvalg."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DEL"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AVSLÅ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Endre tastatur"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Andre tastaturoppsett"</string>
<string name="show_ime" msgid="2506087537466597099">"Ha den på skjermen mens det fysiske tastaturet er aktivt"</string>
<string name="hardware" msgid="194658061510127999">"Vis det virtuelle tastaturet"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Velg tastaturoppsett"</string>
@@ -1227,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Flere alternativer"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s – %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s – %2$s – %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Intern lagring"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Delt internlagring"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kort"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD-kort"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-stasjon"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index d63db60ddef8..459eccdc9dcf 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -1230,7 +1230,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"थप विकल्पहरू"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"आन्तरिक भण्डारण"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD कार्ड"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD कार्ड"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ड्राइभ"</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 4cfe8c78bc1b..e8279af74d31 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Meer opties"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interne opslag"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Interne gedeelde opslag"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kaart"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD-kaart"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-drive"</string>
diff --git a/core/res/res/values-pa-rIN/strings.xml b/core/res/res/values-pa-rIN/strings.xml
index d28e9120ecee..f74b93cf6d77 100644
--- a/core/res/res/values-pa-rIN/strings.xml
+++ b/core/res/res/values-pa-rIN/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ਹੋਰ ਚੋਣਾਂ"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"ਅੰਦਰੂਨੀ ਸਟੋਰੇਜ"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD ਕਾਰਡ"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD ਕਾਰਡ"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ਡ੍ਰਾਇਵ"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index f7ba6debeb38..6e4091a09e34 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -911,10 +911,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Edytuj w aplikacji %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Udostępnij przez:"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Udostępnij przez %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Wyślij za pomocą"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Wyślij za pomocą %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Wybierz aplikację ekranu głównego"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Użyj %1$s jako ekranu głównego"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Domyślne dla tej czynności"</string>
@@ -1078,8 +1076,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"UDOSTĘPNIJ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODRZUĆ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmień klawiaturę"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Inne klawiatury"</string>
<string name="show_ime" msgid="2506087537466597099">"Pozostaw na ekranie, gdy aktywna jest klawiatura fizyczna"</string>
<string name="hardware" msgid="194658061510127999">"Pokaż klawiaturę wirtualną"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Wybierz układ klawiatury"</string>
@@ -1245,7 +1242,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Więcej opcji"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Pamięć wewnętrzna"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Karta SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Karta SD (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Dysk USB"</string>
diff --git a/core/res/res/values-pt-rBR/strings.xml b/core/res/res/values-pt-rBR/strings.xml
index 66bc338ee964..62ee01c89760 100644
--- a/core/res/res/values-pt-rBR/strings.xml
+++ b/core/res/res/values-pt-rBR/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar com %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Compartilhar com"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Compartilhar com %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Enviar usando"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Enviar usando %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Selecione um app de Página inicial"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Usar %1$s como Página inicial"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Usar como padrão para esta ação."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecione o layout de teclado"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Armazenamento interno"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Drive USB"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index aaa575fb9c42..331cd9dda2ab 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar com %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Partilhar com"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Partilhar com %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Enviar com"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Enviar com %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Selecione uma aplicação Página inicial"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utilizar %1$s como Página inicial"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Utilizar por predefinição para esta acção."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PARTILHAR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manter no ecrã enquanto o teclado físico estiver ativo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar o teclado virtual"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecionar esquema de teclado"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"memória de armazenamento interno"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unidade USB"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 66bc338ee964..62ee01c89760 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editar com %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Compartilhar com"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Compartilhar com %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Enviar usando"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Enviar usando %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Selecione um app de Página inicial"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Usar %1$s como Página inicial"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Usar como padrão para esta ação."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"COMPARTILHAR"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RECUSAR"</string>
<string name="select_input_method" msgid="8547250819326693584">"Alterar teclado"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Outros teclados"</string>
<string name="show_ime" msgid="2506087537466597099">"Manter na tela enquanto o teclado físico estiver ativo"</string>
<string name="hardware" msgid="194658061510127999">"Mostrar teclado virtual"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selecione o layout de teclado"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Mais opções"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Armazenamento interno"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Cartão SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Cartão SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Drive USB"</string>
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 72ec2f6acc63..dd4faad18f61 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -905,10 +905,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Editați cu %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Trimiteți prin"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Distribuiți cu %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Trimiteți folosind"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Trimiteți folosind %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Selectați o aplicație de pe ecranul de pornire"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Utilizați %1$s ca ecran de pornire"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Se utilizează în mod prestabilit pentru această acțiune."</string>
@@ -1070,8 +1068,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"TRIMITEȚI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUZAȚI"</string>
<string name="select_input_method" msgid="8547250819326693584">"Schimbați tastatura"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Alte tastaturi"</string>
<string name="show_ime" msgid="2506087537466597099">"Se păstrează pe ecran cât timp este activată tastatura fizică"</string>
<string name="hardware" msgid="194658061510127999">"Afișați tastatura virtuală"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Selectați aspectul tastaturii"</string>
@@ -1236,7 +1233,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Mai multe opțiuni"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Stocare internă"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Card SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Card SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Unitate USB"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index a5ac24d3b3cb..4d618acb4069 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -1242,7 +1242,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Ещё"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Внутр. накопитель"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-карта"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD-карта <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-накопитель"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 838d4e62bb54..5dbb9223134f 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -1226,7 +1226,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"තවත් විකල්ප"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"අභ්‍යන්තර ආචයනය"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD පත"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD කාඩ්පත"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB ධාවකය"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index d0ee456e5a17..75a2129d934f 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -911,10 +911,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Upraviť v aplikácii %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Zdieľať"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Zdieľať v aplikácii %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Odoslať pomocou aplikácie"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Odoslať pomocou aplikácie %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Výber aplikácie na plochu"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Ako plochu používať aplikáciu %1$s"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Použiť ako predvolené nastavenie pre túto akciu."</string>
@@ -1078,8 +1076,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ZDIEĽAŤ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ODMIETNUŤ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Zmeniť klávesnicu"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Ďalšie klávesnice"</string>
<string name="show_ime" msgid="2506087537466597099">"Ponechať na obrazovke, keď je aktívna fyzická klávesnica"</string>
<string name="hardware" msgid="194658061510127999">"Zobraziť virtuálnu klávesnicu"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Zvoľte rozloženie klávesnice"</string>
@@ -1245,7 +1242,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Viac možností"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Interné úložisko"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD karta"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD karta <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Disk USB"</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index d73c1a8e1ee9..579880a4a42e 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -911,10 +911,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Urejanje z aplikacijo %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Skupna raba z aplikacijo"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Skupna raba z aplikacijo %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Pošiljanje z aplikacijo"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Pošiljanje z aplikacijo %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Izbira aplikacije na začetnem zaslonu"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Uporaba aplikacije %1$s na začetnem zaslonu"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Privzeta uporaba za to dejanje."</string>
@@ -1078,8 +1076,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SKUPNA RABA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"NE SPREJMEM"</string>
<string name="select_input_method" msgid="8547250819326693584">"Sprememba tipkovnice"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Druge tipkovnice"</string>
<string name="show_ime" msgid="2506087537466597099">"Ohrani na zaslonu, dokler je aktivna fizična tipkovnica"</string>
<string name="hardware" msgid="194658061510127999">"Pokaži navidezno tipkovnico"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Izberite razporeditev tipkovnice"</string>
@@ -1245,7 +1242,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Več možnosti"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Notranja shramba"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Kartica SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Kartica SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Pogon USB"</string>
diff --git a/core/res/res/values-sq-rAL/strings.xml b/core/res/res/values-sq-rAL/strings.xml
index be63565c9406..b39f297beda7 100644
--- a/core/res/res/values-sq-rAL/strings.xml
+++ b/core/res/res/values-sq-rAL/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Redakto me %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Shpërnda publikisht me"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Shpërnda publikisht me %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Dërgo me"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Dërgo me %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Përzgjidh një aplikacion nga ekrani bazë"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Përdore %1$s si faqe bazë"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Përdore si parametër të paracaktuar për këtë veprim."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHPËRNDA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REFUZO"</string>
<string name="select_input_method" msgid="8547250819326693584">"Ndërro tastierë"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Tastierat e tjera"</string>
<string name="show_ime" msgid="2506087537466597099">"Mbaje në ekran ndërsa tastiera fizike është aktive"</string>
<string name="hardware" msgid="194658061510127999">"Shfaq tastierën virtuale"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Përzgjidh planin e tastierës"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Opsione të tjera"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Hapësira e brendshme ruajtëse"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Karta SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Karta SD nga <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-ja"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index df54c09fc74d..74fc273acbd1 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -905,10 +905,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Измените помоћу апликације %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Делите помоћу"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Делите помоћу апликације %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Пошаљите помоћу:"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Пошаљите помоћу: %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Изаберите апликацију за почетну страницу"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Користите %1$s за почетну"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Подразумевано користи за ову радњу."</string>
@@ -1070,8 +1068,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ДЕЛИ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"ОДБИЈ"</string>
<string name="select_input_method" msgid="8547250819326693584">"Промените тастатуру"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Друге тастатуре"</string>
<string name="show_ime" msgid="2506087537466597099">"Задржи га на екрану док је физичка тастатура активна"</string>
<string name="hardware" msgid="194658061510127999">"Прикажи виртуелну тастатуру"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Избор распореда тастатуре"</string>
@@ -1236,7 +1233,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Још опција"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Интерна меморија"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD картица"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD картица"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB диск"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index dc20d4764f9b..610fa072e137 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Redigera med %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Dela med"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Dela med %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Skicka med"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Skicka med %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Välj en startsidesapp"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Använd %1$s som startsida"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Använd som standard för denna åtgärd."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"DELA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"AVVISA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Byt tangentbord"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Andra tangentbord"</string>
<string name="show_ime" msgid="2506087537466597099">"Ha kvar den på skärmen när det fysiska tangentbordet används"</string>
<string name="hardware" msgid="194658061510127999">"Visa virtuellt tangentbord"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Välj en tangentbordslayout"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Fler alternativ"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"lagring"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD-kort"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"SD-kort (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB-enhet"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index b1dec3d82a57..3d4bc60d66ad 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -901,10 +901,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Badilisha kwa %1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Shiriki na"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Shiriki na %1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Tuma kwa kutumia"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Tuma kwa kutumia %1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Chagua programu ya Mwanzo"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Tumia %1$s kama programu ya Mwanzo"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Tumia kama chaguo-msingi la kitendo hiki."</string>
@@ -1064,8 +1062,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"SHIRIKI"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"KATAA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Badilisha kibodi"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Kibodi zingine"</string>
<string name="show_ime" msgid="2506087537466597099">"Iweke kwenye skrini wakati kibodi inapotumika"</string>
<string name="hardware" msgid="194658061510127999">"Onyesha kibodi pepe"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Teua mpangilio wa kibodi"</string>
@@ -1229,7 +1226,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Chaguo zaidi"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Hifadhi ya mfumo"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Kadi ya SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Kadi ya SD iliyotengenezwa na <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Hifadhi ya USB"</string>
diff --git a/core/res/res/values-ta-rIN/strings.xml b/core/res/res/values-ta-rIN/strings.xml
index 9361300396cf..9411f5b7ba54 100644
--- a/core/res/res/values-ta-rIN/strings.xml
+++ b/core/res/res/values-ta-rIN/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"மேலும் விருப்பங்கள்"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"அகச் சேமிப்பிடம்"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD கார்டு"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD கார்டு"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB டிரைவ்"</string>
diff --git a/core/res/res/values-te-rIN/strings.xml b/core/res/res/values-te-rIN/strings.xml
index a5cb4334633a..9beb1e10ea5b 100644
--- a/core/res/res/values-te-rIN/strings.xml
+++ b/core/res/res/values-te-rIN/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$sతో సవరించు"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"దీనితో భాగస్వామ్యం చేయి"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$sతో భాగస్వామ్యం చేయి"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"దీన్ని ఉపయోగించి పంపండి"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$sని ఉపయోగించి పంపండి"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"హోమ్ అనువర్తనాన్ని ఎంచుకోండి"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"%1$sని హోమ్‌గా ఉపయోగించండి"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ఈ చర్యకు డిఫాల్ట్‌గా ఉపయోగించండి."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"భాగస్వామ్యం చేయి"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"తిరస్కరిస్తున్నాను"</string>
<string name="select_input_method" msgid="8547250819326693584">"కీబోర్డ్‌ను మార్చు"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"ఇతర కీబోర్డ్‌లు"</string>
<string name="show_ime" msgid="2506087537466597099">"దీన్ని భౌతిక కీబోర్డ్ సక్రియంగా ఉన్నప్పుడు స్క్రీన్‌పై ఉంచుతుంది"</string>
<string name="hardware" msgid="194658061510127999">"వర్చువల్ కీబోర్డ్‌ను చూపు"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"కీబోర్డ్ లేఅవుట్‌ను ఎంచుకోండి"</string>
@@ -1227,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"మరిన్ని ఎంపికలు"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"అంతర్గత నిల్వ"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"అంతర్గత భాగస్వామ్య నిల్వ"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD కార్డు"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD కార్డ్"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB డ్రైవ్"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 8016663d5ebd..353da8a7a780 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"ตัวเลือกเพิ่มเติม"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"ที่จัดเก็บข้อมูลภายใน"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"การ์ด SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"การ์ด SD ของ <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"ไดรฟ์ USB"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index e49450e0ae18..41ada1cb7bdb 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Higit pang mga pagpipilian"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Panloob na storage"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD card"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD card"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB drive"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 51aa594472b2..3a044634d860 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"%1$s ile düzenle"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Şununla paylaş:"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"%1$s ile paylaş"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Göndermek için kullanılacak uygulama"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s uygulamasını kullanarak gönderin"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Ana Ekran uygulaması seçin"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Ana Ekran olarak %1$s uygulamasını kullanın"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Varsayılan olarak bu işlem için kullan."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"PAYLAŞ"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"REDDET"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klavyeyi değiştir"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Diğer klavyeler"</string>
<string name="show_ime" msgid="2506087537466597099">"Fiziksel klavye etkin durumdayken ekranda tut"</string>
<string name="hardware" msgid="194658061510127999">"Sanal klavyeyi göster"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Klavye düzeni seçin"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Diğer seçenekler"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Dahili depolama birimi"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD kart"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD kartı"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB sürücü"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index df1d9bacf773..8142aa03372d 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -1242,7 +1242,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Інші варіанти"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Внутрішня пам’ять"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"Внутрішнє спільне сховище"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"Карта SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Карта SD (<xliff:g id="MANUFACTURER">%s</xliff:g>)"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Носій USB"</string>
diff --git a/core/res/res/values-ur-rPK/strings.xml b/core/res/res/values-ur-rPK/strings.xml
index 6a09649a855e..565cdd962250 100644
--- a/core/res/res/values-ur-rPK/strings.xml
+++ b/core/res/res/values-ur-rPK/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"‏%1$s کے ساتھ ترمیم کریں"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"اس کے ساتھ اشتراک کریں"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"‏%1$s کے ساتھ اشتراک کریں"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"بھیجیں بذریعہ"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"‏بھیجیں بذریعہ ‎%1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"‏ایک Home ایپ منتخب کریں"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"‏%1$s کو Home کے بطور استعمال کریں"</string>
<string name="alwaysUse" msgid="4583018368000610438">"اس کارروائی کیلئے بطور ڈیفالٹ استعمال کریں۔"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"اشتراک کریں"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"مسترد کریں"</string>
<string name="select_input_method" msgid="8547250819326693584">"کی بورڈ تبدیل کریں"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"دیگر کی بورڈز"</string>
<string name="show_ime" msgid="2506087537466597099">"‏جب فزیکل کی بورڈ فعال ہو تو IME کو اسکرین پر رکھیں"</string>
<string name="hardware" msgid="194658061510127999">"ورچوئل کی بورڈ دکھائیں"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"کی بورڈ کا خاکہ منتخب کریں"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"مزید اختیارات"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"داخلی اسٹوریج"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"‏SD کارڈ"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"‏<xliff:g id="MANUFACTURER">%s</xliff:g> SD کارڈ"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"‏USB ڈرائیو"</string>
diff --git a/core/res/res/values-uz-rUZ/strings.xml b/core/res/res/values-uz-rUZ/strings.xml
index 228dd8aa9033..1a8124540710 100644
--- a/core/res/res/values-uz-rUZ/strings.xml
+++ b/core/res/res/values-uz-rUZ/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"“%1$s” yordamida tahrirlash"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Ulashish…"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"“%1$s” orqali ulashish"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Ilovani tanlang"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"%1$s yordamida yuborish"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Bosh ilovani tanlash"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"%1$s: Bosh ilova sifatida foydalanish"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Ushbu amaldan standart sifatida foydalanish"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"ULASHISH"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"RAD ETISH"</string>
<string name="select_input_method" msgid="8547250819326693584">"Klaviaturani o‘zgartirish"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Boshqa klaviaturalar"</string>
<string name="show_ime" msgid="2506087537466597099">"Tashqi klaviaturadan foydalanilayotganda buni ekranda saqlab turish"</string>
<string name="hardware" msgid="194658061510127999">"Virtual klaviatura ko‘rsatilsin"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Tugmalar tartibini tanlash"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Ko‘proq sozlamalar"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Ichki xotira"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD karta"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD kartasi"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB xotira"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 67c5f9aa904e..7302f7af23aa 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Tùy chọn khác"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Bộ nhớ trong"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Thẻ SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"Thẻ SD <xliff:g id="MANUFACTURER">%s</xliff:g>"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Ổ USB"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 4ab928558aec..4c90e1ce1597 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -1224,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"更多选项"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s:%2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s - %2$s:%3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"内部存储设备"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD卡"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 卡"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"U 盘"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index f002b4016822..e15aaf2bb877 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -1224,7 +1224,7 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"更多選項"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s:%2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s (%2$s):%3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"內部儲存空間"</string>
+ <string name="storage_internal" msgid="3570990907910199483">"內部共用儲存空間"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"SD 記憶卡"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 卡"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB 驅動器"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 99df97e6ace4..a782d40ce3f7 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"使用 %1$s 編輯"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"選擇分享工具"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"透過 %1$s 分享"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"透過以下應用程式傳送:"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"透過「%1$s」傳送"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"選取主螢幕應用程式"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"使用「%1$s」做為主螢幕"</string>
<string name="alwaysUse" msgid="4583018368000610438">"設為預設應用程式。"</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"分享"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"拒絕"</string>
<string name="select_input_method" msgid="8547250819326693584">"變更鍵盤"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"其他鍵盤"</string>
<string name="show_ime" msgid="2506087537466597099">"有連接的實體鍵盤時保持顯示"</string>
<string name="hardware" msgid="194658061510127999">"顯示虛擬鍵盤"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"選取鍵盤配置"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"更多選項"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s:%2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s - %2$s:%3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"內部儲存空間"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"SD 卡"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> SD 卡"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"USB 隨身碟"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index 7d7215f3ca18..23d72dc05127 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -899,10 +899,8 @@
<string name="whichEditApplicationNamed" msgid="1775815530156447790">"Hlela nge-%1$s"</string>
<string name="whichSendApplication" msgid="6902512414057341668">"Yabelana no-"</string>
<string name="whichSendApplicationNamed" msgid="2799370240005424391">"Yabelana no-%1$s"</string>
- <!-- no translation found for whichSendToApplication (8272422260066642057) -->
- <skip />
- <!-- no translation found for whichSendToApplicationNamed (7768387871529295325) -->
- <skip />
+ <string name="whichSendToApplication" msgid="8272422260066642057">"Thumela usebenzisa"</string>
+ <string name="whichSendToApplicationNamed" msgid="7768387871529295325">"Thumela usebenzisa i-%1$s"</string>
<string name="whichHomeApplication" msgid="4307587691506919691">"Khetha uhlelo lokusebenza lasekhaya"</string>
<string name="whichHomeApplicationNamed" msgid="4493438593214760979">"Sebenzisa i-%1$s njengekhaya"</string>
<string name="alwaysUse" msgid="4583018368000610438">"Sebenzisa ngokuzenzakalelayo kulesenzo."</string>
@@ -1062,8 +1060,7 @@
<string name="share_remote_bugreport_action" msgid="6249476773913384948">"YABELANA"</string>
<string name="decline_remote_bugreport_action" msgid="6230987241608770062">"YENQABA"</string>
<string name="select_input_method" msgid="8547250819326693584">"Shintsha ikhibhodi"</string>
- <!-- no translation found for configure_input_methods (5673193194563164021) -->
- <skip />
+ <string name="configure_input_methods" msgid="5673193194563164021">"Amanye amakhibhodi"</string>
<string name="show_ime" msgid="2506087537466597099">"Yigcine kusikrini ngenkathi kusebenza ikhibhodi ephathekayo"</string>
<string name="hardware" msgid="194658061510127999">"Bonisa ikhibhodi ebonakalayo"</string>
<string name="select_keyboard_layout_notification_title" msgid="1407367017263030773">"Khetha isendlalelo sekhibhodi"</string>
@@ -1227,7 +1224,8 @@
<string name="action_menu_overflow_description" msgid="2295659037509008453">"Izinketho ezingaphezulu"</string>
<string name="action_bar_home_description_format" msgid="7965984360903693903">"%1$s, %2$s"</string>
<string name="action_bar_home_subtitle_description_format" msgid="6985546530471780727">"%1$s, %2$s, %3$s"</string>
- <string name="storage_internal" msgid="4891916833657929263">"Isitoreji sangaphakathi"</string>
+ <!-- no translation found for storage_internal (3570990907910199483) -->
+ <skip />
<string name="storage_sd_card" msgid="3282948861378286745">"Ikhadi le-SD"</string>
<string name="storage_sd_card_label" msgid="6347111320774379257">"<xliff:g id="MANUFACTURER">%s</xliff:g> ikhadi le-SD"</string>
<string name="storage_usb_drive" msgid="6261899683292244209">"Idrayivu ye-USB"</string>
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 7711825ecad5..48aa44059b82 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -130,11 +130,15 @@
<drawable name="notification_template_divider">#29000000</drawable>
<drawable name="notification_template_divider_media">#29ffffff</drawable>
+ <color name="notification_material_background_color">#ffffffff</color>
+
<color name="notification_default_color">#757575</color> <!-- Gray 600 -->
<color name="notification_icon_default_color">@color/notification_default_color</color>
<color name="notification_progress_background_color">@color/secondary_text_material_light</color>
+ <color name="notification_action_list">#ffeeeeee</color>
+
<!-- Keyguard colors -->
<color name="keyguard_avatar_frame_color">#ffffffff</color>
<color name="keyguard_avatar_frame_shadow_color">#80000000</color>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index ba9bcaa03239..74ce753412a0 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3368,8 +3368,8 @@
tapping/clicking the whole thing is going to do. -->
<string name="action_bar_home_subtitle_description_format">%1$s, %2$s, %3$s</string>
- <!-- Storage description for internal storage. [CHAR LIMIT=NONE] -->
- <string name="storage_internal">Internal storage</string>
+ <!-- Storage description for internal shared storage. [CHAR LIMIT=NONE] -->
+ <string name="storage_internal">Internal shared storage</string>
<!-- Storage description for a generic SD card. [CHAR LIMIT=NONE] -->
<string name="storage_sd_card">SD card</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 8b7818312495..ce7d80bfe223 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2537,6 +2537,9 @@
<java-symbol type="string" name="usb_mtp_launch_notification_title" />
<java-symbol type="string" name="usb_mtp_launch_notification_description" />
+ <java-symbol type="color" name="notification_action_list" />
+ <java-symbol type="color" name="notification_material_background_color" />
+
<!-- Resolver target actions -->
<java-symbol type="array" name="resolver_target_actions_pin" />
<java-symbol type="array" name="resolver_target_actions_unpin" />
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index d554a5014a52..cbed96caf348 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -20,6 +20,8 @@ import android.graphics.Paint.FontMetricsInt;
import android.test.suitebuilder.annotation.SmallTest;
import android.text.Layout.Alignment;
import static android.text.Layout.Alignment.*;
+import android.text.TextPaint;
+import android.text.method.EditorState;
import android.util.Log;
import junit.framework.TestCase;
@@ -33,6 +35,10 @@ import junit.framework.TestCase;
* @Suppress
*/
public class StaticLayoutTest extends TestCase {
+ private static final int DEFAULT_OUTER_WIDTH = 150;
+ private static final Alignment DEFAULT_ALIGN = Alignment.ALIGN_CENTER;
+ private static final float SPACE_MULTI = 1.0f;
+ private static final float SPACE_ADD = 0.0f;
/**
* Basic test showing expected behavior and relationship between font
@@ -321,4 +327,91 @@ public class StaticLayoutTest extends TestCase {
assertEquals(topPad, l.getTopPadding());
assertEquals(botPad, l.getBottomPadding());
}
+
+ private void moveCursorToRightCursorableOffset(EditorState state, TextPaint paint) {
+ assertEquals("The editor has selection", state.mSelectionStart, state.mSelectionEnd);
+ final Layout layout = builder().setText(state.mText.toString()).setPaint(paint).build();
+ final int newOffset = layout.getOffsetToRightOf(state.mSelectionStart);
+ state.mSelectionStart = state.mSelectionEnd = newOffset;
+ }
+
+ private void moveCursorToLeftCursorableOffset(EditorState state, TextPaint paint) {
+ assertEquals("The editor has selection", state.mSelectionStart, state.mSelectionEnd);
+ final Layout layout = builder().setText(state.mText.toString()).setPaint(paint).build();
+ final int newOffset = layout.getOffsetToLeftOf(state.mSelectionStart);
+ state.mSelectionStart = state.mSelectionEnd = newOffset;
+ }
+
+ /**
+ * Tests for keycap, variation selectors, flags are in CTS.
+ * See {@link android.text.cts.StaticLayoutTest}.
+ */
+ public void testEmojiOffset() {
+ EditorState state = new EditorState();
+ TextPaint paint = new TextPaint();
+
+ // Odd numbered regional indicator symbols.
+ // U+1F1E6 is REGIONAL INDICATOR SYMBOL LETTER A, U+1F1E8 is REGIONAL INDICATOR SYMBOL
+ // LETTER C.
+ state.setByString("| U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+1F1E6 U+1F1E8 | U+1F1E6 U+1F1E8 U+1F1E6");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 | U+1F1E6");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6 |");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6 |");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 | U+1F1E6");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("U+1F1E6 U+1F1E8 | U+1F1E6 U+1F1E8 U+1F1E6");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("| U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("| U+1F1E6 U+1F1E8 U+1F1E6 U+1F1E8 U+1F1E6");
+ moveCursorToLeftCursorableOffset(state, paint);
+
+ // Zero width sequence
+ final String zwjSequence = "U+1F468 U+200D U+2764 U+FE0F U+200D U+1F468";
+ state.setByString("| " + zwjSequence + " " + zwjSequence + " " + zwjSequence);
+ moveCursorToRightCursorableOffset(state, paint);
+ state.assertEquals(zwjSequence + " | " + zwjSequence + " " + zwjSequence);
+ moveCursorToRightCursorableOffset(state, paint);
+ state.assertEquals(zwjSequence + " " + zwjSequence + " | " + zwjSequence);
+ moveCursorToRightCursorableOffset(state, paint);
+ state.assertEquals(zwjSequence + " " + zwjSequence + " " + zwjSequence + " |");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.assertEquals(zwjSequence + " " + zwjSequence + " " + zwjSequence + " |");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.assertEquals(zwjSequence + " " + zwjSequence + " | " + zwjSequence);
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.assertEquals(zwjSequence + " | " + zwjSequence + " " + zwjSequence);
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.assertEquals("| " + zwjSequence + " " + zwjSequence + " " + zwjSequence);
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.assertEquals("| " + zwjSequence + " " + zwjSequence + " " + zwjSequence);
+ moveCursorToLeftCursorableOffset(state, paint);
+
+ // Emoji modifiers
+ // U+261D is WHITE UP POINTING INDEX, U+1F3FB is EMOJI MODIFIER FITZPATRICK TYPE-1-2.
+ state.setByString("| U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+261D U+1F3FB | U+261D U+1F3FB U+261D U+1F3FB");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+261D U+1F3FB U+261D U+1F3FB | U+261D U+1F3FB");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB |");
+ moveCursorToRightCursorableOffset(state, paint);
+ state.setByString("U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB |");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("U+261D U+1F3FB U+261D U+1F3FB | U+261D U+1F3FB");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("U+261D U+1F3FB | U+261D U+1F3FB U+261D U+1F3FB");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("| U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB");
+ moveCursorToLeftCursorableOffset(state, paint);
+ state.setByString("| U+261D U+1F3FB U+261D U+1F3FB U+261D U+1F3FB");
+ moveCursorToLeftCursorableOffset(state, paint);
+ }
}
diff --git a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
index 923b8299a60a..3fbc16a655aa 100644
--- a/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
+++ b/core/tests/coretests/src/android/widget/TextViewActivityMouseTest.java
@@ -44,6 +44,7 @@ import com.android.frameworks.coretests.R;
import android.support.test.espresso.Espresso;
import android.test.ActivityInstrumentationTestCase2;
import android.test.suitebuilder.annotation.SmallTest;
+import android.test.suitebuilder.annotation.Suppress;
import android.view.MotionEvent;
import android.widget.espresso.ContextMenuUtils;
@@ -97,6 +98,7 @@ public class TextViewActivityMouseTest extends ActivityInstrumentationTestCase2<
}
@SmallTest
+ @Suppress
public void testContextMenu() throws Exception {
final String text = "abc def ghi.";
onView(withId(R.id.textview)).perform(click());
diff --git a/graphics/java/android/graphics/NinePatch.java b/graphics/java/android/graphics/NinePatch.java
index 5efc00c8fda5..b6a209f25df9 100644
--- a/graphics/java/android/graphics/NinePatch.java
+++ b/graphics/java/android/graphics/NinePatch.java
@@ -45,15 +45,11 @@ public class NinePatch {
int outlineLeft, int outlineTop, int outlineRight, int outlineBottom,
float outlineRadius, int outlineAlpha, float decodeScale) {
opticalRect = new Rect(opticalLeft, opticalTop, opticalRight, opticalBottom);
- outlineRect = new Rect(outlineLeft, outlineTop, outlineRight, outlineBottom);
+ opticalRect.scale(decodeScale);
- if (decodeScale != 1.0f) {
- // if bitmap was scaled when decoded, scale the insets from the metadata values
- opticalRect.scale(decodeScale);
+ outlineRect = scaleInsets(outlineLeft, outlineTop,
+ outlineRight, outlineBottom, decodeScale);
- // round inward while scaling outline, as the outline should always be conservative
- outlineRect.scaleRoundIn(decodeScale);
- }
this.outlineRadius = outlineRadius * decodeScale;
this.outlineAlpha = outlineAlpha / 255.0f;
}
@@ -62,6 +58,23 @@ public class NinePatch {
public final Rect outlineRect;
public final float outlineRadius;
public final float outlineAlpha;
+
+ /**
+ * Scales up the rect by the given scale, ceiling values, so actual outline Rect
+ * grows toward the inside.
+ */
+ public static Rect scaleInsets(int left, int top, int right, int bottom, float scale) {
+ if (scale == 1.0f) {
+ return new Rect(left, top, right, bottom);
+ }
+
+ Rect result = new Rect();
+ result.left = (int) Math.ceil(left * scale);
+ result.top = (int) Math.ceil(top * scale);
+ result.right = (int) Math.ceil(right * scale);
+ result.bottom = (int) Math.ceil(bottom * scale);
+ return result;
+ }
}
private final Bitmap mBitmap;
diff --git a/graphics/java/android/graphics/Rect.java b/graphics/java/android/graphics/Rect.java
index 93ef3f0c5f9b..7f579a2fd404 100644
--- a/graphics/java/android/graphics/Rect.java
+++ b/graphics/java/android/graphics/Rect.java
@@ -647,16 +647,4 @@ public final class Rect implements Parcelable {
}
}
- /**
- * Scales up the rect by the given scale, rounding values toward the inside.
- * @hide
- */
- public void scaleRoundIn(float scale) {
- if (scale != 1.0f) {
- left = (int) Math.ceil(left * scale);
- top = (int) Math.ceil(top * scale);
- right = (int) Math.floor(right * scale);
- bottom = (int) Math.floor(bottom * scale);
- }
- }
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index ae9ebc762d76..46a0f438e8a4 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -804,7 +804,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
}
private interface VectorDrawableAnimator {
- void init(AnimatorSet set);
+ void init(@NonNull AnimatorSet set);
void start();
void end();
void reset();
@@ -818,21 +818,44 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
}
private static class VectorDrawableAnimatorUI implements VectorDrawableAnimator {
- private AnimatorSet mSet = new AnimatorSet();
+ // mSet is only initialized in init(). So we need to check whether it is null before any
+ // operation.
+ private AnimatorSet mSet = null;
private final Drawable mDrawable;
+ // Caching the listener in the case when listener operation is called before the mSet is
+ // setup by init().
+ private ArrayList<AnimatorListener> mListenerArray = null;
- VectorDrawableAnimatorUI(AnimatedVectorDrawable drawable) {
+ VectorDrawableAnimatorUI(@NonNull AnimatedVectorDrawable drawable) {
mDrawable = drawable;
}
@Override
- public void init(AnimatorSet set) {
- mSet = set;
+ public void init(@NonNull AnimatorSet set) {
+ if (mSet != null) {
+ // Already initialized
+ throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
+ "re-initialized");
+ }
+ // Keep a deep copy of the set, such that set can be still be constantly representing
+ // the static content from XML file.
+ mSet = set.clone();
+
+ // If there are listeners added before calling init(), now they should be setup.
+ if (mListenerArray != null && !mListenerArray.isEmpty()) {
+ for (int i = 0; i < mListenerArray.size(); i++) {
+ mSet.addListener(mListenerArray.get(i));
+ }
+ mListenerArray.clear();
+ mListenerArray = null;
+ }
}
+ // Although start(), reset() and reverse() should call init() already, it is better to
+ // protect these functions from NPE in any situation.
@Override
public void start() {
- if (mSet.isStarted()) {
+ if (mSet == null || mSet.isStarted()) {
return;
}
mSet.start();
@@ -841,51 +864,74 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
@Override
public void end() {
+ if (mSet == null) {
+ return;
+ }
mSet.end();
}
@Override
public void reset() {
+ if (mSet == null) {
+ return;
+ }
start();
mSet.cancel();
}
@Override
public void reverse() {
+ if (mSet == null) {
+ return;
+ }
mSet.reverse();
invalidateOwningView();
}
@Override
public boolean canReverse() {
- return mSet.canReverse();
+ return mSet != null && mSet.canReverse();
}
@Override
public void setListener(AnimatorListener listener) {
- mSet.addListener(listener);
+ if (mSet == null) {
+ if (mListenerArray == null) {
+ mListenerArray = new ArrayList<AnimatorListener>();
+ }
+ mListenerArray.add(listener);
+ } else {
+ mSet.addListener(listener);
+ }
}
@Override
public void removeListener(AnimatorListener listener) {
- mSet.removeListener(listener);
+ if (mSet == null) {
+ if (mListenerArray == null) {
+ return;
+ }
+ mListenerArray.remove(listener);
+ } else {
+ mSet.removeListener(listener);
+ }
}
@Override
public void onDraw(Canvas canvas) {
- if (mSet.isStarted()) {
+ if (mSet != null && mSet.isStarted()) {
invalidateOwningView();
}
}
@Override
public boolean isStarted() {
- return mSet.isStarted();
+ return mSet != null && mSet.isStarted();
}
@Override
public boolean isRunning() {
- return mSet.isRunning();
+ return mSet != null && mSet.isRunning();
}
private void invalidateOwningView() {
@@ -928,7 +974,7 @@ public class AnimatedVectorDrawable extends Drawable implements Animatable2 {
}
@Override
- public void init(AnimatorSet set) {
+ public void init(@NonNull AnimatorSet set) {
if (mInitialized) {
// Already initialized
throw new UnsupportedOperationException("VectorDrawableAnimator cannot be " +
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 5b1cc80665f0..d96238521f94 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -706,18 +706,9 @@ public class NinePatchDrawable extends Drawable {
final NinePatch.InsetStruct insets = ninePatch.getBitmap().getNinePatchInsets();
if (insets != null) {
- if (mOutlineInsets == null) {
- mOutlineInsets = new Rect();
- }
- final Rect outlineInsets = insets.outlineRect;
- mOutlineInsets.left = Drawable.scaleFromDensity(
- outlineInsets.left, sourceDensity, targetDensity, false);
- mOutlineInsets.top = Drawable.scaleFromDensity(
- outlineInsets.top, sourceDensity, targetDensity, false);
- mOutlineInsets.right = Drawable.scaleFromDensity(
- outlineInsets.right, sourceDensity, targetDensity, false);
- mOutlineInsets.bottom = Drawable.scaleFromDensity(
- outlineInsets.bottom, sourceDensity, targetDensity, false);
+ Rect outlineRect = insets.outlineRect;
+ mOutlineInsets = NinePatch.InsetStruct.scaleInsets(outlineRect.left, outlineRect.top,
+ outlineRect.right, outlineRect.bottom, targetDensity / (float) sourceDensity);
mOutlineRadius = Drawable.scaleFromDensity(
insets.outlineRadius, sourceDensity, targetDensity);
} else {
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
index 156f45f6db99..be390ffca2d9 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreBCWorkaroundProvider.java
@@ -193,12 +193,12 @@ class AndroidKeyStoreBCWorkaroundProvider extends Provider {
putSignatureImpl("NONEwithECDSA",
PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$NONE");
- putSignatureImpl("ECDSA", PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA1");
- put("Alg.Alias.Signature.SHA1withECDSA", "ECDSA");
- put("Alg.Alias.Signature.ECDSAwithSHA1", "ECDSA");
+ putSignatureImpl("SHA1withECDSA", PACKAGE_NAME + ".AndroidKeyStoreECDSASignatureSpi$SHA1");
+ put("Alg.Alias.Signature.ECDSA", "SHA1withECDSA");
+ put("Alg.Alias.Signature.ECDSAwithSHA1", "SHA1withECDSA");
// iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA1(1)
- put("Alg.Alias.Signature.1.2.840.10045.4.1", "ECDSA");
- put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10045.2.1", "ECDSA");
+ put("Alg.Alias.Signature.1.2.840.10045.4.1", "SHA1withECDSA");
+ put("Alg.Alias.Signature.1.3.14.3.2.26with1.2.840.10045.2.1", "SHA1withECDSA");
// iso(1) member-body(2) us(840) ansi-x962(10045) signatures(4) ecdsa-with-SHA2(3)
putSignatureImpl("SHA224withECDSA",
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index ca077389b629..516591b2f099 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -12,6 +12,11 @@ HWUI_ENABLE_OPENGL_VALIDATION := true
hwui_src_files := \
font/CacheTexture.cpp \
font/Font.cpp \
+ hwui/Canvas.cpp \
+ hwui/MinikinSkia.cpp \
+ hwui/MinikinUtils.cpp \
+ hwui/PaintImpl.cpp \
+ hwui/Typeface.cpp \
renderstate/Blend.cpp \
renderstate/MeshState.cpp \
renderstate/OffscreenBufferPool.cpp \
@@ -41,7 +46,6 @@ hwui_src_files := \
AnimatorManager.cpp \
AssetAtlas.cpp \
Caches.cpp \
- Canvas.cpp \
CanvasState.cpp \
ClipArea.cpp \
DamageAccumulator.cpp \
@@ -143,7 +147,9 @@ endef
hwui_c_includes += \
external/skia/include/private \
- external/skia/src/core
+ external/skia/src/core \
+ external/harfbuzz_ng/src \
+ external/freetype/include
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
hwui_cflags += -DANDROID_ENABLE_RENDERSCRIPT
diff --git a/libs/hwui/Canvas.cpp b/libs/hwui/Canvas.cpp
deleted file mode 100644
index 11ae1a137e2e..000000000000
--- a/libs/hwui/Canvas.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Canvas.h"
-
-#include "DisplayListCanvas.h"
-#include "RecordingCanvas.h"
-#include <SkDrawFilter.h>
-
-namespace android {
-
-Canvas* Canvas::create_recording_canvas(int width, int height) {
-#if HWUI_NEW_OPS
- return new uirenderer::RecordingCanvas(width, height);
-#else
- return new uirenderer::DisplayListCanvas(width, height);
-#endif
-}
-
-void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
- uint32_t flags;
- SkDrawFilter* drawFilter = getDrawFilter();
- if (drawFilter) {
- SkPaint paintCopy(paint);
- drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
- flags = paintCopy.getFlags();
- } else {
- flags = paint.getFlags();
- }
- if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
- // Same values used by Skia
- const float kStdStrikeThru_Offset = (-6.0f / 21.0f);
- const float kStdUnderline_Offset = (1.0f / 9.0f);
- const float kStdUnderline_Thickness = (1.0f / 18.0f);
-
- SkScalar left = x;
- SkScalar right = x + length;
- float textSize = paint.getTextSize();
- float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
- if (flags & SkPaint::kUnderlineText_Flag) {
- SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
- drawRect(left, top, right, bottom, paint);
- }
- if (flags & SkPaint::kStrikeThruText_Flag) {
- SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
- SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
- drawRect(left, top, right, bottom, paint);
- }
- }
-}
-
-} // namespace android
diff --git a/libs/hwui/CanvasState.cpp b/libs/hwui/CanvasState.cpp
index 43ff33f2b997..e2149d1e4a69 100644
--- a/libs/hwui/CanvasState.cpp
+++ b/libs/hwui/CanvasState.cpp
@@ -14,8 +14,8 @@
* limitations under the License.
*/
-#include "Canvas.h"
#include "CanvasState.h"
+#include "hwui/Canvas.h"
#include "utils/MathUtils.h"
namespace android {
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 6a3c8902dff1..44a24c840892 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -47,6 +47,9 @@ public:
return false;
}
+ int getWidth() { return mWidth; }
+ int getHeight() { return mHeight; }
+
ANDROID_API bool setBlend(bool blend) {
if (blend != mBlend) {
mBlend = blend;
@@ -75,6 +78,10 @@ public:
mTransform = matrix ? new SkMatrix(*matrix) : nullptr;
}
+ SkMatrix* getTransform() {
+ return mTransform;
+ }
+
ANDROID_API void setPaint(const SkPaint* paint);
void apply();
diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp
index a14bdc4693e6..2dccf32a7c78 100644
--- a/libs/hwui/DisplayListCanvas.cpp
+++ b/libs/hwui/DisplayListCanvas.cpp
@@ -418,7 +418,7 @@ void DisplayListCanvas::drawVectorDrawable(VectorDrawableRoot* tree) {
addDrawOp(new (alloc()) DrawVectorDrawableOp(tree));
}
-void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count,
+void DisplayListCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count,
const SkPath& path, float hOffset, float vOffset, const SkPaint& paint) {
if (!glyphs || count <= 0) return;
@@ -429,7 +429,7 @@ void DisplayListCanvas::drawTextOnPath(const uint16_t* glyphs, int count,
addDrawOp(op);
}
-void DisplayListCanvas::drawText(const uint16_t* glyphs, const float* positions,
+void DisplayListCanvas::drawGlyphs(const uint16_t* glyphs, const float* positions,
int count, const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) {
diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h
index a703e227fc8d..d6a5794734d6 100644
--- a/libs/hwui/DisplayListCanvas.h
+++ b/libs/hwui/DisplayListCanvas.h
@@ -17,12 +17,12 @@
#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
-#include "Canvas.h"
#include "CanvasState.h"
#include "DisplayList.h"
#include "RenderNode.h"
#include "ResourceCache.h"
#include "SkiaCanvasProxy.h"
+#include "hwui/Canvas.h"
#include "utils/Macros.h"
#include <SkDrawFilter.h>
@@ -209,10 +209,10 @@ public:
virtual void drawVectorDrawable(VectorDrawableRoot* tree) override;
// Text
- virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
+ virtual void drawGlyphs(const uint16_t* glyphs, const float* positions, int count,
const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
float boundsRight, float boundsBottom, float totalAdvance) override;
- virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+ virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) override;
virtual bool drawTextAbsolutePos() const override { return false; }
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index fc396825029f..fae8e489f337 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -16,11 +16,11 @@
#include "FrameBuilder.h"
-#include "Canvas.h"
#include "LayerUpdateQueue.h"
#include "RenderNode.h"
#include "VectorDrawable.h"
#include "renderstate/OffscreenBufferPool.h"
+#include "hwui/Canvas.h"
#include "utils/FatVector.h"
#include "utils/PaintUtils.h"
#include "utils/TraceUtils.h"
@@ -34,7 +34,7 @@ namespace uirenderer {
FrameBuilder::FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
uint32_t viewportWidth, uint32_t viewportHeight,
const std::vector< sp<RenderNode> >& nodes,
- const LightGeometry& lightGeometry, const Rect &contentDrawBounds, Caches* caches)
+ const LightGeometry& lightGeometry, const Rect &contentDrawBounds, Caches& caches)
: mCanvasState(*this)
, mCaches(caches)
, mLightRadius(lightGeometry.radius) {
@@ -364,15 +364,13 @@ void FrameBuilder::deferShadow(const RenderNodeOp& casterNodeOp) {
casterPath = frameAllocatedPath;
}
-
if (CC_LIKELY(!mCanvasState.getRenderTargetClipBounds().isEmpty())) {
Matrix4 shadowMatrixXY(casterNodeOp.localMatrix);
Matrix4 shadowMatrixZ(casterNodeOp.localMatrix);
node.applyViewPropertyTransforms(shadowMatrixXY, false);
node.applyViewPropertyTransforms(shadowMatrixZ, true);
- LOG_ALWAYS_FATAL_IF(!mCaches, "Caches needed for shadows");
- sp<TessellationCache::ShadowTask> task = mCaches->tessellationCache.getShadowTask(
+ sp<TessellationCache::ShadowTask> task = mCaches.tessellationCache.getShadowTask(
mCanvasState.currentTransform(),
mCanvasState.getLocalClipBounds(),
casterAlpha >= 1.0f,
@@ -483,13 +481,14 @@ void FrameBuilder::deferRenderNodeOp(const RenderNodeOp& op) {
* Defers an unmergeable, strokeable op, accounting correctly
* for paint's style on the bounds being computed.
*/
-void FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
+const BakedOpState* FrameBuilder::deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
BakedOpState::StrokeBehavior strokeBehavior) {
// Note: here we account for stroke when baking the op
BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct(
mAllocator, *mCanvasState.writableSnapshot(), op, strokeBehavior);
- if (!bakedState) return; // quick rejected
+ if (!bakedState) return nullptr; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, batchId);
+ return bakedState;
}
/**
@@ -607,7 +606,10 @@ void FrameBuilder::deferPatchOp(const PatchOp& op) {
}
void FrameBuilder::deferPathOp(const PathOp& op) {
- deferStrokeableOp(op, OpBatchType::Bitmap);
+ auto state = deferStrokeableOp(op, OpBatchType::AlphaMaskTexture);
+ if (CC_LIKELY(state)) {
+ mCaches.pathCache.precache(op.path, op.paint);
+ }
}
void FrameBuilder::deferPointsOp(const PointsOp& op) {
@@ -620,7 +622,12 @@ void FrameBuilder::deferRectOp(const RectOp& op) {
}
void FrameBuilder::deferRoundRectOp(const RoundRectOp& op) {
- deferStrokeableOp(op, tessBatchId(op));
+ auto state = deferStrokeableOp(op, tessBatchId(op));
+ if (CC_LIKELY(state && !op.paint->getPathEffect())) {
+ // TODO: consider storing tessellation task in BakedOpState
+ mCaches.tessellationCache.precacheRoundRect(state->computedState.transform, *(op.paint),
+ op.unmappedBounds.getWidth(), op.unmappedBounds.getHeight(), op.rx, op.ry);
+ }
}
void FrameBuilder::deferRoundRectPropsOp(const RoundRectPropsOp& op) {
@@ -660,15 +667,32 @@ void FrameBuilder::deferTextOp(const TextOp& op) {
} else {
currentLayer().deferUnmergeableOp(mAllocator, bakedState, batchId);
}
+
+ FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer();
+ auto& totalTransform = bakedState->computedState.transform;
+ if (totalTransform.isPureTranslate() || totalTransform.isPerspective()) {
+ fontRenderer.precache(op.paint, op.glyphs, op.glyphCount, SkMatrix::I());
+ } else {
+ // Partial transform case, see BakedOpDispatcher::renderTextOp
+ float sx, sy;
+ totalTransform.decomposeScale(sx, sy);
+ fontRenderer.precache(op.paint, op.glyphs, op.glyphCount, SkMatrix::MakeScale(
+ roundf(std::max(1.0f, sx)),
+ roundf(std::max(1.0f, sy))));
+ }
}
void FrameBuilder::deferTextOnPathOp(const TextOnPathOp& op) {
BakedOpState* bakedState = tryBakeUnboundedOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint)));
+
+ mCaches.fontRenderer.getFontRenderer().precache(
+ op.paint, op.glyphs, op.glyphCount, SkMatrix::I());
}
void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) {
+ if (CC_UNLIKELY(!op.layer->isRenderable())) return;
BakedOpState* bakedState = tryBakeOpState(op);
if (!bakedState) return; // quick rejected
currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::TextureLayer);
@@ -826,5 +850,9 @@ void FrameBuilder::deferEndUnclippedLayerOp(const EndUnclippedLayerOp& /* ignore
}
}
+void FrameBuilder::finishDefer() {
+ mCaches.fontRenderer.endPrecaching();
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/FrameBuilder.h b/libs/hwui/FrameBuilder.h
index 8a00d336dc08..0b7a6062456a 100644
--- a/libs/hwui/FrameBuilder.h
+++ b/libs/hwui/FrameBuilder.h
@@ -65,14 +65,16 @@ public:
uint32_t viewportWidth, uint32_t viewportHeight,
const std::vector< sp<RenderNode> >& nodes,
const LightGeometry& lightGeometry,
- Caches* caches)
- : FrameBuilder(layers, clip, viewportWidth, viewportHeight, nodes, lightGeometry, Rect(), caches) {}
+ Caches& caches)
+ : FrameBuilder(layers, clip, viewportWidth, viewportHeight,
+ nodes, lightGeometry, Rect(), caches) {}
FrameBuilder(const LayerUpdateQueue& layers, const SkRect& clip,
uint32_t viewportWidth, uint32_t viewportHeight,
const std::vector< sp<RenderNode> >& nodes,
const LightGeometry& lightGeometry,
- const Rect &contentDrawBounds, Caches* caches);
+ const Rect &contentDrawBounds,
+ Caches& caches);
virtual ~FrameBuilder() {}
@@ -81,10 +83,10 @@ public:
*
* It constructs a lookup array of lambdas, which allows a recorded BakeOpState to use
* state->op->opId to lookup a receiver that will be called when the op is replayed.
- *
*/
template <typename StaticDispatcher, typename Renderer>
void replayBakedOps(Renderer& renderer) {
+ finishDefer();
/**
* Defines a LUT of lambdas which allow a recorded BakedOpState to use state->op->opId to
* dispatch the op via a method on a static dispatcher when the op is replayed.
@@ -157,6 +159,7 @@ public:
virtual GLuint getTargetFbo() const override { return 0; }
private:
+ void finishDefer();
enum class ChildrenSelectMode {
Negative,
Positive
@@ -198,7 +201,7 @@ private:
return mAllocator.create<SkPath>();
}
- void deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
+ const BakedOpState* deferStrokeableOp(const RecordedOp& op, batchid_t batchId,
BakedOpState::StrokeBehavior strokeBehavior = BakedOpState::StrokeBehavior::StyleDefined);
/**
@@ -230,7 +233,7 @@ private:
CanvasState mCanvasState;
- Caches* mCaches = nullptr;
+ Caches& mCaches;
float mLightRadius;
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index e00ae66997a5..1e5498bb3d21 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -216,6 +216,10 @@ public:
this->renderTarget = renderTarget;
}
+ inline bool isRenderable() const {
+ return renderTarget != GL_NONE;
+ }
+
void setWrap(GLenum wrap, bool bindTexture = false, bool force = false) {
texture.setWrap(wrap, bindTexture, force, renderTarget);
}
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 5bce8ac83020..137316f57725 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -353,7 +353,7 @@ void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) {
bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) {
Caches& caches = Caches::getInstance();
- if (layer && layer->getRenderTarget() != GL_NONE
+ if (layer && layer->isRenderable()
&& bitmap->width() <= caches.maxTextureSize
&& bitmap->height() <= caches.maxTextureSize) {
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 7693fdcbe817..c0994272c964 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -17,7 +17,6 @@
#include <GpuMemoryTracker.h>
#include "OpenGLRenderer.h"
-#include "Canvas.h"
#include "DeferredDisplayList.h"
#include "GammaFontRenderer.h"
#include "Glop.h"
@@ -32,6 +31,7 @@
#include "SkiaShader.h"
#include "Vector.h"
#include "VertexBuffer.h"
+#include "hwui/Canvas.h"
#include "utils/GLUtils.h"
#include "utils/PaintUtils.h"
#include "utils/TraceUtils.h"
diff --git a/libs/hwui/RecordingCanvas.cpp b/libs/hwui/RecordingCanvas.cpp
index 1546baf88691..4eeadb7ad30f 100644
--- a/libs/hwui/RecordingCanvas.cpp
+++ b/libs/hwui/RecordingCanvas.cpp
@@ -514,7 +514,7 @@ void RecordingCanvas::drawNinePatch(const SkBitmap& bitmap, const android::Res_p
}
// Text
-void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, int glyphCount,
+void RecordingCanvas::drawGlyphs(const uint16_t* glyphs, const float* positions, int glyphCount,
const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
float boundsRight, float boundsBottom, float totalAdvance) {
if (!glyphs || !positions || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
@@ -530,7 +530,7 @@ void RecordingCanvas::drawText(const uint16_t* glyphs, const float* positions, i
drawTextDecorations(x, y, totalAdvance, paint);
}
-void RecordingCanvas::drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
+void RecordingCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) {
if (!glyphs || glyphCount <= 0 || PaintUtils::paintWillNotDrawText(paint)) return;
glyphs = refBuffer<glyph_t>(glyphs, glyphCount);
@@ -574,15 +574,19 @@ void RecordingCanvas::drawLayer(DeferredLayerUpdater* layerHandle) {
// We ref the DeferredLayerUpdater due to its thread-safe ref-counting semantics.
mDisplayList->ref(layerHandle);
- Layer* layer = layerHandle->backingLayer();
+ // Note that the backing layer has *not* yet been updated, so don't trust
+ // its width, height, transform, etc...!
Matrix4 totalTransform(*(mState.currentSnapshot()->transform));
- totalTransform.multiply(layer->getTransform());
+ if (layerHandle->getTransform()) {
+ Matrix4 layerTransform(*layerHandle->getTransform());
+ totalTransform.multiply(layerTransform);
+ }
addOp(alloc().create_trivial<TextureLayerOp>(
- Rect(layer->getWidth(), layer->getHeight()),
+ Rect(layerHandle->getWidth(), layerHandle->getHeight()),
totalTransform,
getRecordedClip(),
- layer));
+ layerHandle->backingLayer()));
}
void RecordingCanvas::callDrawGLFunction(Functor* functor) {
diff --git a/libs/hwui/RecordingCanvas.h b/libs/hwui/RecordingCanvas.h
index 719872d35169..1eb4fa0b884f 100644
--- a/libs/hwui/RecordingCanvas.h
+++ b/libs/hwui/RecordingCanvas.h
@@ -17,12 +17,12 @@
#ifndef ANDROID_HWUI_RECORDING_CANVAS_H
#define ANDROID_HWUI_RECORDING_CANVAS_H
-#include "Canvas.h"
#include "CanvasState.h"
#include "DisplayList.h"
#include "ResourceCache.h"
#include "SkiaCanvasProxy.h"
#include "Snapshot.h"
+#include "hwui/Canvas.h"
#include "utils/LinearAllocator.h"
#include "utils/Macros.h"
#include "utils/NinePatch.h"
@@ -191,10 +191,10 @@ public:
const SkPaint* paint) override;
// Text
- virtual void drawText(const uint16_t* glyphs, const float* positions, int glyphCount,
+ virtual void drawGlyphs(const uint16_t* glyphs, const float* positions, int glyphCount,
const SkPaint& paint, float x, float y, float boundsLeft, float boundsTop,
float boundsRight, float boundsBottom, float totalAdvance) override;
- virtual void drawTextOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
+ virtual void drawGlyphsOnPath(const uint16_t* glyphs, int glyphCount, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) override;
virtual bool drawTextAbsolutePos() const override { return false; }
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 0b0f0fa4f304..f577785110d3 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -23,9 +23,9 @@
#include <SkPath.h>
#include <SkPathOps.h>
-#include "Canvas.h"
#include "Matrix.h"
#include "OpenGLRenderer.h"
+#include "hwui/Canvas.h"
#include "utils/MathUtils.h"
namespace android {
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index bd4442dc378d..b1ecb7112207 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-#include "Canvas.h"
#include "CanvasProperty.h"
#include "Layer.h"
#include "RenderNode.h"
+#include "hwui/Canvas.h"
#include <SkCanvas.h>
#include <SkClipStack.h>
@@ -147,11 +147,11 @@ public:
float dstLeft, float dstTop, float dstRight, float dstBottom,
const SkPaint* paint) override;
- virtual void drawText(const uint16_t* text, const float* positions, int count,
+ virtual void drawGlyphs(const uint16_t* text, const float* positions, int count,
const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) override;
- virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+ virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) override;
virtual bool drawTextAbsolutePos() const override { return true; }
@@ -757,7 +757,7 @@ void SkiaCanvas::drawVectorDrawable(VectorDrawableRoot* vectorDrawable) {
// Canvas draw operations: Text
// ----------------------------------------------------------------------------
-void SkiaCanvas::drawText(const uint16_t* text, const float* positions, int count,
+void SkiaCanvas::drawGlyphs(const uint16_t* text, const float* positions, int count,
const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) {
@@ -772,7 +772,7 @@ void SkiaCanvas::drawText(const uint16_t* text, const float* positions, int coun
drawTextDecorations(x, y, totalAdvance, paint);
}
-void SkiaCanvas::drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+void SkiaCanvas::drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) {
mCanvas->drawTextOnPathHV(glyphs, count << 1, path, hOffset, vOffset, paint);
}
diff --git a/libs/hwui/SkiaCanvasProxy.cpp b/libs/hwui/SkiaCanvasProxy.cpp
index 6530d4ed8d50..c6124803eb6a 100644
--- a/libs/hwui/SkiaCanvasProxy.cpp
+++ b/libs/hwui/SkiaCanvasProxy.cpp
@@ -290,7 +290,7 @@ void SkiaCanvasProxy::onDrawText(const void* text, size_t byteLength, SkScalar x
}
static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
- mCanvas->drawText(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint,
+ mCanvas->drawGlyphs(glyphs.glyphIDs, &pointStorage[0].fX, glyphs.count, glyphs.paint,
x, y, bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
}
@@ -326,7 +326,7 @@ void SkiaCanvasProxy::onDrawPosText(const void* text, size_t byteLength, const S
bounds.offset(x, y);
static_assert(sizeof(SkPoint) == sizeof(float)*2, "SkPoint is no longer two floats");
- mCanvas->drawText(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y,
+ mCanvas->drawGlyphs(glyphs.glyphIDs, &posArray[0].fX, glyphs.count, glyphs.paint, x, y,
bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, 0);
}
@@ -344,7 +344,7 @@ void SkiaCanvasProxy::onDrawTextOnPath(const void* text, size_t byteLength, cons
const SkMatrix* matrix, const SkPaint& origPaint) {
// convert to glyphIDs if necessary
GlyphIDConverter glyphs(text, byteLength, origPaint);
- mCanvas->drawTextOnPath(glyphs.glyphIDs, glyphs.count, path, 0, 0, glyphs.paint);
+ mCanvas->drawGlyphsOnPath(glyphs.glyphIDs, glyphs.count, path, 0, 0, glyphs.paint);
}
void SkiaCanvasProxy::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
diff --git a/libs/hwui/SkiaCanvasProxy.h b/libs/hwui/SkiaCanvasProxy.h
index e342d192ea31..973c55fe2236 100644
--- a/libs/hwui/SkiaCanvasProxy.h
+++ b/libs/hwui/SkiaCanvasProxy.h
@@ -20,7 +20,7 @@
#include <cutils/compiler.h>
#include <SkCanvas.h>
-#include "Canvas.h"
+#include "hwui/Canvas.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index cf5e69a1e6ae..d7842801fdd8 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -16,7 +16,7 @@
#include "Snapshot.h"
-#include "Canvas.h"
+#include "hwui/Canvas.h"
namespace android {
namespace uirenderer {
diff --git a/libs/hwui/VectorDrawable.h b/libs/hwui/VectorDrawable.h
index 4d2fed096adf..7a45bf5ca8a8 100644
--- a/libs/hwui/VectorDrawable.h
+++ b/libs/hwui/VectorDrawable.h
@@ -17,7 +17,7 @@
#ifndef ANDROID_HWUI_VPATH_H
#define ANDROID_HWUI_VPATH_H
-#include "Canvas.h"
+#include "hwui/Canvas.h"
#include <SkBitmap.h>
#include <SkColor.h>
diff --git a/libs/hwui/hwui/Canvas.cpp b/libs/hwui/hwui/Canvas.cpp
new file mode 100644
index 000000000000..8c3eea35e783
--- /dev/null
+++ b/libs/hwui/hwui/Canvas.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Canvas.h"
+
+#include "DisplayListCanvas.h"
+#include "RecordingCanvas.h"
+#include "MinikinUtils.h"
+#include "Paint.h"
+#include "Typeface.h"
+
+#include <SkDrawFilter.h>
+
+namespace android {
+
+Canvas* Canvas::create_recording_canvas(int width, int height) {
+#if HWUI_NEW_OPS
+ return new uirenderer::RecordingCanvas(width, height);
+#else
+ return new uirenderer::DisplayListCanvas(width, height);
+#endif
+}
+
+void Canvas::drawTextDecorations(float x, float y, float length, const SkPaint& paint) {
+ uint32_t flags;
+ SkDrawFilter* drawFilter = getDrawFilter();
+ if (drawFilter) {
+ SkPaint paintCopy(paint);
+ drawFilter->filter(&paintCopy, SkDrawFilter::kText_Type);
+ flags = paintCopy.getFlags();
+ } else {
+ flags = paint.getFlags();
+ }
+ if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) {
+ // Same values used by Skia
+ const float kStdStrikeThru_Offset = (-6.0f / 21.0f);
+ const float kStdUnderline_Offset = (1.0f / 9.0f);
+ const float kStdUnderline_Thickness = (1.0f / 18.0f);
+
+ SkScalar left = x;
+ SkScalar right = x + length;
+ float textSize = paint.getTextSize();
+ float strokeWidth = fmax(textSize * kStdUnderline_Thickness, 1.0f);
+ if (flags & SkPaint::kUnderlineText_Flag) {
+ SkScalar top = y + textSize * kStdUnderline_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdUnderline_Offset + 0.5f * strokeWidth;
+ drawRect(left, top, right, bottom, paint);
+ }
+ if (flags & SkPaint::kStrikeThruText_Flag) {
+ SkScalar top = y + textSize * kStdStrikeThru_Offset - 0.5f * strokeWidth;
+ SkScalar bottom = y + textSize * kStdStrikeThru_Offset + 0.5f * strokeWidth;
+ drawRect(left, top, right, bottom, paint);
+ }
+ }
+}
+
+static void simplifyPaint(int color, SkPaint* paint) {
+ paint->setColor(color);
+ paint->setShader(nullptr);
+ paint->setColorFilter(nullptr);
+ paint->setLooper(nullptr);
+ paint->setStrokeWidth(4 + 0.04 * paint->getTextSize());
+ paint->setStrokeJoin(SkPaint::kRound_Join);
+ paint->setLooper(nullptr);
+}
+
+class DrawTextFunctor {
+public:
+ DrawTextFunctor(const Layout& layout, Canvas* canvas, uint16_t* glyphs, float* pos,
+ const SkPaint& paint, float x, float y, MinikinRect& bounds, float totalAdvance)
+ : layout(layout)
+ , canvas(canvas)
+ , glyphs(glyphs)
+ , pos(pos)
+ , paint(paint)
+ , x(x)
+ , y(y)
+ , bounds(bounds)
+ , totalAdvance(totalAdvance) {
+ }
+
+ void operator()(size_t start, size_t end) {
+ if (canvas->drawTextAbsolutePos()) {
+ for (size_t i = start; i < end; i++) {
+ glyphs[i] = layout.getGlyphId(i);
+ pos[2 * i] = x + layout.getX(i);
+ pos[2 * i + 1] = y + layout.getY(i);
+ }
+ } else {
+ for (size_t i = start; i < end; i++) {
+ glyphs[i] = layout.getGlyphId(i);
+ pos[2 * i] = layout.getX(i);
+ pos[2 * i + 1] = layout.getY(i);
+ }
+ }
+
+ size_t glyphCount = end - start;
+
+ if (CC_UNLIKELY(canvas->isHighContrastText() && paint.getAlpha() != 0)) {
+ // high contrast draw path
+ int color = paint.getColor();
+ int channelSum = SkColorGetR(color) + SkColorGetG(color) + SkColorGetB(color);
+ bool darken = channelSum < (128 * 3);
+
+ // outline
+ SkPaint outlinePaint(paint);
+ simplifyPaint(darken ? SK_ColorWHITE : SK_ColorBLACK, &outlinePaint);
+ outlinePaint.setStyle(SkPaint::kStrokeAndFill_Style);
+ canvas->drawGlyphs(glyphs + start, pos + (2 * start), glyphCount, outlinePaint, x, y,
+ bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
+
+ // inner
+ SkPaint innerPaint(paint);
+ simplifyPaint(darken ? SK_ColorBLACK : SK_ColorWHITE, &innerPaint);
+ innerPaint.setStyle(SkPaint::kFill_Style);
+ canvas->drawGlyphs(glyphs + start, pos + (2 * start), glyphCount, innerPaint, x, y,
+ bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
+ } else {
+ // standard draw path
+ canvas->drawGlyphs(glyphs + start, pos + (2 * start), glyphCount, paint, x, y,
+ bounds.mLeft, bounds.mTop, bounds.mRight, bounds.mBottom, totalAdvance);
+ }
+ }
+private:
+ const Layout& layout;
+ Canvas* canvas;
+ uint16_t* glyphs;
+ float* pos;
+ const SkPaint& paint;
+ float x;
+ float y;
+ MinikinRect& bounds;
+ float totalAdvance;
+};
+
+void Canvas::drawText(const uint16_t* text, int start, int count, int contextCount,
+ float x, float y, int bidiFlags, const Paint& origPaint, Typeface* typeface) {
+ // minikin may modify the original paint
+ Paint paint(origPaint);
+
+ Layout layout;
+ MinikinUtils::doLayout(&layout, &paint, bidiFlags, typeface, text, start, count, contextCount);
+
+ size_t nGlyphs = layout.nGlyphs();
+ std::unique_ptr<uint16_t[]> glyphs(new uint16_t[nGlyphs]);
+ std::unique_ptr<float[]> pos(new float[nGlyphs * 2]);
+
+ x += MinikinUtils::xOffsetForTextAlign(&paint, layout);
+
+ MinikinRect bounds;
+ layout.getBounds(&bounds);
+ if (!drawTextAbsolutePos()) {
+ bounds.offset(x, y);
+ }
+
+ DrawTextFunctor f(layout, this, glyphs.get(), pos.get(),
+ paint, x, y, bounds, layout.getAdvance());
+ MinikinUtils::forFontRun(layout, &paint, f);
+}
+
+class DrawTextOnPathFunctor {
+public:
+ DrawTextOnPathFunctor(const Layout& layout, Canvas* canvas, float hOffset,
+ float vOffset, const Paint& paint, const SkPath& path)
+ : layout(layout)
+ , canvas(canvas)
+ , hOffset(hOffset)
+ , vOffset(vOffset)
+ , paint(paint)
+ , path(path) {
+ }
+
+ void operator()(size_t start, size_t end) {
+ uint16_t glyphs[1];
+ for (size_t i = start; i < end; i++) {
+ glyphs[0] = layout.getGlyphId(i);
+ float x = hOffset + layout.getX(i);
+ float y = vOffset + layout.getY(i);
+ canvas->drawGlyphsOnPath(glyphs, 1, path, x, y, paint);
+ }
+ }
+private:
+ const Layout& layout;
+ Canvas* canvas;
+ float hOffset;
+ float vOffset;
+ const Paint& paint;
+ const SkPath& path;
+};
+
+void Canvas::drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
+ float hOffset, float vOffset, const Paint& paint, Typeface* typeface) {
+ Paint paintCopy(paint);
+ Layout layout;
+ MinikinUtils::doLayout(&layout, &paintCopy, bidiFlags, typeface, text, 0, count, count);
+ hOffset += MinikinUtils::hOffsetForTextAlign(&paintCopy, layout, path);
+
+ // Set align to left for drawing, as we don't want individual
+ // glyphs centered or right-aligned; the offset above takes
+ // care of all alignment.
+ paintCopy.setTextAlign(Paint::kLeft_Align);
+
+ DrawTextOnPathFunctor f(layout, this, hOffset, vOffset, paintCopy, path);
+ MinikinUtils::forFontRun(layout, &paintCopy, f);
+}
+
+} // namespace android
diff --git a/libs/hwui/Canvas.h b/libs/hwui/hwui/Canvas.h
index 27facdf652cd..dc669f0b526a 100644
--- a/libs/hwui/Canvas.h
+++ b/libs/hwui/hwui/Canvas.h
@@ -59,6 +59,9 @@ class Tree;
};
typedef uirenderer::VectorDrawable::Tree VectorDrawableRoot;
+class Paint;
+struct Typeface;
+
class ANDROID_API Canvas {
public:
virtual ~Canvas() {};
@@ -207,12 +210,12 @@ public:
* drawText: count is of glyphs
* totalAdvance: used to define width of text decorations (underlines, strikethroughs).
*/
- virtual void drawText(const uint16_t* glyphs, const float* positions, int count,
+ virtual void drawGlyphs(const uint16_t* glyphs, const float* positions, int count,
const SkPaint& paint, float x, float y,
float boundsLeft, float boundsTop, float boundsRight, float boundsBottom,
float totalAdvance) = 0;
/** drawTextOnPath: count is of glyphs */
- virtual void drawTextOnPath(const uint16_t* glyphs, int count, const SkPath& path,
+ virtual void drawGlyphsOnPath(const uint16_t* glyphs, int count, const SkPath& path,
float hOffset, float vOffset, const SkPaint& paint) = 0;
/**
@@ -229,6 +232,16 @@ public:
*/
virtual void drawVectorDrawable(VectorDrawableRoot* tree);
+ /**
+ * Converts utf16 text to glyphs, calculating position and boundary,
+ * and delegating the final draw to virtual drawGlyphs method.
+ */
+ void drawText(const uint16_t* text, int start, int count, int contextCount,
+ float x, float y, int bidiFlags, const Paint& origPaint, Typeface* typeface);
+
+ void drawTextOnPath(const uint16_t* text, int count, int bidiFlags, const SkPath& path,
+ float hOffset, float vOffset, const Paint& paint, Typeface* typeface);
+
protected:
void drawTextDecorations(float x, float y, float length, const SkPaint& paint);
};
diff --git a/core/jni/android/graphics/MinikinSkia.cpp b/libs/hwui/hwui/MinikinSkia.cpp
index 8ac5d4664687..b9e33589885e 100644
--- a/core/jni/android/graphics/MinikinSkia.cpp
+++ b/libs/hwui/hwui/MinikinSkia.cpp
@@ -14,14 +14,12 @@
* limitations under the License.
*/
-#include <SkTypeface.h>
-#include <SkPaint.h>
+#include "MinikinSkia.h"
-#define LOG_TAG "Minikin"
+#include <SkPaint.h>
+#include <SkTypeface.h>
#include <cutils/log.h>
-#include "MinikinSkia.h"
-
namespace android {
MinikinFontSkia::MinikinFontSkia(SkTypeface *typeface) :
diff --git a/core/jni/android/graphics/MinikinSkia.h b/libs/hwui/hwui/MinikinSkia.h
index 8f469ba01ddd..1d50168adac0 100644
--- a/core/jni/android/graphics/MinikinSkia.h
+++ b/libs/hwui/hwui/MinikinSkia.h
@@ -17,11 +17,15 @@
#ifndef _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
#define _ANDROID_GRAPHICS_MINIKIN_SKIA_H_
+#include <cutils/compiler.h>
#include <minikin/MinikinFont.h>
+class SkPaint;
+class SkTypeface;
+
namespace android {
-class MinikinFontSkia : public MinikinFont {
+class ANDROID_API MinikinFontSkia : public MinikinFont {
public:
// Note: this takes ownership of the reference (will unref on dtor)
explicit MinikinFontSkia(SkTypeface *typeface);
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/libs/hwui/hwui/MinikinUtils.cpp
index 309d35b90260..67b775d98356 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/libs/hwui/hwui/MinikinUtils.cpp
@@ -13,22 +13,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#include "MinikinUtils.h"
-#define LOG_TAG "Minikin"
-#include <cutils/log.h>
-#include <string>
-
-#include "SkPathMeasure.h"
#include "Paint.h"
-#include "TypefaceImpl.h"
+#include "SkPathMeasure.h"
+#include "Typeface.h"
-#include "MinikinUtils.h"
+#include <cutils/log.h>
+#include <string>
namespace android {
FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
- const Paint* paint, TypefaceImpl* typeface) {
- const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
+ const Paint* paint, Typeface* typeface) {
+ const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
*pFont = resolvedFace->fFontCollection;
FontStyle resolved = resolvedFace->fStyle;
@@ -53,7 +51,7 @@ FontStyle MinikinUtils::prepareMinikinPaint(MinikinPaint* minikinPaint, FontColl
}
void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags,
- TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
+ Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize) {
FontCollection *font;
MinikinPaint minikinPaint;
@@ -62,7 +60,7 @@ void MinikinUtils::doLayout(Layout* layout, const Paint* paint, int bidiFlags,
layout->doLayout(buf, start, count, bufSize, bidiFlags, minikinStyle, minikinPaint);
}
-float MinikinUtils::measureText(const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
+float MinikinUtils::measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances) {
FontCollection *font;
MinikinPaint minikinPaint;
@@ -71,8 +69,8 @@ float MinikinUtils::measureText(const Paint* paint, int bidiFlags, TypefaceImpl*
font, advances);
}
-bool MinikinUtils::hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs) {
- const TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
+bool MinikinUtils::hasVariationSelector(Typeface* typeface, uint32_t codepoint, uint32_t vs) {
+ const Typeface* resolvedFace = Typeface::resolveDefault(typeface);
return resolvedFace->fFontCollection->hasVariationSelector(codepoint, vs);
}
diff --git a/core/jni/android/graphics/MinikinUtils.h b/libs/hwui/hwui/MinikinUtils.h
index 91525397b2ba..cfaa961ac1fc 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/libs/hwui/hwui/MinikinUtils.h
@@ -24,33 +24,34 @@
#ifndef _ANDROID_GRAPHICS_MINIKIN_UTILS_H_
#define _ANDROID_GRAPHICS_MINIKIN_UTILS_H_
+#include <cutils/compiler.h>
#include <minikin/Layout.h>
#include "Paint.h"
#include "MinikinSkia.h"
-#include "TypefaceImpl.h"
+#include "Typeface.h"
namespace android {
class MinikinUtils {
public:
- static FontStyle prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
- const Paint* paint, TypefaceImpl* typeface);
+ ANDROID_API static FontStyle prepareMinikinPaint(MinikinPaint* minikinPaint, FontCollection** pFont,
+ const Paint* paint, Typeface* typeface);
- static void doLayout(Layout* layout, const Paint* paint, int bidiFlags,
- TypefaceImpl* typeface, const uint16_t* buf, size_t start, size_t count,
+ ANDROID_API static void doLayout(Layout* layout, const Paint* paint, int bidiFlags,
+ Typeface* typeface, const uint16_t* buf, size_t start, size_t count,
size_t bufSize);
- static float measureText(const Paint* paint, int bidiFlags, TypefaceImpl* typeface,
+ ANDROID_API static float measureText(const Paint* paint, int bidiFlags, Typeface* typeface,
const uint16_t* buf, size_t start, size_t count, size_t bufSize, float *advances);
- static bool hasVariationSelector(TypefaceImpl* typeface, uint32_t codepoint, uint32_t vs);
+ ANDROID_API static bool hasVariationSelector(Typeface* typeface, uint32_t codepoint, uint32_t vs);
- static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
+ ANDROID_API static float xOffsetForTextAlign(Paint* paint, const Layout& layout);
- static float hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path);
+ ANDROID_API static float hOffsetForTextAlign(Paint* paint, const Layout& layout, const SkPath& path);
// f is a functor of type void f(size_t start, size_t end);
template <typename F>
- static void forFontRun(const Layout& layout, Paint* paint, F& f) {
+ ANDROID_API static void forFontRun(const Layout& layout, Paint* paint, F& f) {
float saveSkewX = paint->getTextSkewX();
bool savefakeBold = paint->isFakeBoldText();
MinikinFont* curFont = NULL;
diff --git a/core/jni/android/graphics/Paint.h b/libs/hwui/hwui/Paint.h
index cb6e622ccced..69c321ca0caa 100644
--- a/core/jni/android/graphics/Paint.h
+++ b/libs/hwui/hwui/Paint.h
@@ -17,6 +17,8 @@
#ifndef ANDROID_GRAPHICS_PAINT_H_
#define ANDROID_GRAPHICS_PAINT_H_
+#include <cutils/compiler.h>
+
#include <SkPaint.h>
#include <string>
@@ -24,7 +26,7 @@
namespace android {
-class Paint : public SkPaint {
+class ANDROID_API Paint : public SkPaint {
public:
Paint();
Paint(const Paint& paint);
@@ -45,7 +47,7 @@ public:
return mLetterSpacing;
}
- void setFontFeatureSettings(const std::string &fontFeatureSettings) {
+ void setFontFeatureSettings(const std::string& fontFeatureSettings) {
mFontFeatureSettings = fontFeatureSettings;
}
diff --git a/core/jni/android/graphics/PaintImpl.cpp b/libs/hwui/hwui/PaintImpl.cpp
index bd513ae60823..1172a0e044b1 100644
--- a/core/jni/android/graphics/PaintImpl.cpp
+++ b/libs/hwui/hwui/PaintImpl.cpp
@@ -15,10 +15,6 @@
*/
#include "Paint.h"
-#include <SkPaint.h>
-
-#define LOG_TAG "Paint"
-#include <cutils/log.h>
namespace android {
diff --git a/core/jni/android/graphics/TypefaceImpl.cpp b/libs/hwui/hwui/Typeface.cpp
index da56290c94f9..fa8ad5d6ce32 100644
--- a/core/jni/android/graphics/TypefaceImpl.cpp
+++ b/libs/hwui/hwui/Typeface.cpp
@@ -20,26 +20,21 @@
* being, that choice is hidden under the USE_MINIKIN compile-time flag.
*/
-#define LOG_TAG "TypefaceImpl"
-
-#include "jni.h" // for jlong, remove when being passed proper type
+#include "Typeface.h"
+#include "MinikinSkia.h"
#include "SkTypeface.h"
+#include "SkPaint.h"
-#include <vector>
#include <minikin/FontCollection.h>
#include <minikin/FontFamily.h>
#include <minikin/Layout.h>
-#include "SkPaint.h"
-#include "MinikinSkia.h"
-
-#include "TypefaceImpl.h"
-#include "Utils.h"
+#include <utils/Log.h>
namespace android {
// Resolve the 1..9 weight based on base weight and bold flag
-static void resolveStyle(TypefaceImpl* typeface) {
+static void resolveStyle(Typeface* typeface) {
int weight = typeface->fBaseWeight / 100;
if (typeface->fSkiaStyle & SkTypeface::kBold) {
weight += 3;
@@ -51,7 +46,7 @@ static void resolveStyle(TypefaceImpl* typeface) {
typeface->fStyle = FontStyle(weight, italic);
}
-TypefaceImpl* gDefaultTypeface = NULL;
+Typeface* gDefaultTypeface = NULL;
pthread_once_t gDefaultTypefaceOnce = PTHREAD_ONCE_INIT;
// This installs a default typeface (from a hardcoded path) that allows
@@ -90,7 +85,7 @@ static void getDefaultTypefaceOnce() {
if (gDefaultTypeface == NULL) {
// We expect the client to set a default typeface, but provide a
// default so we can make progress before that happens.
- gDefaultTypeface = new TypefaceImpl;
+ gDefaultTypeface = new Typeface;
gDefaultTypeface->fFontCollection = makeFontCollection();
gDefaultTypeface->fSkiaStyle = SkTypeface::kNormal;
gDefaultTypeface->fBaseWeight = 400;
@@ -98,7 +93,7 @@ static void getDefaultTypefaceOnce() {
}
}
-TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
+Typeface* Typeface::resolveDefault(Typeface* src) {
if (src == NULL) {
pthread_once(&gDefaultTypefaceOnce, getDefaultTypefaceOnce);
return gDefaultTypeface;
@@ -107,9 +102,9 @@ TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src) {
}
}
-TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style) {
- TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
- TypefaceImpl* result = new TypefaceImpl;
+Typeface* Typeface::createFromTypeface(Typeface* src, SkTypeface::Style style) {
+ Typeface* resolvedFace = Typeface::resolveDefault(src);
+ Typeface* result = new Typeface;
if (result != 0) {
result->fFontCollection = resolvedFace->fFontCollection;
result->fFontCollection->Ref();
@@ -120,9 +115,9 @@ TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Sty
return result;
}
-TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) {
- TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(src);
- TypefaceImpl* result = new TypefaceImpl;
+Typeface* Typeface::createWeightAlias(Typeface* src, int weight) {
+ Typeface* resolvedFace = Typeface::resolveDefault(src);
+ Typeface* result = new Typeface;
if (result != 0) {
result->fFontCollection = resolvedFace->fFontCollection;
result->fFontCollection->Ref();
@@ -133,15 +128,10 @@ TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int weight) {
return result;
}
-TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
- std::vector<FontFamily *>familyVec;
- for (size_t i = 0; i < size; i++) {
- FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
- familyVec.push_back(family);
- }
- TypefaceImpl* result = new TypefaceImpl;
- result->fFontCollection = new FontCollection(familyVec);
- if (size == 0) {
+Typeface* Typeface::createFromFamilies(const std::vector<FontFamily*>& families) {
+ Typeface* result = new Typeface;
+ result->fFontCollection = new FontCollection(families);
+ if (families.empty()) {
ALOGW("createFromFamilies creating empty collection");
result->fSkiaStyle = SkTypeface::kNormal;
} else {
@@ -162,18 +152,12 @@ TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size
return result;
}
-void TypefaceImpl_unref(TypefaceImpl* face) {
- if (face != NULL) {
- face->fFontCollection->Unref();
- }
- delete face;
-}
-
-int TypefaceImpl_getStyle(TypefaceImpl* face) {
- return face->fSkiaStyle;
+void Typeface::unref() {
+ fFontCollection->Unref();
+ delete this;
}
-void TypefaceImpl_setDefault(TypefaceImpl* face) {
+void Typeface::setDefault(Typeface* face) {
gDefaultTypeface = face;
}
diff --git a/core/jni/android/graphics/TypefaceImpl.h b/libs/hwui/hwui/Typeface.h
index 4b14917eaaf2..8862e5a5a911 100644
--- a/core/jni/android/graphics/TypefaceImpl.h
+++ b/libs/hwui/hwui/Typeface.h
@@ -18,15 +18,15 @@
#ifndef _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
#define _ANDROID_GRAPHICS_TYPEFACE_IMPL_H_
-#include "jni.h" // for jlong, eventually remove
#include "SkTypeface.h"
-#include <androidfw/AssetManager.h>
+#include <cutils/compiler.h>
#include <minikin/FontCollection.h>
+#include <vector>
namespace android {
-struct TypefaceImpl {
+struct ANDROID_API Typeface {
FontCollection *fFontCollection;
// style used for constructing and querying Typeface objects
@@ -36,29 +36,19 @@ struct TypefaceImpl {
// resolved style actually used for rendering
FontStyle fStyle;
-};
-
-// Note: it would be cleaner if the following functions were member
-// functions (static or otherwise) of the TypefaceImpl class. However,
-// that can't be easily accommodated in the case where TypefaceImpl
-// is just a pointer to SkTypeface, in the non-USE_MINIKIN case.
-// TODO: when #ifdef USE_MINIKIN is removed, move to member functions.
-TypefaceImpl* TypefaceImpl_resolveDefault(TypefaceImpl* src);
+ void unref();
-TypefaceImpl* TypefaceImpl_createFromTypeface(TypefaceImpl* src, SkTypeface::Style style);
+ static Typeface* resolveDefault(Typeface* src);
-TypefaceImpl* TypefaceImpl_createWeightAlias(TypefaceImpl* src, int baseweight);
+ static Typeface* createFromTypeface(Typeface* src, SkTypeface::Style style);
-// When we remove the USE_MINIKIN ifdef, probably a good idea to move the casting
-// (from jlong to FontFamily*) to the caller in Typeface.cpp.
-TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size);
+ static Typeface* createWeightAlias(Typeface* src, int baseweight);
-void TypefaceImpl_unref(TypefaceImpl* face);
+ static Typeface* createFromFamilies(const std::vector<FontFamily*>& families);
-int TypefaceImpl_getStyle(TypefaceImpl* face);
-
-void TypefaceImpl_setDefault(TypefaceImpl* face);
+ static void setDefault(Typeface* face);
+};
}
diff --git a/libs/hwui/hwui_static_deps.mk b/libs/hwui/hwui_static_deps.mk
index 7d4ef0f1f31e..299095217a8d 100644
--- a/libs/hwui/hwui_static_deps.mk
+++ b/libs/hwui/hwui_static_deps.mk
@@ -21,8 +21,11 @@ LOCAL_SHARED_LIBRARIES += \
libskia \
libui \
libgui \
- libprotobuf-cpp-lite
+ libprotobuf-cpp-lite \
+ libharfbuzz_ng \
+ libft2 \
+ libminikin
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
LOCAL_SHARED_LIBRARIES += libRS libRScpp
-endif \ No newline at end of file
+endif
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index c539d63daed3..eee527881a6a 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -19,7 +19,6 @@
#include "AnimationContext.h"
#include "Caches.h"
-#include "Canvas.h"
#include "DeferredLayerUpdater.h"
#include "EglManager.h"
#include "LayerUpdateQueue.h"
@@ -27,6 +26,7 @@
#include "OpenGLRenderer.h"
#include "Properties.h"
#include "RenderThread.h"
+#include "hwui/Canvas.h"
#include "renderstate/RenderState.h"
#include "renderstate/Stencil.h"
#include "protos/hwui.pb.h"
@@ -345,10 +345,10 @@ void CanvasContext::draw() {
mEglManager.damageFrame(frame, dirty);
#if HWUI_NEW_OPS
+ auto& caches = Caches::getInstance();
FrameBuilder frameBuilder(mLayerUpdateQueue, dirty, frame.width(), frame.height(),
- mRenderNodes, mLightGeometry, mContentDrawBounds, &Caches::getInstance());
+ mRenderNodes, mLightGeometry, mContentDrawBounds, caches);
mLayerUpdateQueue.clear();
- auto&& caches = Caches::getInstance();
BakedOpRenderer renderer(caches, mRenderThread.renderState(),
mOpaque, mLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
diff --git a/libs/hwui/tests/common/TestUtils.cpp b/libs/hwui/tests/common/TestUtils.cpp
index c809ff4f85e8..a4aee61a7b11 100644
--- a/libs/hwui/tests/common/TestUtils.cpp
+++ b/libs/hwui/tests/common/TestUtils.cpp
@@ -87,7 +87,7 @@ void TestUtils::layoutTextUnscaled(const SkPaint& paint, const char* text,
*outTotalAdvance = totalAdvance;
}
-void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
+void TestUtils::drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, float x, float y) {
// drawing text requires GlyphID TextEncoding (which JNI layer would have done)
LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
@@ -113,11 +113,11 @@ void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
// Force left alignment, since alignment offset is already baked in
SkPaint alignPaintCopy(paint);
alignPaintCopy.setTextAlign(SkPaint::kLeft_Align);
- canvas->drawText(glyphs.data(), positions.data(), glyphs.size(), alignPaintCopy, x, y,
+ canvas->drawGlyphs(glyphs.data(), positions.data(), glyphs.size(), alignPaintCopy, x, y,
bounds.left, bounds.top, bounds.right, bounds.bottom, totalAdvance);
}
-void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
+void TestUtils::drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, const SkPath& path) {
// drawing text requires GlyphID TextEncoding (which JNI layer would have done)
LOG_ALWAYS_FATAL_IF(paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding,
@@ -130,7 +130,7 @@ void TestUtils::drawTextToCanvas(TestCanvas* canvas, const char* text,
SkUnichar unichar = SkUTF8_NextUnichar(&text);
glyphs.push_back(autoCache.getCache()->unicharToGlyph(unichar));
}
- canvas->drawTextOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint);
+ canvas->drawGlyphsOnPath(glyphs.data(), glyphs.size(), path, 0, 0, paint);
}
void TestUtils::TestTask::run() {
@@ -143,5 +143,13 @@ void TestUtils::TestTask::run() {
renderState.onGLContextDestroyed();
}
+std::unique_ptr<uint16_t[]> TestUtils::utf8ToUtf16(const char* str) {
+ const size_t strLen = strlen(str);
+ const ssize_t utf16Len = utf8_to_utf16_length((uint8_t*) str, strLen);
+ std::unique_ptr<uint16_t[]> dst(new uint16_t[utf16Len + 1]);
+ utf8_to_utf16((uint8_t*) str, strLen, (char16_t*) dst.get());
+ return dst;
+}
+
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index 28ac1166fc5c..a5e7a5fb808c 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -207,12 +207,14 @@ public:
std::vector<glyph_t>* outGlyphs, std::vector<float>* outPositions,
float* outTotalAdvance, Rect* outBounds);
- static void drawTextToCanvas(TestCanvas* canvas, const char* text,
+ static void drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, float x, float y);
- static void drawTextToCanvas(TestCanvas* canvas, const char* text,
+ static void drawUtf8ToCanvas(TestCanvas* canvas, const char* text,
const SkPaint& paint, const SkPath& path);
+ static std::unique_ptr<uint16_t[]> utf8ToUtf16(const char* str);
+
private:
static void syncHierarchyPropertiesAndDisplayListImpl(RenderNode* node) {
node->syncProperties();
diff --git a/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
new file mode 100644
index 000000000000..52039efc6d71
--- /dev/null
+++ b/libs/hwui/tests/common/scenes/GlyphStressAnimation.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TestSceneBase.h"
+#include "utils/Color.h"
+
+#include <minikin/Layout.h>
+#include <hwui/Paint.h>
+
+#include <cstdio>
+
+class GlyphStressAnimation;
+
+static TestScene::Registrar _GlyphStress(TestScene::Info{
+ "glyphstress",
+ "A stress test for both the glyph cache, and glyph rendering.",
+ TestScene::simpleCreateScene<GlyphStressAnimation>
+});
+
+class GlyphStressAnimation : public TestScene {
+public:
+ sp<RenderNode> container;
+ void createContent(int width, int height, TestCanvas& canvas) override {
+ container = TestUtils::createNode(0, 0, width, height, nullptr);
+ doFrame(0); // update container
+
+ canvas.drawColor(Color::White, SkXfermode::kSrcOver_Mode);
+ canvas.drawRenderNode(container.get());
+ }
+
+ void doFrame(int frameNr) override {
+ std::unique_ptr<uint16_t[]> text = TestUtils::utf8ToUtf16(
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ ssize_t textLength = 26 * 2;
+
+ TestCanvas canvas(
+ container->stagingProperties().getWidth(),
+ container->stagingProperties().getHeight());
+ Paint paint;
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setAntiAlias(true);
+ paint.setColor(Color::Black);
+ for (int i = 0; i < 5; i++) {
+ paint.setTextSize(10 + (frameNr % 20) + i * 20);
+ canvas.drawText(text.get(), 0, textLength, textLength,
+ 0, 100 * (i + 2), kBidi_Force_LTR, paint, nullptr);
+ }
+
+ container->setStagingDisplayList(canvas.finishRecording());
+ }
+};
diff --git a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
index 43e247e68bc0..ab368c059de0 100644
--- a/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/ListViewAnimation.cpp
@@ -136,9 +136,9 @@ private:
textPaint.setAntiAlias(true);
char buf[256];
snprintf(buf, sizeof(buf), "This card is #%d", cardId);
- TestUtils::drawTextToCanvas(&canvas, buf, textPaint, cardHeight, dp(25));
+ TestUtils::drawUtf8ToCanvas(&canvas, buf, textPaint, cardHeight, dp(25));
textPaint.setTextSize(dp(15));
- TestUtils::drawTextToCanvas(&canvas, "This is some more text on the card", textPaint,
+ TestUtils::drawUtf8ToCanvas(&canvas, "This is some more text on the card", textPaint,
cardHeight, dp(45));
canvas.drawBitmap(createRandomCharIcon(), dp(10), dp(10), nullptr);
diff --git a/libs/hwui/tests/common/scenes/TextAnimation.cpp b/libs/hwui/tests/common/scenes/TextAnimation.cpp
index 1823db2940aa..be8f48b9fd17 100644
--- a/libs/hwui/tests/common/scenes/TextAnimation.cpp
+++ b/libs/hwui/tests/common/scenes/TextAnimation.cpp
@@ -39,14 +39,14 @@ public:
paint.setColor(Color::Black);
for (int i = 0; i < 10; i++) {
- TestUtils::drawTextToCanvas(&canvas, "Test string", paint, 400, i * 100);
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string", paint, 400, i * 100);
}
SkPath path;
path.addOval(SkRect::MakeLTRB(100, 100, 300, 300));
paint.setColor(Color::Blue_500);
- TestUtils::drawTextToCanvas(&canvas, "This is a neat circle of text!", paint, path);
+ TestUtils::drawUtf8ToCanvas(&canvas, "This is a neat circle of text!", paint, path);
});
canvas.drawRenderNode(card.get());
}
diff --git a/libs/hwui/tests/microbench/FrameBuilderBench.cpp b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
index 7816f0fbf864..9daf6334b507 100644
--- a/libs/hwui/tests/microbench/FrameBuilderBench.cpp
+++ b/libs/hwui/tests/microbench/FrameBuilderBench.cpp
@@ -65,7 +65,7 @@ void BM_FrameBuilder_defer(benchmark::State& state) {
auto nodes = createTestNodeList();
while (state.KeepRunning()) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- nodes, sLightGeometry, nullptr);
+ nodes, sLightGeometry, Caches::getInstance());
benchmark::DoNotOptimize(&frameBuilder);
}
}
@@ -80,7 +80,7 @@ void BM_FrameBuilder_deferAndRender(benchmark::State& state) {
while (state.KeepRunning()) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- nodes, sLightGeometry, nullptr);
+ nodes, sLightGeometry, Caches::getInstance());
BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
@@ -119,7 +119,7 @@ void BM_FrameBuilder_defer_scene(benchmark::State& state) {
while (state.KeepRunning()) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
- nodes, sLightGeometry, nullptr);
+ nodes, sLightGeometry, Caches::getInstance());
benchmark::DoNotOptimize(&frameBuilder);
}
}
@@ -137,7 +137,7 @@ void BM_FrameBuilder_deferAndRender_scene(benchmark::State& state) {
while (state.KeepRunning()) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeWH(gDisplay.w, gDisplay.h), gDisplay.w, gDisplay.h,
- nodes, sLightGeometry, nullptr);
+ nodes, sLightGeometry, Caches::getInstance());
BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
diff --git a/libs/hwui/tests/unit/CanvasStateTests.cpp b/libs/hwui/tests/unit/CanvasStateTests.cpp
index 68d74ee1e91d..0afabd83f5cc 100644
--- a/libs/hwui/tests/unit/CanvasStateTests.cpp
+++ b/libs/hwui/tests/unit/CanvasStateTests.cpp
@@ -16,9 +16,9 @@
#include "CanvasState.h"
-#include "Canvas.h"
#include "Matrix.h"
#include "Rect.h"
+#include "hwui/Canvas.h"
#include "utils/LinearAllocator.h"
#include <gtest/gtest.h>
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 31555f2f86ec..0aabfb1f1f34 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -107,7 +107,7 @@ public:
class FailRenderer : public TestRendererBase {};
-TEST(FrameBuilder, simple) {
+RENDERTHREAD_TEST(FrameBuilder, simple) {
class SimpleTestRenderer : public TestRendererBase {
public:
void startFrame(uint32_t width, uint32_t height, const Rect& repaintRect) override {
@@ -133,13 +133,13 @@ TEST(FrameBuilder, simple) {
canvas.drawBitmap(bitmap, 10, 10, nullptr);
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex()); // 2 ops + start + end
}
-TEST(FrameBuilder, simpleStroke) {
+RENDERTHREAD_TEST(FrameBuilder, simpleStroke) {
class SimpleStrokeTestRenderer : public TestRendererBase {
public:
void onPointsOp(const PointsOp& op, const BakedOpState& state) override {
@@ -159,13 +159,13 @@ TEST(FrameBuilder, simpleStroke) {
canvas.drawPoint(50, 50, strokedPaint);
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 200), 100, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SimpleStrokeTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex());
}
-TEST(FrameBuilder, simpleRejection) {
+RENDERTHREAD_TEST(FrameBuilder, simpleRejection) {
auto node = TestUtils::createNode(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
@@ -174,13 +174,13 @@ TEST(FrameBuilder, simpleRejection) {
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
FailRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
-TEST(FrameBuilder, simpleBatching) {
+RENDERTHREAD_TEST(FrameBuilder, simpleBatching) {
const int LOOPS = 5;
class SimpleBatchingTestRenderer : public TestRendererBase {
public:
@@ -209,14 +209,14 @@ TEST(FrameBuilder, simpleBatching) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SimpleBatchingTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2 * LOOPS, renderer.getIndex())
<< "Expect number of ops = 2 * loop count";
}
-TEST(FrameBuilder, clippedMerging) {
+RENDERTHREAD_TEST(FrameBuilder, clippedMerging) {
class ClippedMergingTestRenderer : public TestRendererBase {
public:
void onMergedBitmapOps(const MergedBakedOpList& opList) override {
@@ -250,13 +250,13 @@ TEST(FrameBuilder, clippedMerging) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
ClippedMergingTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
-TEST(FrameBuilder, textMerging) {
+RENDERTHREAD_TEST(FrameBuilder, textMerging) {
class TextMergingTestRenderer : public TestRendererBase {
public:
void onMergedTextOps(const MergedBakedOpList& opList) override {
@@ -274,17 +274,17 @@ TEST(FrameBuilder, textMerging) {
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setAntiAlias(true);
paint.setTextSize(50);
- TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
- TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 0); // will be top clipped
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100); // not clipped
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
TextMergingTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex()) << "Expect 2 ops";
}
-TEST(FrameBuilder, textStrikethrough) {
+RENDERTHREAD_TEST(FrameBuilder, textStrikethrough) {
const int LOOPS = 5;
class TextStrikethroughTestRenderer : public TestRendererBase {
public:
@@ -305,11 +305,11 @@ TEST(FrameBuilder, textStrikethrough) {
textPaint.setStrikeThruText(true);
textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
for (int i = 0; i < LOOPS; i++) {
- TestUtils::drawTextToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
+ TestUtils::drawUtf8ToCanvas(&canvas, "test text", textPaint, 10, 100 * (i + 1));
}
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 2000), 200, 2000,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
TextStrikethroughTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2 * LOOPS, renderer.getIndex())
@@ -319,7 +319,7 @@ TEST(FrameBuilder, textStrikethrough) {
static auto styles = {
SkPaint::kFill_Style, SkPaint::kStroke_Style, SkPaint::kStrokeAndFill_Style };
-TEST(FrameBuilder, textStyle) {
+RENDERTHREAD_TEST(FrameBuilder, textStyle) {
class TextStyleTestRenderer : public TestRendererBase {
public:
void onMergedTextOps(const MergedBakedOpList& opList) override {
@@ -361,11 +361,11 @@ TEST(FrameBuilder, textStyle) {
// They'll get merged, but with
for (auto style : styles) {
paint.setStyle(style);
- TestUtils::drawTextToCanvas(&canvas, "Test string1", paint, 100, 100);
+ TestUtils::drawUtf8ToCanvas(&canvas, "Test string1", paint, 100, 100);
}
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
TextStyleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(3, renderer.getIndex()) << "Expect 3 ops";
@@ -398,13 +398,13 @@ RENDERTHREAD_TEST(FrameBuilder, textureLayer) {
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
TextureLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex());
}
-TEST(FrameBuilder, functor_reject) {
+RENDERTHREAD_TEST(FrameBuilder, functor_reject) {
class FunctorTestRenderer : public TestRendererBase {
public:
void onFunctorOp(const FunctorOp& op, const BakedOpState& state) override {
@@ -421,13 +421,14 @@ TEST(FrameBuilder, functor_reject) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(scrolledFunctorView), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(scrolledFunctorView),
+ sLightGeometry, Caches::getInstance());
FunctorTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex()) << "Functor should not be rejected";
}
-TEST(FrameBuilder, renderNode) {
+RENDERTHREAD_TEST(FrameBuilder, renderNode) {
class RenderNodeTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
@@ -466,13 +467,13 @@ TEST(FrameBuilder, renderNode) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance());
RenderNodeTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex());
}
-TEST(FrameBuilder, clipped) {
+RENDERTHREAD_TEST(FrameBuilder, clipped) {
class ClippedTestRenderer : public TestRendererBase {
public:
void onBitmapOp(const BitmapOp& op, const BakedOpState& state) override {
@@ -491,12 +492,12 @@ TEST(FrameBuilder, clipped) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue,
SkRect::MakeLTRB(10, 20, 30, 40), // clip to small area, should see in receiver
- 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ 200, 200, TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
ClippedTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
-TEST(FrameBuilder, saveLayer_simple) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayer_simple) {
class SaveLayerSimpleTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) override {
@@ -533,13 +534,13 @@ TEST(FrameBuilder, saveLayer_simple) {
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
-TEST(FrameBuilder, saveLayer_nested) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayer_nested) {
/* saveLayer1 { rect1, saveLayer2 { rect2 } } will play back as:
* - startTemporaryLayer2, rect2 endLayer2
* - startTemporaryLayer1, rect1, drawLayer2, endLayer1
@@ -605,13 +606,13 @@ TEST(FrameBuilder, saveLayer_nested) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(800, 800), 800, 800,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerNestedTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex());
}
-TEST(FrameBuilder, saveLayer_contentRejection) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayer_contentRejection) {
auto node = TestUtils::createNode(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
canvas.save(SaveFlags::MatrixClip);
@@ -625,14 +626,14 @@ TEST(FrameBuilder, saveLayer_contentRejection) {
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
FailRenderer renderer;
// should see no ops, even within the layer, since the layer should be rejected
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
-TEST(FrameBuilder, saveLayerUnclipped_simple) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_simple) {
class SaveLayerUnclippedSimpleTestRenderer : public TestRendererBase {
public:
void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
@@ -668,13 +669,13 @@ TEST(FrameBuilder, saveLayerUnclipped_simple) {
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerUnclippedSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
-TEST(FrameBuilder, saveLayerUnclipped_mergedClears) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_mergedClears) {
class SaveLayerUnclippedMergedClearsTestRenderer : public TestRendererBase {
public:
void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
@@ -722,14 +723,14 @@ TEST(FrameBuilder, saveLayerUnclipped_mergedClears) {
canvas.restoreToCount(restoreTo);
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerUnclippedMergedClearsTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex())
<< "Expect 4 copyTos, 4 copyFroms, 1 clear SimpleRects, and 1 rect.";
}
-TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
class SaveLayerUnclippedClearClipTestRenderer : public TestRendererBase {
public:
void onCopyToLayerOp(const CopyToLayerOp& op, const BakedOpState& state) override {
@@ -763,13 +764,13 @@ TEST(FrameBuilder, saveLayerUnclipped_clearClip) {
// draw with partial screen dirty, and assert we see that rect later
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeLTRB(50, 50, 150, 150), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerUnclippedClearClipTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
}
-TEST(FrameBuilder, saveLayerUnclipped_reject) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_reject) {
auto node = TestUtils::createNode(0, 0, 200, 200,
[](RenderProperties& props, RecordingCanvas& canvas) {
// unclipped savelayer + rect both in area that won't intersect with dirty
@@ -780,7 +781,7 @@ TEST(FrameBuilder, saveLayerUnclipped_reject) {
// draw with partial screen dirty that doesn't intersect with savelayer
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
FailRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
}
@@ -789,7 +790,7 @@ TEST(FrameBuilder, saveLayerUnclipped_reject) {
* - startTemporaryLayer, onCopyToLayer, onSimpleRects, onRect, onCopyFromLayer, endLayer
* - startFrame, onCopyToLayer, onSimpleRects, drawLayer, onCopyFromLayer, endframe
*/
-TEST(FrameBuilder, saveLayerUnclipped_complex) {
+RENDERTHREAD_TEST(FrameBuilder, saveLayerUnclipped_complex) {
class SaveLayerUnclippedComplexTestRenderer : public TestRendererBase {
public:
OffscreenBuffer* startTemporaryLayer(uint32_t width, uint32_t height) {
@@ -840,7 +841,7 @@ TEST(FrameBuilder, saveLayerUnclipped_complex) {
canvas.restore();
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(600, 600), 600, 600,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
SaveLayerUnclippedComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(12, renderer.getIndex());
@@ -898,7 +899,7 @@ RENDERTHREAD_TEST(FrameBuilder, hwLayer_simple) {
layerUpdateQueue.enqueueLayerWithDamage(node.get(), Rect(25, 25, 75, 75));
FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- syncedNodeList, sLightGeometry, nullptr);
+ syncedNodeList, sLightGeometry, Caches::getInstance());
HwLayerSimpleTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(6, renderer.getIndex());
@@ -999,7 +1000,7 @@ RENDERTHREAD_TEST(FrameBuilder, hwLayer_complex) {
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(200, 200));
FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- syncedList, sLightGeometry, nullptr);
+ syncedList, sLightGeometry, Caches::getInstance());
HwLayerComplexTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(13, renderer.getIndex());
@@ -1023,7 +1024,7 @@ static void drawOrderedNode(RecordingCanvas* canvas, uint8_t expectedDrawOrder,
node->setPropertyFieldsDirty(RenderNode::TRANSLATION_Z);
canvas->drawRenderNode(node.get()); // canvas takes reference/sole ownership
}
-TEST(FrameBuilder, zReorder) {
+RENDERTHREAD_TEST(FrameBuilder, zReorder) {
class ZReorderTestRenderer : public TestRendererBase {
public:
void onRectOp(const RectOp& op, const BakedOpState& state) override {
@@ -1048,13 +1049,13 @@ TEST(FrameBuilder, zReorder) {
drawOrderedNode(&canvas, 9, -10.0f); // in reorder=false at this point, so played inorder
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
- TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance());
ZReorderTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(10, renderer.getIndex());
};
-TEST(FrameBuilder, projectionReorder) {
+RENDERTHREAD_TEST(FrameBuilder, projectionReorder) {
static const int scrollX = 5;
static const int scrollY = 10;
class ProjectionReorderTestRenderer : public TestRendererBase {
@@ -1139,7 +1140,7 @@ TEST(FrameBuilder, projectionReorder) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 100, 100,
- TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance());
ProjectionReorderTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(3, renderer.getIndex());
@@ -1222,7 +1223,7 @@ RENDERTHREAD_TEST(FrameBuilder, projectionHwLayer) {
LayerUpdateQueue layerUpdateQueue; // Note: enqueue damage post-sync, so bounds are valid
layerUpdateQueue.enqueueLayerWithDamage(child.get(), Rect(200, 200));
FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
- syncedList, sLightGeometry, nullptr);
+ syncedList, sLightGeometry, Caches::getInstance());
ProjectionHwLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(6, renderer.getIndex());
@@ -1278,7 +1279,7 @@ RENDERTHREAD_TEST(FrameBuilder, projectionChildScroll) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(400, 400), 400, 400,
- TestUtils::createSyncedNodeList(parent), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance());
ProjectionChildScrollTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex());
@@ -1321,7 +1322,7 @@ RENDERTHREAD_TEST(FrameBuilder, shadow) {
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(parent), sLightGeometry, &Caches::getInstance());
+ TestUtils::createSyncedNodeList(parent), sLightGeometry, Caches::getInstance());
ShadowTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(2, renderer.getIndex());
@@ -1363,8 +1364,7 @@ RENDERTHREAD_TEST(FrameBuilder, shadowSaveLayer) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
TestUtils::createSyncedNodeList(parent),
- (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50},
- &Caches::getInstance());
+ (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
ShadowSaveLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(5, renderer.getIndex());
@@ -1416,8 +1416,7 @@ RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) {
layerUpdateQueue.enqueueLayerWithDamage(parent.get(), Rect(100, 100));
FrameBuilder frameBuilder(layerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
syncedList,
- (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30},
- &Caches::getInstance());
+ (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 30}, Caches::getInstance());
ShadowHwLayerTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(5, renderer.getIndex());
@@ -1426,7 +1425,7 @@ RENDERTHREAD_TEST(FrameBuilder, shadowHwLayer) {
*layerHandle = nullptr;
}
-TEST(FrameBuilder, shadowLayering) {
+RENDERTHREAD_TEST(FrameBuilder, shadowLayering) {
class ShadowLayeringTestRenderer : public TestRendererBase {
public:
void onShadowOp(const ShadowOp& op, const BakedOpState& state) override {
@@ -1447,8 +1446,7 @@ TEST(FrameBuilder, shadowLayering) {
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
TestUtils::createSyncedNodeList(parent),
- (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50},
- &Caches::getInstance());
+ (FrameBuilder::LightGeometry) {{ 100, 100, 100 }, 50}, Caches::getInstance());
ShadowLayeringTestRenderer renderer;
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(4, renderer.getIndex());
@@ -1476,13 +1474,13 @@ static void testProperty(std::function<void(RenderProperties&)> propSetupCallbac
});
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(100, 100), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometry, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometry, Caches::getInstance());
PropertyTestRenderer renderer(opValidateCallback);
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
EXPECT_EQ(1, renderer.getIndex()) << "Should have seen one op";
}
-TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) {
testProperty([](RenderProperties& properties) {
properties.setAlpha(0.5f);
properties.setHasOverlappingRendering(false);
@@ -1491,7 +1489,7 @@ TEST(FrameBuilder, renderPropOverlappingRenderingAlpha) {
});
}
-TEST(FrameBuilder, renderPropClipping) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropClipping) {
testProperty([](RenderProperties& properties) {
properties.setClipToBounds(true);
properties.setClipBounds(Rect(10, 20, 300, 400));
@@ -1501,7 +1499,7 @@ TEST(FrameBuilder, renderPropClipping) {
});
}
-TEST(FrameBuilder, renderPropRevealClip) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropRevealClip) {
testProperty([](RenderProperties& properties) {
properties.mutableRevealClip().set(true, 50, 50, 25);
}, [](const RectOp& op, const BakedOpState& state) {
@@ -1512,7 +1510,7 @@ TEST(FrameBuilder, renderPropRevealClip) {
});
}
-TEST(FrameBuilder, renderPropOutlineClip) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropOutlineClip) {
testProperty([](RenderProperties& properties) {
properties.mutableOutline().setShouldClip(true);
properties.mutableOutline().setRoundRect(10, 20, 30, 40, 5.0f, 0.5f);
@@ -1524,7 +1522,7 @@ TEST(FrameBuilder, renderPropOutlineClip) {
});
}
-TEST(FrameBuilder, renderPropTransform) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropTransform) {
testProperty([](RenderProperties& properties) {
properties.setLeftTopRightBottom(10, 10, 110, 110);
@@ -1618,7 +1616,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
auto nodes = TestUtils::createSyncedNodeList(node); // sync before querying height
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- nodes, sLightGeometry, nullptr);
+ nodes, sLightGeometry, Caches::getInstance());
SaveLayerAlphaClipTestRenderer renderer(outObservedData);
frameBuilder.replayBakedOps<TestDispatcher>(renderer);
@@ -1626,7 +1624,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
ASSERT_EQ(4, renderer.getIndex()) << "Test must trigger saveLayer alpha behavior.";
}
-TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
SaveLayerAlphaData observedData;
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
properties.setTranslationX(10); // offset rendering content
@@ -1642,7 +1640,7 @@ TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
<< "expect content to be translated as part of being clipped";
}
-TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
SaveLayerAlphaData observedData;
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
// Translate and rotate the view so that the only visible part is the top left corner of
@@ -1661,7 +1659,7 @@ TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {
EXPECT_MATRIX_APPROX_EQ(Matrix4::identity(), observedData.rectMatrix);
}
-TEST(FrameBuilder, renderPropSaveLayerAlphaScale) {
+RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaScale) {
SaveLayerAlphaData observedData;
testSaveLayerAlphaClip(&observedData, [](RenderProperties& properties) {
properties.setPivotX(0);
diff --git a/libs/hwui/tests/unit/LeakCheckTests.cpp b/libs/hwui/tests/unit/LeakCheckTests.cpp
index da786c7d9d46..9161f90b54aa 100644
--- a/libs/hwui/tests/unit/LeakCheckTests.cpp
+++ b/libs/hwui/tests/unit/LeakCheckTests.cpp
@@ -41,7 +41,7 @@ RENDERTHREAD_TEST(LeakCheck, saveLayerUnclipped_simple) {
Caches& caches = Caches::getInstance();
FrameBuilder frameBuilder(sEmptyLayerUpdateQueue, SkRect::MakeWH(200, 200), 200, 200,
- TestUtils::createSyncedNodeList(node), sLightGeometery, nullptr);
+ TestUtils::createSyncedNodeList(node), sLightGeometery, Caches::getInstance());
BakedOpRenderer renderer(caches, renderState, true, sLightInfo);
frameBuilder.replayBakedOps<BakedOpDispatcher>(renderer);
}
diff --git a/libs/hwui/tests/unit/RecordingCanvasTests.cpp b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
index e6d84c6681f1..6ab5110aaa9a 100644
--- a/libs/hwui/tests/unit/RecordingCanvasTests.cpp
+++ b/libs/hwui/tests/unit/RecordingCanvasTests.cpp
@@ -18,6 +18,8 @@
#include <RecordedOp.h>
#include <RecordingCanvas.h>
+#include <hwui/Paint.h>
+#include <minikin/Layout.h>
#include <tests/common/TestUtils.h>
#include <utils/Color.h>
@@ -131,13 +133,13 @@ TEST(RecordingCanvas, drawRoundRect) {
<< "Non-rounded rects should be converted";
}
-TEST(RecordingCanvas, drawText) {
+TEST(RecordingCanvas, drawGlyphs) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25);
+ TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
});
int count = 0;
@@ -152,7 +154,7 @@ TEST(RecordingCanvas, drawText) {
ASSERT_EQ(1, count);
}
-TEST(RecordingCanvas, drawText_strikeThruAndUnderline) {
+TEST(RecordingCanvas, drawGlyphs_strikeThruAndUnderline) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
SkPaint paint;
paint.setAntiAlias(true);
@@ -162,7 +164,7 @@ TEST(RecordingCanvas, drawText_strikeThruAndUnderline) {
for (int j = 0; j < 2; j++) {
paint.setUnderlineText(i != 0);
paint.setStrikeThruText(j != 0);
- TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25);
+ TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
}
}
});
@@ -184,18 +186,18 @@ TEST(RecordingCanvas, drawText_strikeThruAndUnderline) {
EXPECT_EQ(RecordedOpId::RectOp, ops[index++]->opId); // strikethrough
}
-TEST(RecordingCanvas, drawText_forceAlignLeft) {
+TEST(RecordingCanvas, drawGlyphs_forceAlignLeft) {
auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
SkPaint paint;
paint.setAntiAlias(true);
paint.setTextSize(20);
paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
paint.setTextAlign(SkPaint::kLeft_Align);
- TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25);
+ TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
paint.setTextAlign(SkPaint::kCenter_Align);
- TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25);
+ TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
paint.setTextAlign(SkPaint::kRight_Align);
- TestUtils::drawTextToCanvas(&canvas, "test text", paint, 25, 25);
+ TestUtils::drawUtf8ToCanvas(&canvas, "test text", paint, 25, 25);
});
int count = 0;
@@ -576,7 +578,7 @@ TEST(RecordingCanvas, refPaint) {
canvas.drawRect(0, 0, 200, 10, paint);
SkPaint paintCopy(paint);
canvas.drawRect(0, 10, 200, 20, paintCopy);
- TestUtils::drawTextToCanvas(&canvas, "helloworld", paint, 50, 25);
+ TestUtils::drawUtf8ToCanvas(&canvas, "helloworld", paint, 50, 25);
// only here do we use different paint ptr
paint.setColor(SK_ColorRED);
@@ -597,5 +599,54 @@ TEST(RecordingCanvas, refPaint) {
EXPECT_NE(&paint, ops[3]->paint);
}
+TEST(RecordingCanvas, drawText) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ Paint paint;
+ paint.setAntiAlias(true);
+ paint.setTextSize(20);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ std::unique_ptr<uint16_t[]> dst = TestUtils::utf8ToUtf16("HELLO");
+ canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
+ });
+
+ int count = 0;
+ playbackOps(*dl, [&count](const RecordedOp& op) {
+ count++;
+ ASSERT_EQ(RecordedOpId::TextOp, op.opId);
+ EXPECT_EQ(nullptr, op.localClip);
+ EXPECT_TRUE(op.localMatrix.isIdentity());
+ EXPECT_TRUE(op.unmappedBounds.getHeight() >= 10);
+ EXPECT_TRUE(op.unmappedBounds.getWidth() >= 25);
+ });
+ ASSERT_EQ(1, count);
+}
+
+TEST(RecordingCanvas, drawTextInHighContrast) {
+ auto dl = TestUtils::createDisplayList<RecordingCanvas>(200, 200, [](RecordingCanvas& canvas) {
+ canvas.setHighContrastText(true);
+ Paint paint;
+ paint.setColor(SK_ColorWHITE);
+ paint.setAntiAlias(true);
+ paint.setTextSize(20);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ std::unique_ptr<uint16_t[]> dst = TestUtils::utf8ToUtf16("HELLO");
+ canvas.drawText(dst.get(), 0, 5, 5, 25, 25, kBidi_Force_LTR, paint, NULL);
+ });
+
+ int count = 0;
+ playbackOps(*dl, [&count](const RecordedOp& op) {
+ ASSERT_EQ(RecordedOpId::TextOp, op.opId);
+ if (count++ == 0) {
+ EXPECT_EQ(SK_ColorBLACK, op.paint->getColor());
+ EXPECT_EQ(SkPaint::kStrokeAndFill_Style, op.paint->getStyle());
+ } else {
+ EXPECT_EQ(SK_ColorWHITE, op.paint->getColor());
+ EXPECT_EQ(SkPaint::kFill_Style, op.paint->getStyle());
+ }
+
+ });
+ ASSERT_EQ(2, count);
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/location/java/android/location/GnssClock.java b/location/java/android/location/GnssClock.java
index 2af479066c7b..df42a7328a99 100644
--- a/location/java/android/location/GnssClock.java
+++ b/location/java/android/location/GnssClock.java
@@ -471,6 +471,11 @@ public final class GnssClock implements Parcelable {
"DriftUncertaintyNanosPerSecond",
hasDriftUncertaintyNanosPerSecond() ? mDriftUncertaintyNanosPerSecond : null));
+ builder.append(String.format(
+ format,
+ "HardwareClockDiscontinuityCount",
+ mHardwareClockDiscontinuityCount));
+
return builder.toString();
}
diff --git a/media/java/android/media/ExifInterface.java b/media/java/android/media/ExifInterface.java
index ed358d3d270a..4bf08527b594 100644
--- a/media/java/android/media/ExifInterface.java
+++ b/media/java/android/media/ExifInterface.java
@@ -651,6 +651,7 @@ public class ExifInterface {
private final String mFilename;
private final FileDescriptor mSeekableFileDescriptor;
private final AssetManager.AssetInputStream mAssetInputStream;
+ private final boolean mIsInputStream;
private boolean mIsRaw;
private final HashMap[] mAttributes = new HashMap[EXIF_TAGS.length];
private boolean mHasThumbnail;
@@ -669,20 +670,26 @@ public class ExifInterface {
if (filename == null) {
throw new IllegalArgumentException("filename cannot be null");
}
- FileInputStream in = new FileInputStream(filename);
+ FileInputStream in = null;
mAssetInputStream = null;
mFilename = filename;
- if (isSeekableFD(in.getFD())) {
- mSeekableFileDescriptor = in.getFD();
- } else {
- mSeekableFileDescriptor = null;
+ mIsInputStream = false;
+ try {
+ in = new FileInputStream(filename);
+ if (isSeekableFD(in.getFD())) {
+ mSeekableFileDescriptor = in.getFD();
+ } else {
+ mSeekableFileDescriptor = null;
+ }
+ loadAttributes(in);
+ } finally {
+ IoUtils.closeQuietly(in);
}
- loadAttributes(in);
}
/**
* Reads Exif tags from the specified image file descriptor. Attribute mutation is supported
- * for seekable file descriptors only.
+ * for writable and seekable file descriptors only.
*/
public ExifInterface(FileDescriptor fileDescriptor) throws IOException {
if (fileDescriptor == null) {
@@ -692,10 +699,25 @@ public class ExifInterface {
mFilename = null;
if (isSeekableFD(fileDescriptor)) {
mSeekableFileDescriptor = fileDescriptor;
+ // Keep the original file descriptor in order to save attributes when it's seekable.
+ // Otherwise, just close the given file descriptor after reading it because the save
+ // feature won't be working.
+ try {
+ fileDescriptor = Os.dup(fileDescriptor);
+ } catch (ErrnoException e) {
+ e.rethrowAsIOException();
+ }
} else {
mSeekableFileDescriptor = null;
}
- loadAttributes(new FileInputStream(fileDescriptor));
+ mIsInputStream = false;
+ FileInputStream in = null;
+ try {
+ in = new FileInputStream(fileDescriptor);
+ loadAttributes(in);
+ } finally {
+ IoUtils.closeQuietly(in);
+ }
}
/**
@@ -718,6 +740,7 @@ public class ExifInterface {
mAssetInputStream = null;
mSeekableFileDescriptor = null;
}
+ mIsInputStream = true;
loadAttributes(inputStream);
}
@@ -800,41 +823,43 @@ public class ExifInterface {
* determine whether the image data format is JPEG or not.
*/
private void loadAttributes(@NonNull InputStream in) throws IOException {
- // Initialize mAttributes.
- for (int i = 0; i < EXIF_TAGS.length; ++i) {
- mAttributes[i] = new HashMap();
- }
-
- // Process RAW input stream
- if (mAssetInputStream != null) {
- long asset = mAssetInputStream.getNativeAsset();
- if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) {
- return;
- }
- } else if (mSeekableFileDescriptor != null) {
- if (handleRawResult(nativeGetRawAttributesFromFileDescriptor(
- mSeekableFileDescriptor))) {
- return;
+ try {
+ // Initialize mAttributes.
+ for (int i = 0; i < EXIF_TAGS.length; ++i) {
+ mAttributes[i] = new HashMap();
}
- } else {
- in = new BufferedInputStream(in, JPEG_SIGNATURE_SIZE);
- if (!isJpegInputStream((BufferedInputStream) in) && handleRawResult(
- nativeGetRawAttributesFromInputStream(in))) {
- return;
+
+ // Process RAW input stream
+ if (mAssetInputStream != null) {
+ long asset = mAssetInputStream.getNativeAsset();
+ if (handleRawResult(nativeGetRawAttributesFromAsset(asset))) {
+ return;
+ }
+ } else if (mSeekableFileDescriptor != null) {
+ if (handleRawResult(nativeGetRawAttributesFromFileDescriptor(
+ mSeekableFileDescriptor))) {
+ return;
+ }
+ } else {
+ in = new BufferedInputStream(in, JPEG_SIGNATURE_SIZE);
+ if (!isJpegInputStream((BufferedInputStream) in) && handleRawResult(
+ nativeGetRawAttributesFromInputStream(in))) {
+ return;
+ }
}
- }
- // Process JPEG input stream
- try {
+ // Process JPEG input stream
getJpegAttributes(in);
} catch (IOException e) {
// Ignore exceptions in order to keep the compatibility with the old versions of
// ExifInterface.
- Log.w(TAG, "Invalid JPEG", e);
- }
-
- if (DEBUG) {
- printAttributes();
+ Log.w(TAG, "Invalid JPEG: ExifInterface got an unsupported image format file"
+ + "(ExifInterface supports JPEG and some RAW image formats only) "
+ + "or a corrupted JPEG file to ExifInterface.", e);
+ } finally {
+ if (DEBUG) {
+ printAttributes();
+ }
}
}
@@ -878,10 +903,6 @@ public class ExifInterface {
break;
}
}
-
- if (DEBUG) {
- printAttributes();
- }
return true;
}
@@ -915,7 +936,7 @@ public class ExifInterface {
throw new UnsupportedOperationException(
"ExifInterface does not support saving attributes on RAW formats.");
}
- if (mSeekableFileDescriptor == null && mFilename == null) {
+ if (mIsInputStream || (mSeekableFileDescriptor == null && mFilename == null)) {
throw new UnsupportedOperationException(
"ExifInterface does not support saving attributes for the current input.");
}
@@ -1001,8 +1022,9 @@ public class ExifInterface {
} else if (mFilename != null) {
in = new FileInputStream(mFilename);
} else if (mSeekableFileDescriptor != null) {
- Os.lseek(mSeekableFileDescriptor, 0, OsConstants.SEEK_SET);
- in = new FileInputStream(mSeekableFileDescriptor);
+ FileDescriptor fileDescriptor = Os.dup(mSeekableFileDescriptor);
+ Os.lseek(fileDescriptor, 0, OsConstants.SEEK_SET);
+ in = new FileInputStream(fileDescriptor);
}
if (in == null) {
// Should not be reached this.
@@ -1207,7 +1229,8 @@ public class ExifInterface {
int length = dataInputStream.readUnsignedShort() - 2;
bytesRead += 2;
if (DEBUG) {
- Log.d(TAG, "JPEG segment: " + marker + " (length: " + (length + 2) + ")");
+ Log.d(TAG, "JPEG segment: " + Integer.toHexString(marker & 0xff) + " (length: "
+ + (length + 2) + ")");
}
if (length < 0) {
throw new IOException("Invalid length");
@@ -1270,7 +1293,9 @@ public class ExifInterface {
case MARKER_SOF13:
case MARKER_SOF14:
case MARKER_SOF15: {
- dataInputStream.skipBytes(1);
+ if (dataInputStream.skipBytes(1) != 1) {
+ throw new IOException("Invalid SOFx");
+ }
setAttribute("ImageLength",
String.valueOf(dataInputStream.readUnsignedShort()));
setAttribute("ImageWidth", String.valueOf(dataInputStream.readUnsignedShort()));
@@ -1285,7 +1310,9 @@ public class ExifInterface {
if (length < 0) {
throw new IOException("Invalid length");
}
- dataInputStream.skipBytes(length);
+ if (dataInputStream.skipBytes(length) != length) {
+ throw new IOException("Invalid JPEG segment");
+ }
bytesRead += length;
}
}
@@ -1317,10 +1344,11 @@ public class ExifInterface {
byte[] bytes = new byte[4096];
while (true) {
- if (dataInputStream.readByte() != MARKER) {
+ byte marker = dataInputStream.readByte();
+ if (marker != MARKER) {
throw new IOException("Invalid marker");
}
- byte marker = dataInputStream.readByte();
+ marker = dataInputStream.readByte();
switch (marker) {
case MARKER_APP1: {
int length = dataInputStream.readUnsignedShort() - 2;
@@ -1341,6 +1369,8 @@ public class ExifInterface {
}
}
// Copy non-EXIF APP1 segment.
+ dataOutputStream.writeByte(MARKER);
+ dataOutputStream.writeByte(marker);
dataOutputStream.writeUnsignedShort(length + 2);
if (length >= 6) {
length -= 6;
@@ -1644,7 +1674,7 @@ public class ExifInterface {
String tagName = (String) sExifTagMapsForReading[hint].get(tagNumber);
if (DEBUG) {
- Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d," +
+ Log.d(TAG, String.format("hint: %d, tagNumber: %d, tagName: %s, dataFormat: %d, " +
"numberOfComponents: %d", hint, tagNumber, tagName, dataFormat,
numberOfComponents));
}
@@ -1858,6 +1888,19 @@ public class ExifInterface {
for (ExifTag tag : IFD_POINTER_TAGS) {
setAttribute(tag.name, null);
}
+ // Remove old thumbnail data
+ setAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name, null);
+ setAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name, null);
+
+ // Remove null value tags.
+ for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
+ for (Object obj : mAttributes[hint].entrySet().toArray()) {
+ Map.Entry entry = (Map.Entry) obj;
+ if (entry.getValue() == null) {
+ mAttributes[hint].remove(entry.getKey());
+ }
+ }
+ }
// Add IFD pointer tags. The next offset of primary image TIFF IFD will have thumbnail IFD
// offset when there is one or more tags in the thumbnail IFD.
@@ -1870,25 +1913,12 @@ public class ExifInterface {
if (!mAttributes[IFD_GPS_HINT].isEmpty()) {
mAttributes[IFD_TIFF_HINT].put(IFD_POINTER_TAGS[1].name, "0");
}
- // Remove old thumbnail data
- setAttribute(JPEG_INTERCHANGE_FORMAT_TAG.name, null);
- setAttribute(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name, null);
if (mHasThumbnail) {
mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_TAG.name, "0");
mAttributes[IFD_TIFF_HINT].put(JPEG_INTERCHANGE_FORMAT_LENGTH_TAG.name,
String.valueOf(mThumbnailLength));
}
- // Remove null value tags.
- for (int hint = 0; hint < EXIF_TAGS.length; ++hint) {
- for (Object obj : mAttributes[hint].entrySet().toArray()) {
- Map.Entry entry = (Map.Entry) obj;
- if (entry.getValue() == null) {
- mAttributes[hint].remove(entry.getKey());
- }
- }
- }
-
// Calculate IFD group data area sizes. IFD group data area is assigned to save the entry
// value which has a bigger size than 4 bytes.
for (int i = 0; i < 5; ++i) {
@@ -2025,6 +2055,12 @@ public class ExifInterface {
int bytesWritten = 0;
int dataFormat = getDataFormatOfExifEntryValue(entryValue);
+ if (dataFormat == IFD_FORMAT_STRING) {
+ byte[] asciiArray = (entryValue + '\0').getBytes(Charset.forName("US-ASCII"));
+ dataOutputStream.write(asciiArray);
+ return asciiArray.length;
+ }
+
// Values can be composed of several components. Each component is separated by char ','.
String[] components = entryValue.split(",");
for (String component : components) {
@@ -2037,11 +2073,6 @@ public class ExifInterface {
dataOutputStream.writeDouble(Double.parseDouble(component));
bytesWritten += 8;
break;
- case IFD_FORMAT_STRING:
- byte[] asciiArray = (component + '\0').getBytes(Charset.forName("US-ASCII"));
- dataOutputStream.write(asciiArray);
- bytesWritten += asciiArray.length;
- break;
case IFD_FORMAT_SRATIONAL:
String[] rationalNumber = component.split("/");
dataOutputStream.writeInt(Integer.parseInt(rationalNumber[0]));
@@ -2060,11 +2091,31 @@ public class ExifInterface {
// See TIFF 6.0 spec Types. page 15.
// Take the first component if there are more than one component.
if (entryValue.contains(",")) {
- entryValue = entryValue.split(",")[0];
+ String[] entryValues = entryValue.split(",");
+ int dataFormat = getDataFormatOfExifEntryValue(entryValues[0]);
+ if (dataFormat == IFD_FORMAT_STRING) {
+ return IFD_FORMAT_STRING;
+ }
+ for (int i = 1; i < entryValues.length; ++i) {
+ if (getDataFormatOfExifEntryValue(entryValues[i]) != dataFormat) {
+ return IFD_FORMAT_STRING;
+ }
+ }
+ return dataFormat;
}
if (entryValue.contains("/")) {
- return IFD_FORMAT_SRATIONAL;
+ String[] rationalNumber = entryValue.split("/");
+ if (rationalNumber.length == 2) {
+ try {
+ Integer.parseInt(rationalNumber[0]);
+ Integer.parseInt(rationalNumber[1]);
+ return IFD_FORMAT_SRATIONAL;
+ } catch (NumberFormatException e) {
+ // Ignored
+ }
+ }
+ return IFD_FORMAT_STRING;
}
try {
Integer.parseInt(entryValue);
@@ -2084,6 +2135,9 @@ public class ExifInterface {
// Determines the size of EXIF entry value.
private static int getSizeOfExifEntryValue(int dataFormat, String entryValue) {
// See TIFF 6.0 spec Types page 15.
+ if (dataFormat == IFD_FORMAT_STRING) {
+ return (entryValue + '\0').getBytes(Charset.forName("US-ASCII")).length;
+ }
int bytesEstimated = 0;
String[] components = entryValue.split(",");
for (String component : components) {
@@ -2094,10 +2148,6 @@ public class ExifInterface {
case IFD_FORMAT_DOUBLE:
bytesEstimated += 8;
break;
- case IFD_FORMAT_STRING:
- bytesEstimated
- += (component + '\0').getBytes(Charset.forName("US-ASCII")).length;
- break;
case IFD_FORMAT_SRATIONAL:
bytesEstimated += 8;
break;
diff --git a/media/java/android/media/IMediaResourceMonitor.aidl b/media/java/android/media/IMediaResourceMonitor.aidl
index 7b4bc3962ff1..cf0e56d1e786 100644
--- a/media/java/android/media/IMediaResourceMonitor.aidl
+++ b/media/java/android/media/IMediaResourceMonitor.aidl
@@ -19,6 +19,6 @@ package android.media;
/** {@hide} */
interface IMediaResourceMonitor
{
- oneway void notifyResourceGranted(in int pid, String type, String subType, long value);
+ oneway void notifyResourceGranted(in int pid, in int type);
}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
index 5bd607922c81..6207f7d59809 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/ExifInterfaceTest.java
@@ -417,13 +417,15 @@ public class ExifInterfaceTest extends AndroidTestCase {
testExifInterfaceForRaw(LG_G4_ISO_800_DNG, R.array.lg_g4_iso_800_dng);
}
- public void testCorruptedImage() throws Throwable {
+ public void testDoNotFailOnCorruptedImage() throws Throwable {
+ // To keep the compatibility with old versions of ExifInterface, even on a corrupted image,
+ // it shouldn't raise any exceptions except an IOException when unable to open a file.
byte[] bytes = new byte[1024];
try {
new ExifInterface(new ByteArrayInputStream(bytes));
- fail("Should not reach here!");
+ // Always success
} catch (IOException e) {
- // Success
+ fail("Should not reach here!");
}
}
diff --git a/packages/DocumentsUI/Android.mk b/packages/DocumentsUI/Android.mk
index d5e48b5855e7..3197abddb7a3 100644
--- a/packages/DocumentsUI/Android.mk
+++ b/packages/DocumentsUI/Android.mk
@@ -31,9 +31,13 @@ LOCAL_AAPT_FLAGS := \
--extra-packages android.support.v7.recyclerview
LOCAL_JACK_FLAGS := \
- -D jack.assert.policy=enable \
-D jack.optimization.inner-class.accessors=true
+# Only enable asserts on userdebug/eng builds
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+LOCAL_JACK_FLAGS += -D jack.assert.policy=enable
+endif
+
LOCAL_PACKAGE_NAME := DocumentsUI
LOCAL_CERTIFICATE := platform
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index a4acf7e7a6b7..14609b21d19d 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -44,8 +44,8 @@
<activity
android:name=".LauncherActivity"
android:theme="@android:style/Theme.NoDisplay"
- android:icon="@drawable/ic_files_app"
- android:label="@string/files_label">
+ android:icon="@mipmap/ic_launcher_download"
+ android:label="@string/downloads_label">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
@@ -55,8 +55,8 @@
<activity
android:name=".FilesActivity"
android:theme="@style/DocumentsTheme"
- android:icon="@drawable/ic_files_app"
- android:label="@string/files_label"
+ android:icon="@mipmap/ic_launcher_download"
+ android:label="@string/downloads_label"
android:documentLaunchMode="intoExisting">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/packages/DocumentsUI/res/color/item_details.xml b/packages/DocumentsUI/res/color/item_details.xml
index 769b94472a31..ac21fe348594 100644
--- a/packages/DocumentsUI/res/color/item_details.xml
+++ b/packages/DocumentsUI/res/color/item_details.xml
@@ -18,9 +18,5 @@
<item
android:state_enabled="true"
android:color="?android:attr/textColorPrimary"
- android:alpha="0.63" />
- <item
- android:state_enabled="false"
- android:color="?android:attr/textColorPrimary"
- android:alpha="0.3" />
+ android:alpha="0.54" />
</selector>
diff --git a/packages/DocumentsUI/res/color/item_title.xml b/packages/DocumentsUI/res/color/item_title.xml
index ef6aea33fece..9fff2f1bc0d5 100644
--- a/packages/DocumentsUI/res/color/item_title.xml
+++ b/packages/DocumentsUI/res/color/item_title.xml
@@ -17,9 +17,10 @@
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:state_enabled="true"
- android:color="?android:attr/textColorPrimary" />
+ android:color="?android:attr/textColorPrimary"
+ android:alpha="0.87" />
<item
android:state_enabled="false"
android:color="?android:attr/textColorPrimary"
- android:alpha="0.3" />
+ android:alpha="0.54" />
</selector>
diff --git a/packages/DocumentsUI/res/drawable/ic_files_app.xml b/packages/DocumentsUI/res/drawable/ic_files_app.xml
deleted file mode 100644
index ff7189e94e8b..000000000000
--- a/packages/DocumentsUI/res/drawable/ic_files_app.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/icon256"
- android:tint="?android:attr/colorControlNormal"
- android:autoMirrored="true" />
diff --git a/packages/DocumentsUI/res/drawable/icon256.png b/packages/DocumentsUI/res/drawable/icon256.png
deleted file mode 100644
index 631c95144f60..000000000000
--- a/packages/DocumentsUI/res/drawable/icon256.png
+++ /dev/null
Binary files differ
diff --git a/packages/DocumentsUI/res/layout/item_dir_grid.xml b/packages/DocumentsUI/res/layout/item_dir_grid.xml
index 429a972c5d94..36af9b952d69 100644
--- a/packages/DocumentsUI/res/layout/item_dir_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_dir_grid.xml
@@ -23,14 +23,16 @@
android:elevation="@dimen/grid_item_elevation"
android:focusable="true" >
+ <!-- The height is 48px.
+ paddingTop (9dp) + @dimen/check_icon_size (30dp) + paddingBottom (9dp) -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
- android:paddingBottom="16dp"
- android:paddingLeft="12dp"
+ android:paddingBottom="9dp"
+ android:paddingLeft="9dp"
android:paddingRight="12dp"
- android:paddingTop="16dp"
+ android:paddingTop="9dp"
android:gravity="center_vertical">
<FrameLayout
diff --git a/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..f958bbd3c255
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-hdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..f2e937663c2c
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-mdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..4dc533638757
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-xhdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..8716290969da
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-xxhdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..f5be21991761
--- /dev/null
+++ b/packages/DocumentsUI/res/mipmap-xxxhdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
index 461450e5aaaa..7bbf9426fedd 100644
--- a/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/DocumentsUI/res/values-b+sr+Latn/strings.xml
@@ -126,10 +126,8 @@
<item quantity="few">Izabrane su <xliff:g id="COUNT_1">%1$d</xliff:g> stavke</item>
<item quantity="other">Izabrano je <xliff:g id="COUNT_1">%1$d</xliff:g> stavki</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Želite li da izbrišete „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Želite li da izbrišete direktorijum „<xliff:g id="NAME">%1$s</xliff:g>“ i njegov sadržaj?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index 4a978fcae613..329f92f89625 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other">Избрахте <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Избрахте <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Искате ли да изтриете „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Искате ли да изтриете папката „<xliff:g id="NAME">%1$s</xliff:g>“ и съдържанието в нея?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-bn-rBD/strings.xml b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
index 32c870757813..936e2ddb6dce 100644
--- a/packages/DocumentsUI/res/values-bn-rBD/strings.xml
+++ b/packages/DocumentsUI/res/values-bn-rBD/strings.xml
@@ -118,10 +118,8 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g>টি নির্বাচন করা হয়েছে</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" মুছবেন?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ফোল্ডার এবং এটির সামগ্রীগুলিকে মুছবেন?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 48779e91ad00..044350a76c3f 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elements seleccionats</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> element seleccionat</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vols suprimir el fitxer <xliff:g id="NAME">%1$s</xliff:g>?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vols suprimir la carpeta <xliff:g id="NAME">%1$s</xliff:g> i el seu contingut?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index a9c410d39fdb..766222cd8b02 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> ausgewählt</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> ausgewählt</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" löschen?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ordner \"<xliff:g id="NAME">%1$s</xliff:g>\" und dessen Inhalte löschen?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 6a52970e621c..6d847b590cfe 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementos seleccionados</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento seleccionado</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"¿Deseas borrar \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"¿Deseas borrar la carpeta \"<xliff:g id="NAME">%1$s</xliff:g>\" y su contenido?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 6935436e7183..15b569442327 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> seleccionados</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> seleccionado</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"¿Eliminar <xliff:g id="NAME">%1$s</xliff:g>?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"¿Eliminar la carpeta <xliff:g id="NAME">%1$s</xliff:g> y su contenido?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 4351a34195ab..ed60aa94b647 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> on valitud</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> on valitud</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Kas kustutada fail „<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Kas kustutada kaust „<xliff:g id="NAME">%1$s</xliff:g>” ja selle sisu?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-eu-rES/strings.xml b/packages/DocumentsUI/res/values-eu-rES/strings.xml
index 934920d54df9..f3d68b0dc870 100644
--- a/packages/DocumentsUI/res/values-eu-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-eu-rES/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> hautatuta</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> hautatuta</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" ezabatu nahi duzu?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" karpeta eta bertako edukia ezabatu nahi duzu?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 9afd0ff485cf..279aad78a550 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valittu</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> valittu</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Poistetaanko <xliff:g id="NAME">%1$s</xliff:g>?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Poistetaanko kansio <xliff:g id="NAME">%1$s</xliff:g> ja sen sisältö?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index c88fd5807254..347a3f29969c 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -118,10 +118,8 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> élément sélectionné</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> éléments sélectionnés</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Supprimer « <xliff:g id="NAME">%1$s</xliff:g> »?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Supprimer le dossier «  <xliff:g id="NAME">%1$s</xliff:g> » et son contenu?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-gl-rES/strings.xml b/packages/DocumentsUI/res/values-gl-rES/strings.xml
index cd645b0ef904..58181f890ebb 100644
--- a/packages/DocumentsUI/res/values-gl-rES/strings.xml
+++ b/packages/DocumentsUI/res/values-gl-rES/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other">Seleccionáronse <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Seleccionouse <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Queres eliminar \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Queres eliminar o cartafol \"<xliff:g id="NAME">%1$s</xliff:g>\" e o seu contido?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index c60844401ab4..0d42d5dd32d3 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -126,10 +126,8 @@
<item quantity="few">Odabrano: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Odabrano: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Želite li izbrisati datoteku \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Želite li izbrisati mapu \"<xliff:g id="NAME">%1$s</xliff:g>\" i njezin sadržaj?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-is-rIS/strings.xml b/packages/DocumentsUI/res/values-is-rIS/strings.xml
index 5f798259bd2e..a2a0d9b7e0f1 100644
--- a/packages/DocumentsUI/res/values-is-rIS/strings.xml
+++ b/packages/DocumentsUI/res/values-is-rIS/strings.xml
@@ -118,10 +118,8 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> valið</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> valin</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Eyða „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Eyða möppunni „<xliff:g id="NAME">%1$s</xliff:g>“ og öllu innihaldi hennar?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index 8d9da3cdec00..ddede45a1c47 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> elementi selezionati</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> elemento selezionato</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Eliminare \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Eliminare la cartella \"<xliff:g id="NAME">%1$s</xliff:g>\" e i relativi contenuti?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index b2e6a7685bd0..3cad318db17f 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> 個を選択中</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> 個を選択中</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"「<xliff:g id="NAME">%1$s</xliff:g>」を削除しますか?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"フォルダ「<xliff:g id="NAME">%1$s</xliff:g>」とそのコンテンツを削除しますか?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index 6b41a7944ff6..8aec2d471ff9 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -134,10 +134,8 @@
<item quantity="many">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elemento</item>
<item quantity="other">Pasirinkta <xliff:g id="COUNT_1">%1$d</xliff:g> elementų</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Ištrinti „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ištrinti aplanką „<xliff:g id="NAME">%1$s</xliff:g>“ ir jo turinį?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index c1913b8c3940..be2f0b7fa71c 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -126,10 +126,8 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīts</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> atlasīti</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vai izdzēst failu “<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vai izdzēst mapi “<xliff:g id="NAME">%1$s</xliff:g>” un tās saturu?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-mk-rMK/strings.xml b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
index 4d09437731b5..e9c7f3fae4cc 100644
--- a/packages/DocumentsUI/res/values-mk-rMK/strings.xml
+++ b/packages/DocumentsUI/res/values-mk-rMK/strings.xml
@@ -118,10 +118,8 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> е избрана</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> се избрани</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Да се избрише „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Да се избрише папката „<xliff:g id="NAME">%1$s</xliff:g>“ и нејзините содржини?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 00bdec114774..c5f4771a5d84 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> dipilih</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> dipilih</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Padamkan \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Padamkan folder \"<xliff:g id="NAME">%1$s</xliff:g>\" dan kandungannya?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index c308ac9e25c5..5922d1c4d48d 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> er valgt</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> er valgt</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Vil du slette «<xliff:g id="NAME">%1$s</xliff:g>»?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Vil du slette «<xliff:g id="NAME">%1$s</xliff:g>»-mappen og innholdet i den?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 4e941c492709..7a35bc243ed2 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -134,10 +134,8 @@
<item quantity="other">Wybrano <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="one">Wybrano <xliff:g id="COUNT_0">%1$d</xliff:g></item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Usunąć „<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Usunąć folder „<xliff:g id="NAME">%1$s</xliff:g>” i jego zawartość?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-pt-rBR/strings.xml b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
index ff78ba45ebea..b765cd0d15bb 100644
--- a/packages/DocumentsUI/res/values-pt-rBR/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rBR/strings.xml
@@ -118,10 +118,8 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Excluir \" <xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Excluir pasta \"<xliff:g id="NAME">%1$s</xliff:g>\" e o respectivo conteúdo?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index ff78ba45ebea..b765cd0d15bb 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -118,10 +118,8 @@
<item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Excluir \" <xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Excluir pasta \"<xliff:g id="NAME">%1$s</xliff:g>\" e o respectivo conteúdo?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 15df228add1d..10f6aee035cc 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -126,10 +126,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selectate</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> selectat</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Ștergeți „<xliff:g id="NAME">%1$s</xliff:g>”?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Ștergeți dosarul „<xliff:g id="NAME">%1$s</xliff:g>” și conținutul acestuia?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index e70407b8baed..d9f400979d24 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -134,10 +134,8 @@
<item quantity="many">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Выбрано: <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Удалить файл \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Удалить папку \"<xliff:g id="NAME">%1$s</xliff:g>\" со всем содержимым?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-sq-rAL/strings.xml b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
index b13b47070d42..f5ebbbcbce58 100644
--- a/packages/DocumentsUI/res/values-sq-rAL/strings.xml
+++ b/packages/DocumentsUI/res/values-sq-rAL/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> të zgjedhur</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> i zgjedhur</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Të fshihet \"<xliff:g id="NAME">%1$s</xliff:g>\"?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Të fshihet dosja \"<xliff:g id="NAME">%1$s</xliff:g>\" dhe përmbajtja e saj?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index 13322af275bd..6a6488e01a4e 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -126,10 +126,8 @@
<item quantity="few">Изабране су <xliff:g id="COUNT_1">%1$d</xliff:g> ставке</item>
<item quantity="other">Изабрано је <xliff:g id="COUNT_1">%1$d</xliff:g> ставки</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Желите ли да избришете „<xliff:g id="NAME">%1$s</xliff:g>“?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Желите ли да избришете директоријум „<xliff:g id="NAME">%1$s</xliff:g>“ и његов садржај?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-ta-rIN/strings.xml b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
index 8470b9dcb6d6..b32c324dad6b 100644
--- a/packages/DocumentsUI/res/values-ta-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-ta-rIN/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டன</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> தேர்ந்தெடுக்கப்பட்டது</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\"ஐ நீக்கவா?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" கோப்புறையையும் அதன் உள்ளடக்கத்தையும் நீக்கவா?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index 519a05e447de..bc4db0db2cb3 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> öğe seçildi</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> öğe seçildi</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" silinsin mi?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" adlı klasör ve içindekiler silinsin mi?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index 5aefae328320..79b6fbfc04ac 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -134,10 +134,8 @@
<item quantity="many">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
<item quantity="other">Вибрано <xliff:g id="COUNT_1">%1$d</xliff:g></item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"Видалити файл <xliff:g id="NAME">%1$s</xliff:g>?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"Видалити папку \"<xliff:g id="NAME">%1$s</xliff:g>\" та її вміст?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-ur-rPK/strings.xml b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
index 72d28378d42c..4498f8744156 100644
--- a/packages/DocumentsUI/res/values-ur-rPK/strings.xml
+++ b/packages/DocumentsUI/res/values-ur-rPK/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> منتخب کردہ</item>
<item quantity="one"><xliff:g id="COUNT_0">%1$d</xliff:g> منتخب کردہ</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"\"<xliff:g id="NAME">%1$s</xliff:g>\" حذف کریں؟"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"\"<xliff:g id="NAME">%1$s</xliff:g>\" فولڈر اور اس کی مشمولات حذف کریں؟"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 7afc6184b7c8..90d16198cf4b 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -118,10 +118,8 @@
<item quantity="other">已选择 <xliff:g id="COUNT_1">%1$d</xliff:g> 项</item>
<item quantity="one">已选择 <xliff:g id="COUNT_0">%1$d</xliff:g> 项</item>
</plurals>
- <!-- no translation found for delete_filename_confirmation_message (5312817725577537488) -->
- <skip />
- <!-- no translation found for delete_foldername_confirmation_message (5885501832257285329) -->
- <skip />
+ <string name="delete_filename_confirmation_message" msgid="5312817725577537488">"要删除“<xliff:g id="NAME">%1$s</xliff:g>”吗?"</string>
+ <string name="delete_foldername_confirmation_message" msgid="5885501832257285329">"要删除文件夹“<xliff:g id="NAME">%1$s</xliff:g>”及其中的内容吗?"</string>
<!-- no translation found for delete_files_confirmation_message (8417505791395471802) -->
<!-- no translation found for delete_folders_confirmation_message (9185648028213507769) -->
<!-- no translation found for delete_items_confirmation_message (5376214433530243459) -->
diff --git a/packages/DocumentsUI/res/values/config.xml b/packages/DocumentsUI/res/values/config.xml
index ebb3969b7819..408603e85f7e 100644
--- a/packages/DocumentsUI/res/values/config.xml
+++ b/packages/DocumentsUI/res/values/config.xml
@@ -24,5 +24,6 @@
<!-- Indicates if the home directory should be hidden in the roots list, that is presented
in the drawer/left side panel ) -->
<bool name="home_root_hidden">true</bool>
-
+ <!-- Indicates if the advanced roots like internal storage should be hidden in the roots list) -->
+ <bool name="advanced_roots_hidden">true</bool>
</resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 0d098e69b73b..b26ee9778d33 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -204,6 +204,9 @@
<string name="open_external_dialog_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
access to <xliff:g id="directory" example="Pictures"><i>^2</i></xliff:g> directory on
<xliff:g id="storage" example="SD Card"><i>^3</i></xliff:g>?</string>
+ <!-- Text in an alert dialog asking user to grant app access to all data in an external storage volume -->
+ <string name="open_external_dialog_root_request">Grant <xliff:g id="appName" example="System Settings"><b>^1</b></xliff:g>
+ access to your data, including photos and videos, on <xliff:g id="storage" example="SD Card"><i>^2</i></xliff:g>?</string>
<!-- Checkbox that allows user to not be questioned about the directory access request again -->
<string name="never_ask_again">Don\'t ask again</string>
<!-- Text in the button asking user to allow access to a given directory. -->
diff --git a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
index fe61094e56d4..29110275716e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/BaseActivity.java
@@ -437,6 +437,17 @@ public abstract class BaseActivity extends Activity
return mState;
}
+ /*
+ * Get the default directory to be presented after starting the activity.
+ * Method can be overridden if the change of the behavior of the the child activity is needed.
+ */
+ public Uri getDefaultRoot() {
+ return Shared.isHomeRootHidden(this)
+ ? DocumentsContract.buildRootUri("com.android.providers.downloads.documents",
+ "downloads")
+ : DocumentsContract.buildHomeUri();
+ }
+
void setDisplayFileSize(boolean display) {
LocalPreferences.setDisplayFileSize(this, display);
mState.showSize = display;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index ba593dc370bc..5788420a053c 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -108,7 +108,7 @@ public class DocumentsActivity extends BaseActivity {
// we restore the stack as last used from that app.
if (mState.action == ACTION_PICK_COPY_DESTINATION) {
if (DEBUG) Log.d(TAG, "Launching directly into Home directory.");
- loadRoot(DocumentsContract.buildHomeUri());
+ loadRoot(getDefaultRoot());
} else {
if (DEBUG) Log.d(TAG, "Attempting to load last used stack for calling package.");
new LoadLastUsedStackTask(this).execute();
@@ -164,7 +164,7 @@ public class DocumentsActivity extends BaseActivity {
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
- Log.d(TAG, "onActivityResult() code=" + resultCode);
+ if (DEBUG) Log.d(TAG, "onActivityResult() code=" + resultCode);
// Only relay back results when not canceled; otherwise stick around to
// let the user pick another app/backend.
@@ -203,8 +203,8 @@ public class DocumentsActivity extends BaseActivity {
mState.action == ACTION_PICK_COPY_DESTINATION) {
title = getResources().getString(R.string.title_save);
} else {
- // If all else fails, just call it "Files".
- title = getResources().getString(R.string.files_label);
+ // If all else fails, just call it "Downloads".
+ title = getResources().getString(R.string.downloads_label);
}
}
@@ -388,7 +388,7 @@ public class DocumentsActivity extends BaseActivity {
@Override
void onTaskFinished(Uri... uris) {
- Log.d(TAG, "onFinished() " + Arrays.toString(uris));
+ if (DEBUG) Log.d(TAG, "onFinished() " + Arrays.toString(uris));
final Intent intent = new Intent();
if (uris.length == 1) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
index 99f306a44020..2af6c461f2f6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilesActivity.java
@@ -109,9 +109,7 @@ public class FilesActivity extends BaseActivity {
loadRoot(uri);
} else {
if (DEBUG) Log.d(TAG, "All other means skipped. Launching into default directory.");
- Uri defaultUri = DocumentsContract.buildRootUri(
- "com.android.providers.downloads.documents", "downloads");
- loadRoot(defaultUri);
+ loadRoot(getDefaultRoot());
}
final @DialogType int dialogType = intent.getIntExtra(
@@ -182,7 +180,7 @@ public class FilesActivity extends BaseActivity {
@Override
public String getDrawerTitle() {
- return getResources().getString(R.string.files_label);
+ return getResources().getString(R.string.downloads_label);
}
@Override
@@ -414,7 +412,7 @@ public class FilesActivity extends BaseActivity {
@Override
void onTaskFinished(Uri... uris) {
- Log.d(TAG, "onFinished() " + Arrays.toString(uris));
+ if (DEBUG) Log.d(TAG, "onFinished() " + Arrays.toString(uris));
final Intent intent = new Intent();
if (uris.length == 1) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
index 8c4859f52a02..2315664f0d8a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/LocalPreferences.java
@@ -16,8 +16,6 @@
package com.android.documentsui;
-import static com.android.documentsui.Shared.DEBUG;
-import static com.android.documentsui.Shared.TAG;
import static com.android.documentsui.State.MODE_UNKNOWN;
import java.lang.annotation.Retention;
@@ -29,7 +27,6 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.UserHandle;
import android.preference.PreferenceManager;
-import android.util.Log;
import com.android.documentsui.State.ViewMode;
import com.android.documentsui.model.RootInfo;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
index deef1c278e63..929d1e0d0ac6 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Metrics.java
@@ -427,10 +427,14 @@ public final class Metrics {
public static void logValidScopedAccessRequest(Activity activity, String directory,
@ScopedAccessGrant int type) {
int index = -1;
- for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
- if (STANDARD_DIRECTORIES[i].equals(directory)) {
- index = i;
- break;
+ if (OpenExternalDirectoryActivity.DIRECTORY_ROOT.equals(directory)) {
+ index = -2;
+ } else {
+ for (int i = 0; i < STANDARD_DIRECTORIES.length; i++) {
+ if (STANDARD_DIRECTORIES[i].equals(directory)) {
+ index = i;
+ break;
+ }
}
}
final String packageName = activity.getCallingPackage();
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
index 2b6f3968e203..2fe2756e9169 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -85,6 +85,9 @@ public class OpenExternalDirectoryActivity extends Activity {
private static final String EXTRA_APP_LABEL = "com.android.documentsui.APP_LABEL";
private static final String EXTRA_VOLUME_LABEL = "com.android.documentsui.VOLUME_LABEL";
private static final String EXTRA_VOLUME_UUID = "com.android.documentsui.VOLUME_UUID";
+ private static final String EXTRA_IS_ROOT = "com.android.documentsui.IS_ROOT";
+ // Special directory name representing the full volume
+ static final String DIRECTORY_ROOT = "ROOT_DIRECTORY";
private ContentProviderClient mExternalStorageClient;
@@ -114,13 +117,9 @@ public class OpenExternalDirectoryActivity extends Activity {
finish();
return;
}
- final String directoryName = intent.getStringExtra(EXTRA_DIRECTORY_NAME);
+ String directoryName = intent.getStringExtra(EXTRA_DIRECTORY_NAME );
if (directoryName == null) {
- logInvalidScopedAccessRequest(this, SCOPED_DIRECTORY_ACCESS_INVALID_ARGUMENTS);
- if (DEBUG) Log.d(TAG, "missing extra " + EXTRA_DIRECTORY_NAME + " on " + intent);
- setResult(RESULT_CANCELED);
- finish();
- return;
+ directoryName = DIRECTORY_ROOT;
}
final StorageVolume volume = (StorageVolume) storageVolume;
if (getScopedAccessPermissionStatus(getApplicationContext(), getCallingPackage(),
@@ -157,9 +156,11 @@ public class OpenExternalDirectoryActivity extends Activity {
if (DEBUG)
Log.d(TAG, "showFragment() for volume " + storageVolume.dump() + ", directory "
+ directoryName + ", and user " + userId);
+ final boolean isRoot = directoryName.equals(DIRECTORY_ROOT);
+ final File volumeRoot = storageVolume.getPathFile();
File file;
try {
- file = new File(storageVolume.getPathFile(), directoryName).getCanonicalFile();
+ file = isRoot ? volumeRoot : new File(volumeRoot, directoryName).getCanonicalFile();
} catch (IOException e) {
Log.e(TAG, "Could not get canonical file for volume " + storageVolume.dump()
+ " and directory " + directoryName);
@@ -169,16 +170,21 @@ public class OpenExternalDirectoryActivity extends Activity {
final StorageManager sm =
(StorageManager) activity.getSystemService(Context.STORAGE_SERVICE);
- final String root = file.getParent();
- final String directory = file.getName();
-
- // Verify directory is valid.
- if (TextUtils.isEmpty(directory) || !isStandardDirectory(directory)) {
- if (DEBUG)
- Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '"
- + file.getAbsolutePath() + "')");
- logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY);
- return false;
+ final String root, directory;
+ if (isRoot) {
+ root = volumeRoot.getAbsolutePath();
+ directory = ".";
+ } else {
+ root = file.getParent();
+ directory = file.getName();
+ // Verify directory is valid.
+ if (TextUtils.isEmpty(directory) || !isStandardDirectory(directory)) {
+ if (DEBUG)
+ Log.d(TAG, "Directory '" + directory + "' is not standard (full path: '"
+ + file.getAbsolutePath() + "')");
+ logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_INVALID_DIRECTORY);
+ return false;
+ }
}
// Gets volume label and converted path.
@@ -186,12 +192,13 @@ public class OpenExternalDirectoryActivity extends Activity {
String volumeUuid = null;
final List<VolumeInfo> volumes = sm.getVolumes();
if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size());
+ File internalRoot = null;
for (VolumeInfo volume : volumes) {
if (isRightVolume(volume, root, userId)) {
- final File internalRoot = volume.getInternalPathForUser(userId);
+ internalRoot = volume.getInternalPathForUser(userId);
// Must convert path before calling getDocIdForFileCreateNewDir()
if (DEBUG) Log.d(TAG, "Converting " + root + " to " + internalRoot);
- file = new File(internalRoot, directory);
+ file = isRoot ? internalRoot : new File(internalRoot, directory);
volumeLabel = sm.getBestVolumeDescription(volume);
volumeUuid = volume.getFsUuid();
break;
@@ -199,7 +206,7 @@ public class OpenExternalDirectoryActivity extends Activity {
}
// Checks if the user has granted the permission already.
- final Intent intent = getIntentForExistingPermission(activity, file);
+ final Intent intent = getIntentForExistingPermission(activity, isRoot, internalRoot, file);
if (intent != null) {
logValidScopedAccessRequest(activity, directory,
SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED);
@@ -227,6 +234,7 @@ public class OpenExternalDirectoryActivity extends Activity {
args.putString(EXTRA_VOLUME_LABEL, volumeLabel);
args.putString(EXTRA_VOLUME_UUID, volumeUuid);
args.putString(EXTRA_APP_LABEL, appLabel);
+ args.putBoolean(EXTRA_IS_ROOT, isRoot);
final FragmentManager fm = activity.getFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
@@ -282,7 +290,7 @@ public class OpenExternalDirectoryActivity extends Activity {
logInvalidScopedAccessRequest(context, SCOPED_DIRECTORY_ACCESS_ERROR);
return null;
}
- Log.d(TAG, "doc id for " + file + ": " + docId);
+ if (DEBUG) Log.d(TAG, "doc id for " + file + ": " + docId);
final Uri uri = DocumentsContract.buildTreeDocumentUri(EXTERNAL_STORAGE_AUTH, docId);
if (uri == null) {
@@ -310,19 +318,27 @@ public class OpenExternalDirectoryActivity extends Activity {
}
private static Intent getIntentForExistingPermission(OpenExternalDirectoryActivity activity,
- File file) {
+ boolean isRoot, File root, File file) {
final String packageName = activity.getCallingPackage();
- final Uri grantedUri =
- getGrantedUriPermission(activity, activity.getExternalStorageClient(), file);
+ final ContentProviderClient storageClient = activity.getExternalStorageClient();
+ final Uri grantedUri = getGrantedUriPermission(activity, storageClient, file);
+ final Uri rootUri = root.equals(file) ? grantedUri
+ : getGrantedUriPermission(activity, storageClient, root);
+
if (DEBUG)
- Log.d(TAG, "checking if " + packageName + " already has permission for " + grantedUri);
+ Log.d(TAG, "checking if " + packageName + " already has permission for " + grantedUri
+ + " or its root (" + rootUri + ")");
final ActivityManager am =
(ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
for (UriPermission uriPermission : am.getGrantedUriPermissions(packageName).getList()) {
final Uri uri = uriPermission.getUri();
- if (uri.equals(grantedUri)) {
+ if (uri == null) {
+ Log.w(TAG, "null URI for " + uriPermission);
+ continue;
+ }
+ if (uri.equals(grantedUri) || uri.equals(rootUri)) {
if (DEBUG) Log.d(TAG, packageName + " already has permission: " + uriPermission);
- return createGrantedUriPermissionsIntent(uri);
+ return createGrantedUriPermissionsIntent(grantedUri);
}
}
if (DEBUG) Log.d(TAG, packageName + " does not have permission for " + grantedUri);
@@ -335,6 +351,7 @@ public class OpenExternalDirectoryActivity extends Activity {
private String mVolumeUuid;
private String mVolumeLabel;
private String mAppLabel;
+ private boolean mIsRoot;
private CheckBox mDontAskAgain;
private OpenExternalDirectoryActivity mActivity;
private AlertDialog mDialog;
@@ -349,6 +366,7 @@ public class OpenExternalDirectoryActivity extends Activity {
mVolumeUuid = args.getString(EXTRA_VOLUME_UUID);
mVolumeLabel = args.getString(EXTRA_VOLUME_LABEL);
mAppLabel = args.getString(EXTRA_APP_LABEL);
+ mIsRoot = args.getBoolean(EXTRA_IS_ROOT);
}
mActivity = (OpenExternalDirectoryActivity) getActivity();
}
@@ -375,6 +393,7 @@ public class OpenExternalDirectoryActivity extends Activity {
mActivity = (OpenExternalDirectoryActivity) getActivity();
}
final String directory = mFile.getName();
+ final String directoryName = mIsRoot ? DIRECTORY_ROOT : directory;
final Context context = mActivity.getApplicationContext();
final OnClickListener listener = new OnClickListener() {
@@ -386,17 +405,17 @@ public class OpenExternalDirectoryActivity extends Activity {
mActivity.getExternalStorageClient(), mFile);
}
if (which == DialogInterface.BUTTON_NEGATIVE || intent == null) {
- logValidScopedAccessRequest(mActivity, directory,
+ logValidScopedAccessRequest(mActivity, directoryName,
SCOPED_DIRECTORY_ACCESS_DENIED);
final boolean checked = mDontAskAgain.isChecked();
if (checked) {
logValidScopedAccessRequest(mActivity, directory,
SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST);
setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
- mVolumeUuid, directory, PERMISSION_NEVER_ASK);
+ mVolumeUuid, directoryName, PERMISSION_NEVER_ASK);
} else {
setScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
- mVolumeUuid, directory, PERMISSION_ASK_AGAIN);
+ mVolumeUuid, directoryName, PERMISSION_ASK_AGAIN);
}
mActivity.setResult(RESULT_CANCELED);
} else {
@@ -408,13 +427,17 @@ public class OpenExternalDirectoryActivity extends Activity {
}
};
- final CharSequence message = TextUtils
- .expandTemplate(
- getText(R.string.open_external_dialog_request), mAppLabel, directory,
- mVolumeLabel);
@SuppressLint("InflateParams")
// It's ok pass null ViewRoot on AlertDialogs.
final View view = View.inflate(mActivity, R.layout.dialog_open_scoped_directory, null);
+ final CharSequence message;
+ if (mIsRoot) {
+ message = TextUtils.expandTemplate(getText(
+ R.string.open_external_dialog_root_request), mAppLabel, mVolumeLabel);
+ } else {
+ message = TextUtils.expandTemplate(getText(R.string.open_external_dialog_request),
+ mAppLabel, directory, mVolumeLabel);
+ }
final TextView messageField = (TextView) view.findViewById(R.id.message);
messageField.setText(message);
mDialog = new AlertDialog.Builder(mActivity, R.style.Theme_AppCompat_Light_Dialog_Alert)
@@ -425,7 +448,7 @@ public class OpenExternalDirectoryActivity extends Activity {
mDontAskAgain = (CheckBox) view.findViewById(R.id.do_not_ask_checkbox);
if (getScopedAccessPermissionStatus(context, mActivity.getCallingPackage(),
- mVolumeUuid, directory) == PERMISSION_ASK_AGAIN) {
+ mVolumeUuid, directoryName) == PERMISSION_ASK_AGAIN) {
mDontAskAgain.setVisibility(View.VISIBLE);
mDontAskAgain.setOnCheckedChangeListener(new OnCheckedChangeListener() {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index e1b1c09be364..6ef9154451a2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -16,6 +16,7 @@
package com.android.documentsui;
+import static com.android.documentsui.Shared.DEBUG;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
import android.content.ContentProvider;
@@ -338,7 +339,7 @@ public class RecentsProvider extends ContentProvider {
if (predicate.apply(authority)) {
db.delete(TABLE_STATE, StateColumns.AUTHORITY + "=?", new String[] {
authority });
- Log.d(TAG, "Purged state for " + authority);
+ if (DEBUG) Log.d(TAG, "Purged state for " + authority);
}
}
} finally {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index 54e628732a60..35da8cc6357b 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -318,7 +318,9 @@ public class RootsFragment extends Fragment {
for (final RootInfo root : roots) {
final RootItem item = new RootItem(root);
- if (root.isHome() && isHomeRootHidden(context)) {
+ if (root.isHome() && Shared.isHomeRootHidden(context)) {
+ continue;
+ } else if (root.isAdvanced() && Shared.areAdvancedRootsHidden(context)) {
continue;
} else if (root.isLibrary()) {
if (DEBUG) Log.d(TAG, "Adding " + root + " as library.");
@@ -370,13 +372,6 @@ public class RootsFragment extends Fragment {
}
}
- /*
- * Indicates if the home directory should be hidden in the roots list.
- */
- private boolean isHomeRootHidden(Context context) {
- return context.getResources().getBoolean(R.bool.home_root_hidden);
- }
-
@Override
public View getView(int position, View convertView, ViewGroup parent) {
final Item item = getItem(position);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
index 63dc2ee3796e..4d0ba4b79346 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/SearchViewManager.java
@@ -16,6 +16,8 @@
package com.android.documentsui;
+import static com.android.documentsui.Shared.DEBUG;
+
import android.annotation.Nullable;
import android.os.Bundle;
import android.provider.DocumentsContract.Root;
@@ -80,7 +82,7 @@ final class SearchViewManager implements
*/
void update(RootInfo root) {
if (mMenu == null) {
- Log.d(TAG, "update called before Search MenuItem installed.");
+ if (DEBUG) Log.d(TAG, "update called before Search MenuItem installed.");
return;
}
@@ -108,7 +110,7 @@ final class SearchViewManager implements
void showMenu(boolean visible) {
if (mMenu == null) {
- Log.d(TAG, "showMenu called before Search MenuItem installed.");
+ if (DEBUG) Log.d(TAG, "showMenu called before Search MenuItem installed.");
return;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/Shared.java b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
index 6f1863e313c5..d21afee93434 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/Shared.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/Shared.java
@@ -33,7 +33,7 @@ public final class Shared {
public static final String TAG = "Documents";
- public static final boolean DEBUG = true;
+ public static final boolean DEBUG = false;
/** Intent action name to pick a copy destination. */
public static final String ACTION_PICK_COPY_DESTINATION =
@@ -169,4 +169,18 @@ public final class Shared {
}
}
+ /*
+ * Indicates if the home directory should be hidden in the roots list.
+ */
+ public static boolean isHomeRootHidden(Context context) {
+ return context.getResources().getBoolean(R.bool.home_root_hidden);
+ }
+
+ /*
+ * Indicates if the advanced roots should be hidden.
+ */
+ public static boolean areAdvancedRootsHidden(Context context) {
+ return context.getResources().getBoolean(R.bool.advanced_roots_hidden);
+ }
+
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 60e4b9abd4fe..062f2d17754e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -72,6 +72,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
+import android.widget.Toolbar;
import android.widget.TextView;
import com.android.documentsui.BaseActivity;
@@ -506,8 +507,10 @@ public class DirectoryFragment extends Fragment
getActivity().getWindow().setStatusBarColor(color.data);
if (mActionMode != null) {
- mActionMode.setTitle(Shared.getQuantityString(getActivity(),
- R.plurals.elements_selected, mSelected.size()));
+ final String title = Shared.getQuantityString(getActivity(),
+ R.plurals.elements_selected, mSelected.size());
+ mActionMode.setTitle(title);
+ mRecView.announceForAccessibility(title);
}
}
@@ -521,6 +524,16 @@ public class DirectoryFragment extends Fragment
mSelected.clear();
mNoDeleteCount = 0;
mNoRenameCount = -1;
+
+ // Re-enable TalkBack for the toolbars, as they are no longer covered by action mode.
+ final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
+ toolbar.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+
+ // This toolbar is not present in the fixed_layout
+ final Toolbar rootsToolbar = (Toolbar) getActivity().findViewById(R.id.roots_toolbar);
+ if (rootsToolbar != null) {
+ rootsToolbar.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+ }
}
@Override
@@ -530,7 +543,25 @@ public class DirectoryFragment extends Fragment
int size = mSelectionManager.getSelection().size();
mode.getMenuInflater().inflate(R.menu.mode_directory, menu);
mode.setTitle(TextUtils.formatSelectedCount(size));
- return (size > 0);
+
+ if (size > 0) {
+ // Hide the toolbars if action mode is enabled, so TalkBack doesn't navigate to
+ // these controls when using linear navigation.
+ final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
+ toolbar.setImportantForAccessibility(
+ View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+
+ // This toolbar is not present in the fixed_layout
+ final Toolbar rootsToolbar = (Toolbar) getActivity().findViewById(
+ R.id.roots_toolbar);
+ if (rootsToolbar != null) {
+ rootsToolbar.setImportantForAccessibility(
+ View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS);
+ }
+ return true;
+ }
+
+ return false;
}
@Override
diff --git a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
index ea1deb4cdcdb..faa8e3892f61 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/dirlist/FragmentTuner.java
@@ -159,9 +159,6 @@ public abstract class FragmentTuner {
void onModelLoaded(Model model, @ResultType int resultType, boolean isSearch) {
boolean showDrawer = false;
- if (mState.restored) {
- showDrawer = true;
- }
if (MimePredicate.mimeMatches(MimePredicate.VISUAL_MIMES, mState.acceptMimes)) {
showDrawer = false;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index 3960475f5ecd..0709652ec0dc 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -298,6 +298,10 @@ public class RootInfo implements Durable, Parcelable, Comparable<RootInfo> {
return (flags & Root.FLAG_SUPPORTS_SEARCH) != 0;
}
+ public boolean isAdvanced() {
+ return (flags & Root.FLAG_ADVANCED) != 0;
+ }
+
public boolean isLocalOnly() {
return (flags & Root.FLAG_LOCAL_ONLY) != 0;
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
index 3536593564af..b816287fcc47 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/dirlist/ModelTest.java
@@ -21,6 +21,7 @@ import android.content.Context;
import android.content.ContextWrapper;
import android.database.Cursor;
import android.database.MatrixCursor;
+import android.database.MergeCursor;
import android.provider.DocumentsContract.Document;
import android.test.AndroidTestCase;
import android.test.mock.MockContentResolver;
@@ -117,21 +118,25 @@ public class ModelTest extends AndroidTestCase {
// Tests multiple authorities with clashing document IDs.
public void testModelIdIsUnique() {
- MatrixCursor cIn = new MatrixCursor(COLUMNS);
+ MatrixCursor cIn1 = new MatrixCursor(COLUMNS);
+ MatrixCursor cIn2 = new MatrixCursor(COLUMNS);
// Make two sets of items with the same IDs, under different authorities.
final String AUTHORITY0 = "auth0";
final String AUTHORITY1 = "auth1";
+
for (int i = 0; i < ITEM_COUNT; ++i) {
- MatrixCursor.RowBuilder row0 = cIn.newRow();
+ MatrixCursor.RowBuilder row0 = cIn1.newRow();
row0.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY0);
row0.add(Document.COLUMN_DOCUMENT_ID, Integer.toString(i));
- MatrixCursor.RowBuilder row1 = cIn.newRow();
+ MatrixCursor.RowBuilder row1 = cIn2.newRow();
row1.add(RootCursorWrapper.COLUMN_AUTHORITY, AUTHORITY1);
row1.add(Document.COLUMN_DOCUMENT_ID, Integer.toString(i));
}
+ Cursor cIn = new MergeCursor(new Cursor[] { cIn1, cIn2 });
+
// Update the model, then make sure it contains all the expected items.
DirectoryResult r = new DirectoryResult();
r.cursor = cIn;
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 9a51b057d135..62f33bf490a8 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -196,6 +196,7 @@ public class ExternalStorageProvider extends DocumentsProvider {
if (volume.isPrimary()) {
// save off the primary volume for subsequent "Home" dir initialization.
primaryVolume = volume;
+ root.flags |= Root.FLAG_ADVANCED;
}
// Dunno when this would NOT be the case, but never hurts to be correct.
if (volume.isMountedWritable()) {
diff --git a/packages/Keyguard/res/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml
index 1db5f618f4c4..8ad4c5e5ac19 100644
--- a/packages/Keyguard/res/values-af/strings.xml
+++ b/packages/Keyguard/res/values-af/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK-bewerking het misluk!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kode is aanvaar!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Geen diens nie."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knoppie vir wissel van invoermetode."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Wissel invoermetode"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Vliegtuigmodus"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Patroon word vereis nadat toestel herbegin het"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN word vereis nadat toestel herbegin het"</string>
diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml
index 2b19d7a3be59..042562213db8 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"የሲም PUK ክወና አልተሳካም!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ኮዱ ተቀባይነት አግኝቷል!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ከአገልግሎት መስጫ ክልል ውጪ።"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"የግቤት ስልት አዝራር ቀይር"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"የግቤት ስልት ቀይር"</string>
<string name="airplane_mode" msgid="3122107900897202805">"የአውሮፕላን ሁነታ"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"መሣሪያ ዳግም ከጀመረ በኋላ ሥርዓተ ጥለት ያስፈልጋል"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"መሣሪያ ዳግም ከጀመረ በኋላ ፒን ያስፈልጋል"</string>
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index efaad1f8370a..442f29e44263 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -116,7 +116,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"‏أخفقت عملية PUK لبطاقة SIM!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"تم قبول الرمز!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"لا تتوفر خدمة"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"زر تبديل طريقة الإدخال."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"تبديل أسلوب الإدخال"</string>
<string name="airplane_mode" msgid="3122107900897202805">"وضع الطائرة"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"يجب رسم النقش بعد إعادة تشغيل الجهاز."</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"يجب إدخال رقم التعريف الشخصي بعد إعادة تشغيل الجهاز."</string>
diff --git a/packages/Keyguard/res/values-az-rAZ/strings.xml b/packages/Keyguard/res/values-az-rAZ/strings.xml
index 4450c0120f11..686024b32fea 100644
--- a/packages/Keyguard/res/values-az-rAZ/strings.xml
+++ b/packages/Keyguard/res/values-az-rAZ/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK əməliyyatı alınmadı!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod Qəbul Edildi!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Xidmət yoxdur."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Daxiletmə metodu düyməsinə keç"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Daxiletmə metoduna keçin"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Təyyarə rejimi"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Cihaz yeniden başladıqdan sonra qəlib kod tələb olunur"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Cihaz yeniden başladıqdan sonra PIN tələb olunur"</string>
diff --git a/packages/Keyguard/res/values-b+sr+Latn/strings.xml b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
index 0eb4210a49c3..a0af2895948a 100644
--- a/packages/Keyguard/res/values-b+sr+Latn/strings.xml
+++ b/packages/Keyguard/res/values-b+sr+Latn/strings.xml
@@ -110,7 +110,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Radnja sa SIM PUK kodom nije uspela!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kôd je prihvaćen!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Oflajn ste."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Dugme Promeni metod unosa."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Promeni metod unosa"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Režim rada u avionu"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Treba da unesete šablon kada se uređaj ponovo pokrene"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Treba da unesete PIN kada se uređaj ponovo pokrene"</string>
diff --git a/packages/Keyguard/res/values-be-rBY/strings.xml b/packages/Keyguard/res/values-be-rBY/strings.xml
index 5b917de5e172..59464bd1c035 100644
--- a/packages/Keyguard/res/values-be-rBY/strings.xml
+++ b/packages/Keyguard/res/values-be-rBY/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Разблакіраваць SIM-карту PUK-кодам не атрымалася!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код прыняты!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Не абслугоўваецца."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка пераключэння метаду ўводу."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Пераключэнне рэжыму ўводу"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Рэжым палёту"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Пасля перазапуску прылады патрабуецца ўзор"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Пасля перазапуску прылады патрабуецца PIN-код"</string>
diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml
index ae95c49b0113..9d4047ae9a07 100644
--- a/packages/Keyguard/res/values-bg/strings.xml
+++ b/packages/Keyguard/res/values-bg/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Операцията с PUK кода за SIM картата не бе успешна!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Кодът е приет!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Няма покритие."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Бутон за превключване на метода на въвеждане."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Превключване на метода на въвеждане"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Самолетен режим"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"След рестартиране на устройството се изисква фигура"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"След рестартиране на устройството се изисква ПИН код"</string>
diff --git a/packages/Keyguard/res/values-bn-rBD/strings.xml b/packages/Keyguard/res/values-bn-rBD/strings.xml
index 1dd8af8cffd7..8b626876af3a 100644
--- a/packages/Keyguard/res/values-bn-rBD/strings.xml
+++ b/packages/Keyguard/res/values-bn-rBD/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"সিম PUK ক্রিয়াকলাপটি ব্যর্থ হয়েছে!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"কোড স্বীকৃত হয়েছে!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"কোনো পরিষেবা নেই৷"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ইনপুট পদ্ধতির বোতাম পরিবর্তন করুন৷"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ইনপুট পদ্ধতি পাল্টান"</string>
<string name="airplane_mode" msgid="3122107900897202805">"বিমান মোড"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ডিভাইস পুনরায় আরম্ভ করার পর প্যাটার্নের প্রয়োজন হবে"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ডিভাইস পুনরায় আরম্ভ করার পর PIN এর প্রয়োজন হবে"</string>
diff --git a/packages/Keyguard/res/values-bs-rBA/strings.xml b/packages/Keyguard/res/values-bs-rBA/strings.xml
index e4caa9db3731..fdf795c5d65a 100644
--- a/packages/Keyguard/res/values-bs-rBA/strings.xml
+++ b/packages/Keyguard/res/values-bs-rBA/strings.xml
@@ -110,7 +110,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Korištenje PUK-a za SIM nije uspjelo!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kôd je prihvaćen"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nema usluge."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Promijeni dugme za način unosa."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Promijeni način unosa"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Način rada u avionu"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Potreban je uzorak nakon ponovnog pokretanja uređaja"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Potreban je PIN nakon ponovnog pokretanja uređaja"</string>
diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml
index 70e9fd1e5b12..dc8b17891e9d 100644
--- a/packages/Keyguard/res/values-ca/strings.xml
+++ b/packages/Keyguard/res/values-ca/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Hi ha hagut un problema en l\'operació del PUK de la SIM."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"S\'ha acceptat el codi."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sense servei."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botó de canvi del mètode d\'entrada."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Canvia el mètode d\'introducció"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Mode d\'avió"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Cal introduir el patró quan es reinicia el dispositiu"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Cal introduir el PIN quan es reinicia el dispositiu"</string>
diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml
index 96944cf3d33c..cf1dd34e78b1 100644
--- a/packages/Keyguard/res/values-cs/strings.xml
+++ b/packages/Keyguard/res/values-cs/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operace pomocí kódu PUK SIM karty se nezdařila!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kód byl přijat."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Žádný signál."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačítko přepnutí metody zadávání"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Přepnout metodu zadávání"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Režim Letadlo"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Po restartování zařízení je vyžadováno gesto"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Po restartování zařízení je vyžadován kód PIN"</string>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index 5ce1ef0f6033..0af41f526f2f 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK-koden til SIM-kortet blev afvist."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koden blev accepteret."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen dækning."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Skift indtastningsmetode-knappen."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Skift indtastningsmetode"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Flytilstand"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Du skal indtaste et mønster efter genstart af enheden"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Der skal indtaste en pinkode efter genstart af enheden"</string>
diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml
index f1fc198dfd45..269c5c0e1f40 100644
--- a/packages/Keyguard/res/values-de/strings.xml
+++ b/packages/Keyguard/res/values-de/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Fehler beim Entsperren mithilfe des PUK-Codes der SIM-Karte"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code akzeptiert"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Kein Dienst"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Schaltfläche zum Ändern der Eingabemethode"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Eingabemethode wechseln"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Flugmodus"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Nach dem Neustart des Geräts ist die Eingabe des Musters erforderlich."</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Nach dem Neustart des Geräts ist die Eingabe der PIN erforderlich."</string>
diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml
index 535bee868468..be3b3491cf9b 100644
--- a/packages/Keyguard/res/values-el/strings.xml
+++ b/packages/Keyguard/res/values-el/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Αποτυχία λειτουργίας κωδικού PUK κάρτας SIM!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Αποδεκτός κωδικός!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Καμία υπηρεσία."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Κουμπί εναλλαγής μεθόδου εισόδου"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Εναλλαγή μεθόδου εισαγωγής"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Λειτουργία πτήσης"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Απαιτείται μοτίβο μετά την επανεκκίνηση της συσκευής"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Απαιτείται PIN μετά την επανεκκίνηση της συσκευής"</string>
diff --git a/packages/Keyguard/res/values-en-rAU/strings.xml b/packages/Keyguard/res/values-en-rAU/strings.xml
index 63b2137e83a5..e2af2d6268ad 100644
--- a/packages/Keyguard/res/values-en-rAU/strings.xml
+++ b/packages/Keyguard/res/values-en-rAU/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK operation failed!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Switch input method"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Aeroplane mode"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Pattern required after device restarts"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN required after device restarts"</string>
diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml
index 63b2137e83a5..e2af2d6268ad 100644
--- a/packages/Keyguard/res/values-en-rGB/strings.xml
+++ b/packages/Keyguard/res/values-en-rGB/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK operation failed!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Switch input method"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Aeroplane mode"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Pattern required after device restarts"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN required after device restarts"</string>
diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml
index 63b2137e83a5..e2af2d6268ad 100644
--- a/packages/Keyguard/res/values-en-rIN/strings.xml
+++ b/packages/Keyguard/res/values-en-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK operation failed!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepted"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"No service."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Switch input method button."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Switch input method"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Aeroplane mode"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Pattern required after device restarts"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN required after device restarts"</string>
diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml
index cf903eb87a43..6a9b824606ad 100644
--- a/packages/Keyguard/res/values-es-rUS/strings.xml
+++ b/packages/Keyguard/res/values-es-rUS/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Error al desbloquear la tarjeta SIM con el PUK"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sin servicio"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Cambiar método de entrada"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modo de avión"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Se requiere el patrón después de reiniciar el dispositivo"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Se requiere el PIN después de reiniciar el dispositivo"</string>
diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml
index a131cc1b8a9a..9861d2668c38 100644
--- a/packages/Keyguard/res/values-es/strings.xml
+++ b/packages/Keyguard/res/values-es/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Error al intentar desbloquear la tarjeta SIM con el código PUK"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sin servicio"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Botón Cambiar método de entrada"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Cambiar método de introducción"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modo avión"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Debes introducir el patrón después de reiniciar el dispositivo"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Debes introducir el PIN después de reiniciar el dispositivo"</string>
diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml
index 47aadf093135..0a62009469e8 100644
--- a/packages/Keyguard/res/values-et-rEE/strings.xml
+++ b/packages/Keyguard/res/values-et-rEE/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM-i PUK-koodi toiming ebaõnnestus."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kood on õige."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Teenus puudub."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Sisestusmeetodi vahetamise nupp."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Vaheta sisestusmeetodit"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Lennukirežiim"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Pärast seadme taaskäivitamist tuleb sisestada muster"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Pärast seadme taaskäivitamist tuleb sisestada PIN-kood"</string>
diff --git a/packages/Keyguard/res/values-eu-rES/strings.xml b/packages/Keyguard/res/values-eu-rES/strings.xml
index 1c834e99e4e5..351c05a6e38f 100644
--- a/packages/Keyguard/res/values-eu-rES/strings.xml
+++ b/packages/Keyguard/res/values-eu-rES/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM txartelaren PUK eragiketak huts egin du!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kodea onartu da!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Zerbitzurik gabe."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Idazketa-metodoa aldatzeko botoia."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Aldatu idazketa-metodoa"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Hegaldi modua"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Eredua marraztu beharko duzu gailua berrabiarazten denean"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN kodea idatzi beharko duzu gailua berrabiarazten denean"</string>
diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml
index 166e0d92f8fb..b8a87a29c8ba 100644
--- a/packages/Keyguard/res/values-fa/strings.xml
+++ b/packages/Keyguard/res/values-fa/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"‏عملیات PUK سیم کارت ناموفق بود!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"کد پذیرفته شد!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"خدماتی وجود ندارد."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"کلید تغییر روش ورود متن."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"تغییر روش ورودی"</string>
<string name="airplane_mode" msgid="3122107900897202805">"حالت هواپیما"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"بعد از بازنشانی دستگاه باید الگو وارد شود"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"بعد از بازنشانی دستگاه باید پین وارد شود"</string>
diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml
index bba241e340a3..a876351e1691 100644
--- a/packages/Keyguard/res/values-fi/strings.xml
+++ b/packages/Keyguard/res/values-fi/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM-kortin PUK-toiminto epäonnistui!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koodi hyväksytty!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ei yhteyttä."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Syöttötavan vaihtopainike."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Vaihda syöttötapaa."</string>
<string name="airplane_mode" msgid="3122107900897202805">"Lentokonetila"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Kuvio vaaditaan laitteen uudelleenkäynnistyksen jälkeen."</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN-koodi vaaditaan laitteen uudelleenkäynnistyksen jälkeen."</string>
diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml
index 6b63e04fbbb2..e0e06cf1b728 100644
--- a/packages/Keyguard/res/values-fr-rCA/strings.xml
+++ b/packages/Keyguard/res/values-fr-rCA/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Le déverrouillage de la carte SIM par code PUK a échoué."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepté"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Aucun service"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Changer de méthode d\'entrée"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Mode Avion"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Le motif est exigé après le redémarrage de l\'appareil"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Le NIP est exigé après le redémarrage de l\'appareil"</string>
diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml
index 73b9552020e5..eff9e917b08b 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Échec du déverrouillage à l\'aide de la clé PUK de la carte SIM."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code accepté."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Aucun service"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bouton \"Changer le mode de saisie\""</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Changer le mode de saisie"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Mode Avion"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Veuillez saisir le schéma après le redémarrage de l\'appareil."</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Veuillez saisir le code d\'accès après le redémarrage de l\'appareil."</string>
diff --git a/packages/Keyguard/res/values-gl-rES/strings.xml b/packages/Keyguard/res/values-gl-rES/strings.xml
index 05767c9d675e..b27cdad428c3 100644
--- a/packages/Keyguard/res/values-gl-rES/strings.xml
+++ b/packages/Keyguard/res/values-gl-rES/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Erro ao tentar desbloquar a tarxeta SIM co código PUK."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceptado"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Non hai servizo."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Cambiar o botón do método de entrada."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Cambiar de método de entrada"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modo avión"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"É necesario o padrón despois do reinicio do dispositivo"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"É necesario o PIN despois do reinicio do dispositivo"</string>
diff --git a/packages/Keyguard/res/values-gu-rIN/strings.xml b/packages/Keyguard/res/values-gu-rIN/strings.xml
index 1b346a286f73..169bf6e18c16 100644
--- a/packages/Keyguard/res/values-gu-rIN/strings.xml
+++ b/packages/Keyguard/res/values-gu-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK ઓપરેશન નિષ્ફળ થયું!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"કોડ સ્વીકાર્યો!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"કોઈ સેવા ."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ઇનપુટ પદ્ધતિ બટન સ્વિચ કરો."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ઇનપુટ પદ્ધતિ સ્વિચ કરો"</string>
<string name="airplane_mode" msgid="3122107900897202805">"એરપ્લેન મોડ"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ઉપકરણ પુનઃપ્રારંભ થાય તે પછી પેટર્ન જરૂરી છે"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ઉપકરણ પુનઃપ્રારંભ થાય તે પછી PIN જરૂરી છે"</string>
diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml
index 47aefab1dd80..dd9123b9d3dd 100644
--- a/packages/Keyguard/res/values-hi/strings.xml
+++ b/packages/Keyguard/res/values-hi/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"सिम PUK की कार्यवाही विफल रही!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्वीकार किया गया!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"कोई सेवा नहीं."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धति‍ बटन स्विच करें."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"इनपुट पद्धति‍ बदलें"</string>
<string name="airplane_mode" msgid="3122107900897202805">"हवाई जहाज़ मोड"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"डिवाइस के पुनः प्रारंभ होने पर पैटर्न की आवश्यकता होती है"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"डिवाइस के पुनः प्रारंभ होने पर पिन की आवश्यकता होती है"</string>
diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml
index c65db7f660e1..0f3b1ca885fa 100644
--- a/packages/Keyguard/res/values-hr/strings.xml
+++ b/packages/Keyguard/res/values-hr/strings.xml
@@ -110,7 +110,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operacija PUK-a SIM kartice nije uspjela!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kôd je prihvaćen!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nema usluge."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za promjenu načina unosa."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Promjena načina unosa"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Način rada u zrakoplovu"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Nakon ponovnog pokretanja uređaja morate unijeti uzorak"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Nakon ponovnog pokretanja uređaja morate unijeti PIN"</string>
diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml
index 104735d82b6e..7901698e8270 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"A SIM kártya PUK-művelete sikertelen!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kód elfogadva."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nincs szolgáltatás."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Beviteli mód váltása gomb."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Beviteli mód váltása"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Repülős üzemmód"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Az eszköz újraindítását követően meg kell adni a mintát"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Az eszköz újraindítását követően meg kell adni a PIN-kódot"</string>
diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml
index 0c7050891279..e223cb92605f 100644
--- a/packages/Keyguard/res/values-hy-rAM/strings.xml
+++ b/packages/Keyguard/res/values-hy-rAM/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK գործողությունը ձախողվեց:"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Կոդն ընդունվեց:"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ծառայություն չկա:"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Միացնել մուտքագրման եղանակի կոճակը:"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Փոխարկել մուտքագրման եղանակը"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Ինքնաթիռային ռեժիմ"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Սարքը վերագործարկելուց հետո անհրաժեշտ է մուտքագրել նախշը"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Սարքը վերագործարկելուց հետո անհրաժեշտ է մուտքագրել PIN կոդը"</string>
diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml
index b4096465b12f..7a5642ef0590 100644
--- a/packages/Keyguard/res/values-in/strings.xml
+++ b/packages/Keyguard/res/values-in/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operasi PUK SIM gagal!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kode Diterima!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Tidak ada layanan."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tombol beralih metode masukan."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Beralih metode masukan"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Mode pesawat"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Pola diperlukan setelah perangkat dimulai ulang"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN diperlukan setelah perangkat dimulai ulang"</string>
diff --git a/packages/Keyguard/res/values-is-rIS/strings.xml b/packages/Keyguard/res/values-is-rIS/strings.xml
index 53c33f09e455..cece780330a7 100644
--- a/packages/Keyguard/res/values-is-rIS/strings.xml
+++ b/packages/Keyguard/res/values-is-rIS/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK-aðgerð SIM-korts mistókst!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Númer samþykkt!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ekkert símasamband."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Hnappur til að skipta um innsláttaraðferð."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Skipta um innsláttaraðferð"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Flugstilling"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Mynsturs er krafist þegar tækið er endurræst"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN-númers er krafist þegar tækið er endurræst"</string>
diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml
index 6ede2f961ffc..3473863f20be 100644
--- a/packages/Keyguard/res/values-it/strings.xml
+++ b/packages/Keyguard/res/values-it/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operazione con PUK della SIM non riuscita."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Codice accettato."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nessun servizio."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Pulsante per cambiare metodo di immissione."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Cambia metodo di immissione"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modalità aereo"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Sequenza obbligatoria dopo il riavvio del dispositivo"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN obbligatorio dopo il riavvio del dispositivo"</string>
diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml
index 43ff724c1ee2..316fce7db3a8 100644
--- a/packages/Keyguard/res/values-iw/strings.xml
+++ b/packages/Keyguard/res/values-iw/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"‏פעולת קוד ה-PUK של כרטיס ה-SIM נכשלה!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"הקוד התקבל!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"אין קליטה."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"לחצן החלפת שיטת קלט."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"החלפת שיטת קלט"</string>
<string name="airplane_mode" msgid="3122107900897202805">"מצב טיסה"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"יש להזין את קו ביטול הנעילה לאחר הפעלה מחדש של המכשיר"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"‏יש להזין PIN לאחר הפעלה מחדש של המכשיר"</string>
diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml
index 5f1f0405bd0b..c44f2e1fd85e 100644
--- a/packages/Keyguard/res/values-ja/strings.xml
+++ b/packages/Keyguard/res/values-ja/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK操作に失敗しました。"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"コードが承認されました。"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"通信サービスはありません。"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"入力方法の切り替えボタン。"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"入力方法の切り替え"</string>
<string name="airplane_mode" msgid="3122107900897202805">"機内モード"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"端末の再起動後にパターンの入力が必要となります"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"端末の再起動後に PIN の入力が必要となります"</string>
diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml
index 2fdd6686f504..3ceb80a57b10 100644
--- a/packages/Keyguard/res/values-ka-rGE/strings.xml
+++ b/packages/Keyguard/res/values-ka-rGE/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK ოპერაცია ჩაიშალა!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"კოდი მიღებულია!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"არ არის სერვისი."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"შეყვანის მეთოდის გადართვის ღილაკი."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"შეყვანის მეთოდის გადართვა"</string>
<string name="airplane_mode" msgid="3122107900897202805">"თვითმფრინავის რეჟიმი"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"მოწყობილობის გადატვირთვის შემდეგ საჭიროა ნიმუშის შეყვანა"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"მოწყობილობის გადატვირთვის შემდეგ საჭიროა PIN-კოდის შეყვანა"</string>
diff --git a/packages/Keyguard/res/values-kk-rKZ/strings.xml b/packages/Keyguard/res/values-kk-rKZ/strings.xml
index fd5cf930eb6f..517f4e9f75e8 100644
--- a/packages/Keyguard/res/values-kk-rKZ/strings.xml
+++ b/packages/Keyguard/res/values-kk-rKZ/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK жұмысы орындалмады!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код қабылданды!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Қызмет көрсетілмейді."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Енгізу әдісі түймесін ауыстыру."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Енгізу әдісін ауыстыру"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Ұшақ режимі"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Құрылғы қайта іске қосылғаннан кейін өрнекті енгізу қажет"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Құрылғы қайта іске қосылғаннан кейін PIN кодты енгізу қажет"</string>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index 2da83707579d..6afeadff8528 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"បាន​បរាជ័យ​ក្នុង​ការ​ប្រតិបត្តិ​​លេខ​កូដ PUK ស៊ីម!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"បាន​ទទួល​យក​លេខ​កូដ​!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"គ្មាន​សេវា​"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ប្ដូរ​ប៊ូតុង​វិធីសាស្ត្រ​បញ្ចូល។"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ប្ដូរ​វិធីសាស្ត្រ​បញ្ចូល"</string>
<string name="airplane_mode" msgid="3122107900897202805">"របៀបក្នុងយន្តហោះ"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"តម្រូវឲ្យប្រើលំនាំបន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"តម្រូវឲ្យបញ្ចូលកូដ PIN បន្ទាប់ពីឧបករណ៍ចាប់ផ្តើមឡើងវិញ"</string>
diff --git a/packages/Keyguard/res/values-kn-rIN/strings.xml b/packages/Keyguard/res/values-kn-rIN/strings.xml
index 31deb66e2745..7724ef740319 100644
--- a/packages/Keyguard/res/values-kn-rIN/strings.xml
+++ b/packages/Keyguard/res/values-kn-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"ಸಿಮ್‌ PUK ಕಾರ್ಯಾಚರಣೆ ವಿಫಲಗೊಂಡಿದೆ!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ಕೋಡ್ ಅಂಗೀಕೃತವಾಗಿದೆ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ಯಾವುದೇ ಸೇವೆಯಿಲ್ಲ."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ಇನ್‌ಪುಟ್ ವಿಧಾನ ಬದಲಿಸು ಬಟನ್."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ಇನ್‌ಪುಟ್‌‌ ವಿಧಾನ ಬದಲಿಸಿ"</string>
<string name="airplane_mode" msgid="3122107900897202805">"ಏರ್‌ಪ್ಲೇನ್ ಮೋಡ್"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ಸಾಧನ ಮರುಪ್ರಾರಂಭಗೊಂಡ ನಂತರ ಪ್ಯಾಟರ್ನ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ಸಾಧನ ಮರುಪ್ರಾರಂಭಗೊಂಡ ನಂತರ ಪಿನ್ ಅಗತ್ಯವಿರುತ್ತದೆ"</string>
diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml
index 67d6acba7e34..a4860ce27827 100644
--- a/packages/Keyguard/res/values-ko/strings.xml
+++ b/packages/Keyguard/res/values-ko/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK 작업이 실패했습니다."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"코드 승인 완료"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"서비스 불가"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"입력 방법 버튼을 전환합니다."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"입력 방법 전환"</string>
<string name="airplane_mode" msgid="3122107900897202805">"비행기 모드"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"기기가 다시 시작되면 패턴이 필요합니다."</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"기기가 다시 시작되면 PIN이 필요합니다."</string>
diff --git a/packages/Keyguard/res/values-ky-rKG/strings.xml b/packages/Keyguard/res/values-ky-rKG/strings.xml
index 5403c710891a..5089512261ac 100644
--- a/packages/Keyguard/res/values-ky-rKG/strings.xml
+++ b/packages/Keyguard/res/values-ky-rKG/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM-картанын PUK-кодун ачуу кыйрады!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код кабыл алынды!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Байланыш жок."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Киргизүү ыкмасын которуу баскычы."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Киргизүү ыкмасын которуу"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Учак режими"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Түзмөк кайра күйгүзүлгөндөн кийин графикалык ачкыч талап кылынат"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Түзмөк кайра күйгүзүлгөндөн кийин PIN код талап кылынат"</string>
diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml
index e99b22d859c0..0c590087f5fc 100644
--- a/packages/Keyguard/res/values-lo-rLA/strings.xml
+++ b/packages/Keyguard/res/values-lo-rLA/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK ຂອງ SIM ເຮັດວຽກລົ້ມເຫຼວ!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ລະ​ຫັດ​ຖືກຕອບຮັບແລ້ວ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ບໍ່ມີບໍລິການ"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ປຸ່ມສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ສະລັບຮູບແບບການປ້ອນຂໍ້ມູນ"</string>
<string name="airplane_mode" msgid="3122107900897202805">"ໂໝດໃນຍົນ"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ຈຳເປັນຕ້ອງມີແບບຮູບ ຫຼັງຈາກອຸປະກອນເລີ່ມລະບົບໃໝ່"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ຈຳເປັນຕ້ອງມີ PIN ຫຼັງຈາກອຸປະກອນເລີ່ມລະບົບໃໝ່"</string>
diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml
index fd83ece8330b..109adfbc2da0 100644
--- a/packages/Keyguard/res/values-lt/strings.xml
+++ b/packages/Keyguard/res/values-lt/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Nepavyko atlikti SIM kortelės PUK kodo operacijos."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kodas priimtas."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nėra paslaugos."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Perjungti įvesties metodo mygtuką."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Perjungti įvesties metodą"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Lėktuvo režimas"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Iš naujo paleidus įrenginį būtinas atrakinimo piešinys"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Iš naujo paleidus įrenginį būtinas PIN kodas"</string>
diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml
index 5a35912aff7c..bd349d7297d4 100644
--- a/packages/Keyguard/res/values-lv/strings.xml
+++ b/packages/Keyguard/res/values-lv/strings.xml
@@ -110,7 +110,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM kartes PUK koda ievadīšana neizdevās."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kods ir pieņemts!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nav pakalpojuma."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ievades metodes maiņas poga."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Pārslēgt ievades metodi"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Lidojuma režīms"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Pēc ierīces restartēšanas ir jāievada atbloķēšanas kombinācija."</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Pēc ierīces restartēšanas ir jāievada PIN kods."</string>
diff --git a/packages/Keyguard/res/values-mk-rMK/strings.xml b/packages/Keyguard/res/values-mk-rMK/strings.xml
index a1e224d7cdb3..8d110eeb3b08 100644
--- a/packages/Keyguard/res/values-mk-rMK/strings.xml
+++ b/packages/Keyguard/res/values-mk-rMK/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"СИМ картичката не се отклучи со ПУК кодот!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Кодот е прифатен!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Нема услуга."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Копче за префрање метод на внес."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Префрли метод на внесување"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Режим на работа во авион"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Потребна е шема по рестартирање на уредот"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Потребен е ПИН-код по рестартирање на уредот"</string>
diff --git a/packages/Keyguard/res/values-ml-rIN/strings.xml b/packages/Keyguard/res/values-ml-rIN/strings.xml
index 3a898d82d2f6..3a0a1a9dd028 100644
--- a/packages/Keyguard/res/values-ml-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ml-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"സിം PUK പ്രവർത്തനം പരാജയപ്പെട്ടു!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"കോഡ് അംഗികരിച്ചു!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"സേവനമൊന്നുമില്ല."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ടൈപ്പുചെയ്യൽ രീതി ബട്ടൺ മാറുക."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ഇൻപുട്ട് രീതി മാറുക"</string>
<string name="airplane_mode" msgid="3122107900897202805">"ഫ്ലൈറ്റ് മോഡ്"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ഉപകരണം പുനരാരംഭിച്ചതിന് ശേഷം പാറ്റേൺ ആവശ്യമാണ്"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ഉപകരണം പുനരാരംഭിച്ചതിന് ശേഷം പിൻ ആവശ്യമാണ്"</string>
diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml
index 410ec4b3be87..a93164a55d36 100644
--- a/packages/Keyguard/res/values-mn-rMN/strings.xml
+++ b/packages/Keyguard/res/values-mn-rMN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"СИМ ПҮК ажиллуулах амжилтгүй боллоо!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код зөвшөөрөгдлөө!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Үйлчилгээ байхгүй."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Оруулах аргыг сэлгэх товч."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Оролтын аргыг солих"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Нислэгийн горим"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Төхөөрөмжийг дахин эхлүүлсний дараа зурган түгжээ оруулах шаардлагатай"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Төхөөрөмжийг дахин эхлүүлсний дараа PIN оруулах шаардлагатай"</string>
diff --git a/packages/Keyguard/res/values-mr-rIN/strings.xml b/packages/Keyguard/res/values-mr-rIN/strings.xml
index 0418a7b9ea32..e15c4b90341d 100644
--- a/packages/Keyguard/res/values-mr-rIN/strings.xml
+++ b/packages/Keyguard/res/values-mr-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"सिम PUK कार्य अयशस्‍वी झाले!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्‍वीकारला!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"सेवा नाही."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट पद्धत स्‍विच करा बटण."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"इनपुट पद्धत स्विच करा"</string>
<string name="airplane_mode" msgid="3122107900897202805">"विमान मोड"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"डिव्‍हाइस रीस्टार्ट झाल्यावर नमुना आवश्‍यक आहे"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"डिव्‍हाइस रीस्टार्ट झाल्यावर पिन आवश्‍यक आहे"</string>
diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml
index e8c0bab80ac2..42a11ff4d3a4 100644
--- a/packages/Keyguard/res/values-ms-rMY/strings.xml
+++ b/packages/Keyguard/res/values-ms-rMY/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operasi PUK SIM gagal!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod Diterima!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Tiada perkhidmatan."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butang tukar kaedah input."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Tukar kaedah masukan"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Mod Pesawat"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Corak diperlukan setelah peranti dimulakan semula"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN diperlukan setelah peranti dimulakan semula"</string>
diff --git a/packages/Keyguard/res/values-my-rMM/strings.xml b/packages/Keyguard/res/values-my-rMM/strings.xml
index 86c6e78c76bb..f384079f47d5 100644
--- a/packages/Keyguard/res/values-my-rMM/strings.xml
+++ b/packages/Keyguard/res/values-my-rMM/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"ပင်နံပါတ် ပြန်ဖွင့်သည့် ကုဒ် လုပ်ဆောင်မှု မအောင်မြင်ပါ"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ကုဒ်နံပါတ်ကို လက်ခံလိုက်ပါသည်"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ဆားဗစ် မရှိပါ"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ထည့်သွင်းခြင်းခလုတ်အား ပြောင်းခြင်း"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ထည့်သွင်းမှုနည်းလမ်းကို ပြောင်းလဲပါ"</string>
<string name="airplane_mode" msgid="3122107900897202805">"လေယာဉ်ပေါ်သုံးစနစ်"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ကိရိယာကို ပြန်ဖွင့်လျှင် ပုံစံ လိုအပ်ပါသည်"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ကိရိယာကို ပြန်ဖွင့်လျှင် PIN လိုအပ်ပါသည်"</string>
diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml
index a31c52cecb47..210ad18738fc 100644
--- a/packages/Keyguard/res/values-nb/strings.xml
+++ b/packages/Keyguard/res/values-nb/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"PUK-koden for SIM-kortet ble avvist."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koden er godkjent."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen tjeneste."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Bytt knapp for inndatametode."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Bytt inndatametode"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Flymodus"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Du må tegne mønsteret etter at enheten har startet på nytt"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Du må skrive inn PIN-koden etter at enheten har startet på nytt"</string>
diff --git a/packages/Keyguard/res/values-ne-rNP/strings.xml b/packages/Keyguard/res/values-ne-rNP/strings.xml
index 5a3b7ec2f2b0..99d4ff0aa854 100644
--- a/packages/Keyguard/res/values-ne-rNP/strings.xml
+++ b/packages/Keyguard/res/values-ne-rNP/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK राख्‍ने कार्य बिफल भयो!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"कोड स्वीकृत!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"कुनै सेवा छैन।"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"इनपुट विधि बटन स्विच गर्नुहोस्।"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"इनपुट विधिलाई स्विच गर्नुहोस्"</string>
<string name="airplane_mode" msgid="3122107900897202805">"हवाइजहाज मोड"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"यन्त्र पुनः सुरू भएपछि ढाँचा आवश्यक"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"यन्त्र पुनः सुरू भएपछि PIN आवश्यक"</string>
diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml
index 8ded2e8ac788..873a5235088c 100644
--- a/packages/Keyguard/res/values-nl/strings.xml
+++ b/packages/Keyguard/res/values-nl/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Bewerking met pukcode voor simkaart is mislukt."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Code geaccepteerd."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Geen service"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knop voor wijzigen invoermethode."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Invoermethode schakelen"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Vliegtuigmodus"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Patroon vereist nadat het apparaat opnieuw is opgestart"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Pincode vereist nadat het apparaat opnieuw is opgestart"</string>
diff --git a/packages/Keyguard/res/values-pa-rIN/strings.xml b/packages/Keyguard/res/values-pa-rIN/strings.xml
index e867df28df2f..54d10406fadc 100644
--- a/packages/Keyguard/res/values-pa-rIN/strings.xml
+++ b/packages/Keyguard/res/values-pa-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK ਓਪਰੇਸ਼ਨ ਅਸਫਲ!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"ਕੋਡ ਸਵੀਕਾਰ ਕੀਤਾ ਗਿਆ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ਕੋਈ ਸੇਵਾ ਨਹੀਂ।"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ਇਨਪੁਟ ਵਿਧੀ ਬਟਨ ਸਵਿਚ ਕਰੋ।"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ਇਨਪੁੱਟ ਵਿਧੀ ਸਵਿੱਚ ਕਰੋ"</string>
<string name="airplane_mode" msgid="3122107900897202805">"ਏਅਰਪਲੇਨ ਮੋਡ"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ਡੀਵਾਈਸ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਹੋਣ ਤੋਂ ਬਾਅਦ ਪੈਟਰਨ ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ਡੀਵਾਈਸ ਨੂੰ ਮੁੜ-ਚਾਲੂ ਹੋਣ ਤੋਂ ਬਾਅਦ PIN ਦੀ ਲੋੜ ਹੁੰਦੀ ਹੈ"</string>
diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml
index 3bd9caf08ce1..6a2e81aa95e0 100644
--- a/packages/Keyguard/res/values-pl/strings.xml
+++ b/packages/Keyguard/res/values-pl/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operacja z kodem PUK karty SIM nie udała się."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod został zaakceptowany."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Brak usługi."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Przycisk przełączania metody wprowadzania."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Przełącz metodę wprowadzania"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Tryb samolotowy"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Po ponownym uruchomieniu urządzenia wymagany jest wzór"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Po ponownym uruchomieniu urządzenia wymagany jest kod PIN"</string>
diff --git a/packages/Keyguard/res/values-pt-rBR/strings.xml b/packages/Keyguard/res/values-pt-rBR/strings.xml
index 4f1afabc1fae..2d1a7036847e 100644
--- a/packages/Keyguard/res/values-pt-rBR/strings.xml
+++ b/packages/Keyguard/res/values-pt-rBR/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Falha na operação de PUK do SIM."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceito."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sem serviço."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alterar botão do método de entrada."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Alterar o método de entrada"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modo avião"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"O padrão é exigido após a reinicialização do dispositivo"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"O PIN é exigido após a reinicialização do dispositivo"</string>
diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml
index 49c2f16d05fc..5a4973bfa95e 100644
--- a/packages/Keyguard/res/values-pt-rPT/strings.xml
+++ b/packages/Keyguard/res/values-pt-rPT/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Falha ao introduzir o PUK do cartão SIM!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceite!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sem serviço."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alternar botão de método de introdução."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Alternar o método de introdução."</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modo de avião"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"É necessário um padrão após reiniciar o dispositivo"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"É necessário um PIN após reiniciar o dispositivo"</string>
diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml
index 4f1afabc1fae..2d1a7036847e 100644
--- a/packages/Keyguard/res/values-pt/strings.xml
+++ b/packages/Keyguard/res/values-pt/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Falha na operação de PUK do SIM."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Código aceito."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Sem serviço."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Alterar botão do método de entrada."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Alterar o método de entrada"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modo avião"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"O padrão é exigido após a reinicialização do dispositivo"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"O PIN é exigido após a reinicialização do dispositivo"</string>
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index 9ae001531c95..0a5d4fe68ba1 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -110,7 +110,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Deblocarea cu ajutorul codului PUK pentru cardul SIM nu a reușit!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Cod acceptat!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Fără serviciu."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Buton pentru comutarea metodei de introducere."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Comutați metoda de introducere a textului"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Mod Avion"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Modelul este necesar după repornirea dispozitivului"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Codul PIN este necesar după repornirea dispozitivului"</string>
diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml
index 2f0316606b47..d56263a189a3 100644
--- a/packages/Keyguard/res/values-ru/strings.xml
+++ b/packages/Keyguard/res/values-ru/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Не удалось разблокировать SIM-карту"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код принят"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Нет сигнала."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка переключения способа ввода."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Сменить способ ввода"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Режим полета"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"После перезагрузки устройства необходимо ввести графический ключ"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"После перезагрузки устройства необходимо ввести PIN-код"</string>
diff --git a/packages/Keyguard/res/values-si-rLK/strings.xml b/packages/Keyguard/res/values-si-rLK/strings.xml
index 82ef9148ac87..a0170fb5546c 100644
--- a/packages/Keyguard/res/values-si-rLK/strings.xml
+++ b/packages/Keyguard/res/values-si-rLK/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK ක්‍රියාවලිය අපොහොසත් විය!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"කේතය පිළිගැණුනි!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"සේවාව නැත."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ආදාන ක්‍රමය මාරු කිරීමේ බොත්තම."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ආදාන ක්‍රමය මාරු කිරීම"</string>
<string name="airplane_mode" msgid="3122107900897202805">"ගුවන්යානා ප්‍රකාරය"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"උපාංගය නැවත ආරම්භ වූ පසු රටාව අවශ්‍යයි"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"උපාංගය නැවත ආරම්භ වූ පසු PIN අංකය අවශ්‍යයි"</string>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index 72958ce68594..008a7b0d4d12 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operácia kódu PUK SIM karty zlyhala!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kód bol prijatý!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Žiadny signál"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Tlačidlo prepnutia metódy vstupu."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Prepnúť metódu vstupu"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Režim v lietadle"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Po reštartovaní zariadenia musíte zadať bezpečnostný vzor"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Po reštartovaní zariadenia musíte zadať kód PIN"</string>
diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml
index 83a6e4911226..a7cd7ab429ce 100644
--- a/packages/Keyguard/res/values-sl/strings.xml
+++ b/packages/Keyguard/res/values-sl/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Postopek za odklepanje s kodo PUK kartice SIM ni uspel."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koda je sprejeta."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ni storitve."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Gumb za preklop načina vnosa."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Preklop načina vnosa"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Način za letalo"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Po vnovičnem zagonu naprave je treba vnesti vzorec"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Po vnovičnem zagonu naprave je treba vnesti kodo PIN"</string>
diff --git a/packages/Keyguard/res/values-sq-rAL/strings.xml b/packages/Keyguard/res/values-sq-rAL/strings.xml
index 4cd269250d98..870f3bf30a2f 100644
--- a/packages/Keyguard/res/values-sq-rAL/strings.xml
+++ b/packages/Keyguard/res/values-sq-rAL/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Operacioni i PUK-ut të kartës SIM dështoi!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kodi u pranua!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Nuk ka shërbim."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Butoni i metodës së ndërrimit të hyrjeve."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Ndërro metodën e hyrjes"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Modaliteti i aeroplanit"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Kërkohet motivi pas rinisjes së pajisjes"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Kërkohet kodi PIN pas rinisjes së pajisjes"</string>
diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml
index fa6bc096ecf5..20f098eb1948 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -110,7 +110,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Радња са SIM PUK кодом није успела!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Кôд је прихваћен!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Офлајн сте."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Дугме Промени метод уноса."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Промени метод уноса"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Режим рада у авиону"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Треба да унесете шаблон када се уређај поново покрене"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Треба да унесете PIN када се уређај поново покрене"</string>
diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml
index 10b599129998..a77d79ef0e87 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Det gick inte att låsa upp med PUK-koden för SIM-kortet."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Koden godkändes!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ingen tjänst."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Knapp för byte av inmatningsmetod."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Byt inmatningsmetod"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Flygplansläge"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Du måste ange grafiskt lösenord när du startat om enheten"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Du måste ange pinkod när du startat om enheten"</string>
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index 77eaf2a2aaed..8413dad26880 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Utendakazi wa PUK ya SIM umeshindwa!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Msimbo Umekubaliwa!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Hakuna huduma."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Swichi kitufe cha mbinu ingizi."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Badilisha mbinu ya kuingiza data"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Hali ya ndegeni"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Mchoro unahitajika baada ya kuanzisha kifaa upya"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"PIN inahitajika baada ya kifaa kuanzishwa upya"</string>
diff --git a/packages/Keyguard/res/values-ta-rIN/strings.xml b/packages/Keyguard/res/values-ta-rIN/strings.xml
index 5ddad8cc9eb4..e43238f5eeda 100644
--- a/packages/Keyguard/res/values-ta-rIN/strings.xml
+++ b/packages/Keyguard/res/values-ta-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"சிம் PUK செயல்பாடு தோல்வி!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"குறியீடு ஏற்கப்பட்டது!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"சேவை இல்லை."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"உள்ளீட்டு முறையை மாற்றும் பொத்தான்."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"உள்ளீட்டு முறையை மாற்று"</string>
<string name="airplane_mode" msgid="3122107900897202805">"விமானப் பயன்முறை"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"சாதனத்தை மீண்டும் தொடங்கியதும் வடிவத்தை வரைய வேண்டும்"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"சாதனத்தை மீண்டும் தொடங்கியதும் பின்னை உள்ளிட வேண்டும்"</string>
diff --git a/packages/Keyguard/res/values-te-rIN/strings.xml b/packages/Keyguard/res/values-te-rIN/strings.xml
index e10490c46994..7c9b37dd3131 100644
--- a/packages/Keyguard/res/values-te-rIN/strings.xml
+++ b/packages/Keyguard/res/values-te-rIN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"సిమ్ PUK చర్య విఫలమైంది!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"కోడ్ ఆమోదించబడింది!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"సేవ లేదు."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ఇన్‌పుట్ పద్ధతి మార్చే బటన్."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"ఇన్‌పుట్ పద్ధతిని మారుస్తుంది"</string>
<string name="airplane_mode" msgid="3122107900897202805">"ఎయిర్‌ప్లైన్ మోడ్"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"పరికరాన్ని పునఃప్రారంభించిన తర్వాత నమూనా నమోదు చేయడం ఆవశ్యకం"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"పరికరాన్ని పునఃప్రారంభించిన తర్వాత PIN నమోదు చేయడం ఆవశ్యకం"</string>
diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml
index d3fe71e245a8..00c920c12fc3 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"การปลดล็อกด้วย PUK ของซิมล้มเหลว!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"รหัสได้รับการยอมรับ!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"ไม่มีบริการ"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"ปุ่มสลับวิธีการป้อนข้อมูล"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"สลับวิธีการป้อนข้อมูล"</string>
<string name="airplane_mode" msgid="3122107900897202805">"โหมดบนเครื่องบิน"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"ต้องใช้รูปแบบหลังจากอุปกรณ์รีสตาร์ท"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"ต้องระบุ PIN หลังจากอุปกรณ์รีสตาร์ท"</string>
diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml
index 6e6adeced86d..2e428530b4fb 100644
--- a/packages/Keyguard/res/values-tl/strings.xml
+++ b/packages/Keyguard/res/values-tl/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Nabigo ang operasyon ng SIM PUK!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Tinanggap ang Code!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Walang serbisyo."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Ilipat ang button na pamamaraan ng pag-input."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Magpalit ng pamamaraan ng pag-input"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Airplane mode"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Kinakailangan ang pattern pagkatapos mag-restart ng device"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Kinakailangan ang PIN pagkatapos mag-restart ng device"</string>
diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml
index 46c3d008b5a1..484505ac5588 100644
--- a/packages/Keyguard/res/values-tr/strings.xml
+++ b/packages/Keyguard/res/values-tr/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK işlemi başarısız oldu!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod Kabul Edildi!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Hizmet yok."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Giriş yöntemini değiştirme düğmesi."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Giriş yöntemini değiştir"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Uçak modu"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Cihaz yeniden başladıktan sonra desen gerekir"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Cihaz yeniden başladıktan sonra PIN gerekir"</string>
diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml
index c1b742e7f689..c137bf09227c 100644
--- a/packages/Keyguard/res/values-uk/strings.xml
+++ b/packages/Keyguard/res/values-uk/strings.xml
@@ -112,7 +112,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Помилка введення PUK-коду SIM-карти."</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Код прийнято."</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Зв’язку немає."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Кнопка перемикання методу введення."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Змінити метод введення"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Режим польоту"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Після перезавантаження пристрою потрібно ввести ключ"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Після перезавантаження пристрою потрібно ввести PIN-код"</string>
diff --git a/packages/Keyguard/res/values-ur-rPK/strings.xml b/packages/Keyguard/res/values-ur-rPK/strings.xml
index 48986e6f2bf5..d131c34dff02 100644
--- a/packages/Keyguard/res/values-ur-rPK/strings.xml
+++ b/packages/Keyguard/res/values-ur-rPK/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"‏SIM PUK کارروائی ناکام ہو گئی!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"کوڈ قبول کر لیا گیا!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"کوئی سروس نہیں ہے۔"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"اندراج کا طریقہ سوئچ کرنے کا بٹن۔"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"اندراج کا طریقہ سوئچ کریں"</string>
<string name="airplane_mode" msgid="3122107900897202805">"ہوائی جہاز وضع"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"آلہ دوبارہ چالو ہونے کے بعد پیٹرن درکار ہوتا ہے"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"‏آلہ دوبارہ چالو ہونے کے بعد PIN درکار ہوتا ہے"</string>
diff --git a/packages/Keyguard/res/values-uz-rUZ/strings.xml b/packages/Keyguard/res/values-uz-rUZ/strings.xml
index 7e9f50468158..d1e29411b62b 100644
--- a/packages/Keyguard/res/values-uz-rUZ/strings.xml
+++ b/packages/Keyguard/res/values-uz-rUZ/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM karta PUK jarayoni amalga oshmadi!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Kod qabul qilindi!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Aloqa yo‘q."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Kiritish uslubi tugmasini almashtirish."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Matn kiritish usulini o‘zgartirish"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Parvoz rejimi"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Qurilma o‘chirib yoqilgandan so‘ng chizmali kalit talab qilinadi"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Qurilma o‘chirib yoqilgandan so‘ng PIN kod talab qilinadi"</string>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index 6f8110165ae2..4203c946215a 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Thao tác mã PUK của SIM không thành công!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Mã được chấp nhận!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Không có dịch vụ."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Nút chuyển phương thức nhập."</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Chuyển phương thức nhập"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Chế độ trên máy bay"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Yêu cầu hình mở khóa sau khi thiết bị khởi động lại"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Yêu cầu mã PIN sau khi thiết bị khởi động lại"</string>
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index 2c86a7ab0cd3..81666fe76214 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM卡PUK码操作失败!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"代码正确!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"无服务。"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"输入法切换按钮。"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"输入法切换按钮。"</string>
<string name="airplane_mode" msgid="3122107900897202805">"飞行模式"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"重启设备后需要绘制解锁图案"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"重启设备后需要输入 PIN 码"</string>
diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml
index f21dbca6c7f9..e9d120879d31 100644
--- a/packages/Keyguard/res/values-zh-rHK/strings.xml
+++ b/packages/Keyguard/res/values-zh-rHK/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM PUK 碼操作失敗!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"密碼正確!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"沒有服務。"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"切換輸入法"</string>
<string name="airplane_mode" msgid="3122107900897202805">"飛航模式"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"裝置重新啟動後,需要解除上鎖圖案才能使用"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"裝置重新啟動後,需要輸入 PIN 才能使用"</string>
diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml
index 0cb4b16b08fc..36cf9dea161a 100644
--- a/packages/Keyguard/res/values-zh-rTW/strings.xml
+++ b/packages/Keyguard/res/values-zh-rTW/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"SIM 卡 PUK 碼操作失敗!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"密碼正確!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"沒有服務。"</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"切換輸入法按鈕。"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"切換輸入法"</string>
<string name="airplane_mode" msgid="3122107900897202805">"飛航模式"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"裝置重新啟動後需要畫出解鎖圖案"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"裝置重新啟動後需要輸入 PIN 碼"</string>
diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml
index 9e17dba5dfed..68086b2b9706 100644
--- a/packages/Keyguard/res/values-zu/strings.xml
+++ b/packages/Keyguard/res/values-zu/strings.xml
@@ -108,7 +108,7 @@
<string name="kg_password_puk_failed" msgid="2838824369502455984">"Umsebenzi we-PUK ye-SIM wehlulekile!"</string>
<string name="kg_pin_accepted" msgid="1448241673570020097">"Ikhodi yamukelwe!"</string>
<string name="keyguard_carrier_default" msgid="8700650403054042153">"Ayikho isevisi."</string>
- <string name="accessibility_ime_switch_button" msgid="5032926134740456424">"Vula indlela yokungena yenkinobho"</string>
+ <string name="accessibility_ime_switch_button" msgid="2829803408288433429">"Shintsha indlela yokufaka"</string>
<string name="airplane_mode" msgid="3122107900897202805">"Isimo sendiza"</string>
<string name="kg_prompt_reason_restart_pattern" msgid="5519822969283306009">"Iphethini iyadingeka ngemuva kokuqala kabusha kwedivayisi"</string>
<string name="kg_prompt_reason_restart_pin" msgid="4411398237158448198">"Iphinikhodi iyadingeka ngemuva kokuqala kabusha kwedivayisi"</string>
diff --git a/packages/MtpDocumentsProvider/Android.mk b/packages/MtpDocumentsProvider/Android.mk
index b31b0b13ec07..0f945ee8a5e1 100644
--- a/packages/MtpDocumentsProvider/Android.mk
+++ b/packages/MtpDocumentsProvider/Android.mk
@@ -9,5 +9,10 @@ LOCAL_PRIVILEGED_MODULE := true
LOCAL_JNI_SHARED_LIBRARIES := libappfuse_jni
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
+# Only enable asserts on userdebug/eng builds
+ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
+LOCAL_JACK_FLAGS += -D jack.assert.policy=enable
+endif
+
include $(BUILD_PACKAGE)
include $(call all-makefiles-under, $(LOCAL_PATH))
diff --git a/packages/MtpDocumentsProvider/AndroidManifest.xml b/packages/MtpDocumentsProvider/AndroidManifest.xml
index 2dd49ab0782f..843b313db6b1 100644
--- a/packages/MtpDocumentsProvider/AndroidManifest.xml
+++ b/packages/MtpDocumentsProvider/AndroidManifest.xml
@@ -15,10 +15,12 @@
<action android:name="android.content.action.DOCUMENTS_PROVIDER" />
</intent-filter>
</provider>
-
+
<service android:name=".MtpDocumentsService" />
<activity android:name=".ReceiverActivity"
+ android:label="@string/downloads_app_label"
+ android:icon="@mipmap/ic_launcher_download"
android:theme="@android:style/Theme.NoDisplay"
android:screenOrientation="locked"
android:excludeFromRecents="true">
diff --git a/packages/MtpDocumentsProvider/res/mipmap-hdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-hdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..f958bbd3c255
--- /dev/null
+++ b/packages/MtpDocumentsProvider/res/mipmap-hdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-mdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-mdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..f2e937663c2c
--- /dev/null
+++ b/packages/MtpDocumentsProvider/res/mipmap-mdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-xhdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-xhdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..4dc533638757
--- /dev/null
+++ b/packages/MtpDocumentsProvider/res/mipmap-xhdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-xxhdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-xxhdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..8716290969da
--- /dev/null
+++ b/packages/MtpDocumentsProvider/res/mipmap-xxhdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/mipmap-xxxhdpi/ic_launcher_download.png b/packages/MtpDocumentsProvider/res/mipmap-xxxhdpi/ic_launcher_download.png
new file mode 100644
index 000000000000..f5be21991761
--- /dev/null
+++ b/packages/MtpDocumentsProvider/res/mipmap-xxxhdpi/ic_launcher_download.png
Binary files differ
diff --git a/packages/MtpDocumentsProvider/res/values/strings.xml b/packages/MtpDocumentsProvider/res/values/strings.xml
index f3a3fcf0563c..0c1ec509688f 100644
--- a/packages/MtpDocumentsProvider/res/values/strings.xml
+++ b/packages/MtpDocumentsProvider/res/values/strings.xml
@@ -15,8 +15,10 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <!-- Title of the external storage application [CHAR LIMIT=32] -->
- <string name="app_label">Files</string>
+ <!-- App title of MtpDocumentsProvider [CHAR LIMIT=32] -->
+ <string name="app_label">MTP Host</string>
+ <!-- App title of DocumentsUI [CHAR LIMIT=32] -->
+ <string name="downloads_app_label">Downloads</string>
<!-- Name of MTP root shown in UI. Please align the two strings (device
model and storage name) in proper order in the language.
[CHAR LIMIT=32] -->
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
index 0705214b6abd..68f426fa6176 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/DocumentLoader.java
@@ -69,7 +69,8 @@ class DocumentLoader implements AutoCloseable {
*/
synchronized Cursor queryChildDocuments(String[] columnNames, Identifier parent)
throws IOException {
- Preconditions.checkArgument(parent.mDeviceId == mDevice.deviceId);
+ assert parent.mDeviceId == mDevice.deviceId;
+
LoaderTask task = mTaskList.findTask(parent);
if (task == null) {
if (parent.mDocumentId == null) {
@@ -81,11 +82,9 @@ class DocumentLoader implements AutoCloseable {
// 3. startAddingChildDocuemnts.
// 4. stopAddingChildDocuments - It removes the new document added at the step 2,
// because it is not updated between start/stopAddingChildDocuments.
- task = LoaderTask.create(mDatabase, mMtpManager, mDevice.operationsSupported, parent);
- task.fillDocuments(loadDocuments(
- mMtpManager,
- parent.mDeviceId,
- task.getUnloadedObjectHandles(NUM_INITIAL_ENTRIES)));
+ task = new LoaderTask(mMtpManager, mDatabase, mDevice.operationsSupported, parent);
+ task.loadObjectHandles();
+ task.loadObjectInfoList(NUM_INITIAL_ENTRIES);
} else {
// Once remove the existing task in order to add it to the head of the list.
mTaskList.remove(task);
@@ -130,15 +129,11 @@ class DocumentLoader implements AutoCloseable {
Preconditions.checkState(existingTask.getState() != LoaderTask.STATE_LOADING);
mTaskList.remove(existingTask);
}
- try {
- final LoaderTask newTask = LoaderTask.create(
- mDatabase, mMtpManager, mDevice.operationsSupported, identifier);
- mTaskList.addFirst(newTask);
- return newTask;
- } catch (IOException exception) {
- Log.e(MtpDocumentsProvider.TAG, "Failed to create a task for mapping", exception);
- // Continue to release the background thread.
- }
+ final LoaderTask newTask = new LoaderTask(
+ mMtpManager, mDatabase, mDevice.operationsSupported, identifier);
+ newTask.loadObjectHandles();
+ mTaskList.addFirst(newTask);
+ return newTask;
}
mBackgroundThread = null;
@@ -170,24 +165,6 @@ class DocumentLoader implements AutoCloseable {
}
/**
- * Helper method to loads multiple object info.
- */
- private static MtpObjectInfo[] loadDocuments(MtpManager manager, int deviceId, int[] handles)
- throws IOException {
- final ArrayList<MtpObjectInfo> objects = new ArrayList<>();
- for (int i = 0; i < handles.length; i++) {
- final MtpObjectInfo info = manager.getObjectInfo(deviceId, handles[i]);
- if (info == null) {
- Log.e(MtpDocumentsProvider.TAG,
- "Failed to obtain object info handle=" + handles[i]);
- continue;
- }
- objects.add(info);
- }
- return objects.toArray(new MtpObjectInfo[objects.size()]);
- }
-
- /**
* Background thread to fetch object info.
*/
private class BackgroundLoaderThread extends Thread {
@@ -203,21 +180,13 @@ class DocumentLoader implements AutoCloseable {
if (task == null) {
return;
}
- try {
- final MtpObjectInfo[] objectInfos = loadDocuments(
- mMtpManager,
- task.mIdentifier.mDeviceId,
- task.getUnloadedObjectHandles(NUM_LOADING_ENTRIES));
- task.fillDocuments(objectInfos);
- final boolean shouldNotify =
- task.mLastNotified.getTime() <
- new Date().getTime() - NOTIFY_PERIOD_MS ||
- task.getState() != LoaderTask.STATE_LOADING;
- if (shouldNotify) {
- task.notify(mResolver);
- }
- } catch (IOException exception) {
- task.setError(exception);
+ task.loadObjectInfoList(NUM_LOADING_ENTRIES);
+ final boolean shouldNotify =
+ task.mLastNotified.getTime() <
+ new Date().getTime() - NOTIFY_PERIOD_MS ||
+ task.getState() != LoaderTask.STATE_LOADING;
+ if (shouldNotify) {
+ task.notify(mResolver);
}
}
}
@@ -271,43 +240,67 @@ class DocumentLoader implements AutoCloseable {
* Each task is responsible for fetching child documents for the given parent document.
*/
private static class LoaderTask {
- static final int STATE_LOADING = 0;
- static final int STATE_COMPLETED = 1;
- static final int STATE_ERROR = 2;
+ static final int STATE_START = 0;
+ static final int STATE_LOADING = 1;
+ static final int STATE_COMPLETED = 2;
+ static final int STATE_ERROR = 3;
+ final MtpManager mManager;
final MtpDatabase mDatabase;
final int[] mOperationsSupported;
final Identifier mIdentifier;
- final int[] mObjectHandles;
+ int[] mObjectHandles;
+ int mState;
Date mLastNotified;
- int mNumLoaded;
- Exception mError;
-
- LoaderTask(MtpDatabase database, int[] operationsSupported, Identifier identifier,
- int[] objectHandles) {
- Preconditions.checkNotNull(operationsSupported);
- Preconditions.checkNotNull(objectHandles);
+ int mPosition;
+ IOException mError;
+
+ LoaderTask(MtpManager manager, MtpDatabase database, int[] operationsSupported,
+ Identifier identifier) {
+ assert operationsSupported != null;
+ assert identifier.mDocumentType != MtpDatabaseConstants.DOCUMENT_TYPE_DEVICE;
+ mManager = manager;
mDatabase = database;
mOperationsSupported = operationsSupported;
mIdentifier = identifier;
- mObjectHandles = objectHandles;
- mNumLoaded = 0;
+ mObjectHandles = null;
+ mState = STATE_START;
+ mPosition = 0;
mLastNotified = new Date();
}
+ synchronized void loadObjectHandles() {
+ assert mState == STATE_START;
+ int parentHandle = mIdentifier.mObjectHandle;
+ // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
+ // getObjectHandles if we would like to obtain children under the root.
+ if (mIdentifier.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
+ parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
+ }
+ try {
+ mObjectHandles = mManager.getObjectHandles(
+ mIdentifier.mDeviceId, mIdentifier.mStorageId, parentHandle);
+ mState = STATE_LOADING;
+ } catch (IOException error) {
+ mError = error;
+ mState = STATE_ERROR;
+ }
+ }
+
/**
* Returns a cursor that traverses the child document of the parent document handled by the
* task.
* The returned task may have a EXTRA_LOADING flag.
*/
- Cursor createCursor(ContentResolver resolver, String[] columnNames) throws IOException {
+ synchronized Cursor createCursor(ContentResolver resolver, String[] columnNames)
+ throws IOException {
final Bundle extras = new Bundle();
switch (getState()) {
case STATE_LOADING:
extras.putBoolean(DocumentsContract.EXTRA_LOADING, true);
break;
case STATE_ERROR:
- throw new IOException(mError);
+ throw mError;
}
final Cursor cursor =
@@ -319,26 +312,67 @@ class DocumentLoader implements AutoCloseable {
}
/**
- * Returns a state of the task.
+ * Stores object information into database.
*/
- int getState() {
- if (mError != null) {
- return STATE_ERROR;
- } else if (mNumLoaded == mObjectHandles.length) {
- return STATE_COMPLETED;
- } else {
- return STATE_LOADING;
+ void loadObjectInfoList(int count) {
+ synchronized (this) {
+ if (mState != STATE_LOADING) {
+ return;
+ }
+ if (mPosition == 0) {
+ try{
+ mDatabase.getMapper().startAddingDocuments(mIdentifier.mDocumentId);
+ } catch (FileNotFoundException error) {
+ mError = error;
+ mState = STATE_ERROR;
+ return;
+ }
+ }
+ }
+ final ArrayList<MtpObjectInfo> infoList = new ArrayList<>();
+ for (int chunkEnd = mPosition + count;
+ mPosition < mObjectHandles.length && mPosition < chunkEnd;
+ mPosition++) {
+ try {
+ infoList.add(mManager.getObjectInfo(
+ mIdentifier.mDeviceId, mObjectHandles[mPosition]));
+ } catch (IOException error) {
+ Log.e(MtpDocumentsProvider.TAG, "Failed to load object info", error);
+ }
+ }
+ synchronized (this) {
+ try {
+ mDatabase.getMapper().putChildDocuments(
+ mIdentifier.mDeviceId,
+ mIdentifier.mDocumentId,
+ mOperationsSupported,
+ infoList.toArray(new MtpObjectInfo[infoList.size()]));
+ } catch (FileNotFoundException error) {
+ // Looks like the parent document information is removed.
+ // Adding documents has already cancelled in Mapper so we don't need to invoke
+ // stopAddingDocuments.
+ mError = error;
+ mState = STATE_ERROR;
+ return;
+ }
+ if (mPosition >= mObjectHandles.length) {
+ try{
+ mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
+ mState = STATE_COMPLETED;
+ } catch (FileNotFoundException error) {
+ mError = error;
+ mState = STATE_ERROR;
+ return;
+ }
+ }
}
}
/**
- * Obtains object handles that have not been loaded yet.
+ * Returns a state of the task.
*/
- int[] getUnloadedObjectHandles(int count) {
- return Arrays.copyOfRange(
- mObjectHandles,
- mNumLoaded,
- Math.min(mNumLoaded + count, mObjectHandles.length));
+ int getState() {
+ return mState;
}
/**
@@ -349,69 +383,9 @@ class DocumentLoader implements AutoCloseable {
mLastNotified = new Date();
}
- /**
- * Stores object information into database.
- */
- void fillDocuments(MtpObjectInfo[] objectInfoList) {
- if (objectInfoList.length == 0 || getState() != STATE_LOADING) {
- return;
- }
- try{
- if (mNumLoaded == 0) {
- mDatabase.getMapper().startAddingDocuments(mIdentifier.mDocumentId);
- }
- mDatabase.getMapper().putChildDocuments(
- mIdentifier.mDeviceId, mIdentifier.mDocumentId, mOperationsSupported,
- objectInfoList);
- mNumLoaded += objectInfoList.length;
- if (getState() != STATE_LOADING) {
- mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
- }
- } catch (FileNotFoundException exception) {
- setErrorInternal(exception);
- }
- }
-
- /**
- * Marks the loading task as error.
- */
- void setError(Exception error) {
- final int lastState = getState();
- setErrorInternal(error);
- if (lastState == STATE_LOADING) {
- try {
- mDatabase.getMapper().stopAddingDocuments(mIdentifier.mDocumentId);
- } catch (FileNotFoundException exception) {
- setErrorInternal(exception);
- }
- }
- }
-
- private void setErrorInternal(Exception error) {
- Log.e(MtpDocumentsProvider.TAG, "Error in DocumentLoader thread", error);
- mError = error;
- mNumLoaded = 0;
- }
-
private Uri createUri() {
return DocumentsContract.buildChildDocumentsUri(
MtpDocumentsProvider.AUTHORITY, mIdentifier.mDocumentId);
}
-
- /**
- * Creates a LoaderTask that loads children of the given document.
- */
- static LoaderTask create(MtpDatabase database, MtpManager manager,
- int[] operationsSupported, Identifier parent)
- throws IOException {
- int parentHandle = parent.mObjectHandle;
- // Need to pass the special value MtpManager.OBJECT_HANDLE_ROOT_CHILDREN to
- // getObjectHandles if we would like to obtain children under the root.
- if (parent.mDocumentType == MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE) {
- parentHandle = MtpManager.OBJECT_HANDLE_ROOT_CHILDREN;
- }
- return new LoaderTask(database, operationsSupported, parent, manager.getObjectHandles(
- parent.mDeviceId, parent.mStorageId, parentHandle));
- }
}
}
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
index 8c73211cccf1..4564018f5760 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDatabase.java
@@ -617,6 +617,7 @@ class MtpDatabase {
final String whereClosure =
"parent." + COLUMN_DEVICE_ID + " = ? AND " +
"parent." + COLUMN_ROW_STATE + " IN (?, ?) AND " +
+ "parent." + COLUMN_DOCUMENT_TYPE + " != ? AND " +
"child." + COLUMN_ROW_STATE + " = ?";
try (final Cursor cursor = mDatabase.query(
fromClosure,
@@ -626,7 +627,7 @@ class MtpDatabase {
"parent." + Document.COLUMN_DOCUMENT_ID,
"parent." + COLUMN_DOCUMENT_TYPE),
whereClosure,
- strings(deviceId, ROW_STATE_VALID, ROW_STATE_INVALIDATED,
+ strings(deviceId, ROW_STATE_VALID, ROW_STATE_INVALIDATED, DOCUMENT_TYPE_DEVICE,
ROW_STATE_DISCONNECTED),
null,
null,
@@ -750,7 +751,12 @@ class MtpDatabase {
values.putNull(Document.COLUMN_SUMMARY);
values.putNull(Document.COLUMN_LAST_MODIFIED);
values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
- values.put(Document.COLUMN_FLAGS, 0);
+ values.put(Document.COLUMN_FLAGS, getDocumentFlags(
+ device.operationsSupported,
+ Document.MIME_TYPE_DIR,
+ 0,
+ MtpConstants.PROTECTION_STATUS_NONE,
+ DOCUMENT_TYPE_DEVICE));
values.putNull(Document.COLUMN_SIZE);
extraValues.clear();
@@ -765,7 +771,7 @@ class MtpDatabase {
* @param values {@link ContentValues} that receives values.
* @param extraValues {@link ContentValues} that receives extra values for roots.
* @param parentDocumentId Parent document ID.
- * @param supportedOperations Array of Operation code supported by the device.
+ * @param operationsSupported Array of Operation code supported by the device.
* @param root Root to be converted {@link ContentValues}.
*/
static void getStorageDocumentValues(
@@ -786,7 +792,12 @@ class MtpDatabase {
values.putNull(Document.COLUMN_SUMMARY);
values.putNull(Document.COLUMN_LAST_MODIFIED);
values.put(Document.COLUMN_ICON, R.drawable.ic_root_mtp);
- values.put(Document.COLUMN_FLAGS, 0);
+ values.put(Document.COLUMN_FLAGS, getDocumentFlags(
+ operationsSupported,
+ Document.MIME_TYPE_DIR,
+ 0,
+ MtpConstants.PROTECTION_STATUS_NONE,
+ DOCUMENT_TYPE_STORAGE));
values.put(Document.COLUMN_SIZE, root.mMaxCapacity - root.mFreeSpace);
extraValues.put(Root.COLUMN_FLAGS, getRootFlags(operationsSupported));
@@ -803,8 +814,8 @@ class MtpDatabase {
* @param info MTP object info.
*/
static void getObjectDocumentValues(
- ContentValues values, int deviceId, String parentId, int[] operationsSupported,
- MtpObjectInfo info) {
+ ContentValues values, int deviceId, String parentId,
+ int[] operationsSupported, MtpObjectInfo info) {
values.clear();
final String mimeType = getMimeType(info);
values.put(COLUMN_DEVICE_ID, deviceId);
@@ -822,7 +833,7 @@ class MtpDatabase {
values.putNull(Document.COLUMN_ICON);
values.put(Document.COLUMN_FLAGS, getDocumentFlags(
operationsSupported, mimeType, info.getThumbCompressedSizeLong(),
- info.getProtectionStatus()));
+ info.getProtectionStatus(), DOCUMENT_TYPE_OBJECT));
values.put(Document.COLUMN_SIZE, info.getCompressedSizeLong());
}
@@ -861,16 +872,19 @@ class MtpDatabase {
}
private static int getDocumentFlags(
- int[] operationsSupported, String mimeType, long thumbnailSize, int protectionState) {
+ @Nullable int[] operationsSupported, String mimeType, long thumbnailSize,
+ int protectionState, @DocumentType int documentType) {
int flag = 0;
- if (MtpDeviceRecord.isWritingSupported(operationsSupported) &&
+ if (!mimeType.equals(Document.MIME_TYPE_DIR) &&
+ MtpDeviceRecord.isWritingSupported(operationsSupported) &&
protectionState == MtpConstants.PROTECTION_STATUS_NONE) {
flag |= Document.FLAG_SUPPORTS_WRITE;
}
if (MtpDeviceRecord.isSupported(
operationsSupported, MtpConstants.OPERATION_DELETE_OBJECT) &&
(protectionState == MtpConstants.PROTECTION_STATUS_NONE ||
- protectionState == MtpConstants.PROTECTION_STATUS_NON_TRANSFERABLE_DATA)) {
+ protectionState == MtpConstants.PROTECTION_STATUS_NON_TRANSFERABLE_DATA) &&
+ documentType == DOCUMENT_TYPE_OBJECT) {
flag |= Document.FLAG_SUPPORTS_DELETE;
}
if (mimeType.equals(Document.MIME_TYPE_DIR) &&
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
index 68c19923ccb5..cf5bee5d727d 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpDocumentsProvider.java
@@ -360,8 +360,12 @@ public class MtpDocumentsProvider extends DocumentsProvider {
if (i == 0) {
infoUniqueName = info;
} else {
- infoUniqueName = new MtpObjectInfo.Builder(info).setName(
- baseName + " (" + i + ")." + extension).build();
+ String suffixedName = baseName + " (" + i + " )";
+ if (!extension.isEmpty()) {
+ suffixedName += "." + extension;
+ }
+ infoUniqueName =
+ new MtpObjectInfo.Builder(info).setName(suffixedName).build();
}
try {
objectHandle = mMtpManager.createDocument(
diff --git a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
index 6fb2a786be80..0599b701a3b6 100644
--- a/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
+++ b/packages/MtpDocumentsProvider/src/com/android/mtp/MtpManager.java
@@ -130,11 +130,14 @@ class MtpManager {
return devices.toArray(new MtpDeviceRecord[devices.size()]);
}
- MtpObjectInfo getObjectInfo(int deviceId, int objectHandle)
- throws IOException {
+ MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
final MtpDevice device = getDevice(deviceId);
synchronized (device) {
- return device.getObjectInfo(objectHandle);
+ final MtpObjectInfo info = device.getObjectInfo(objectHandle);
+ if (info == null) {
+ throw new IOException("Failed to get object info: " + objectHandle);
+ }
+ return info;
}
}
@@ -291,7 +294,7 @@ class MtpManager {
if (usbInterface.getInterfaceClass() == UsbConstants.USB_SUBCLASS_VENDOR_SPEC &&
usbInterface.getInterfaceSubclass() == SUBCLASS_MTP &&
usbInterface.getInterfaceProtocol() == PROTOCOL_MTP &&
- usbInterface.getName().equals("MTP")) {
+ "MTP".equals(usbInterface.getName())) {
return true;
}
}
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
index db25421afab0..45f89e4e1ffd 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/DocumentLoaderTest.java
@@ -55,13 +55,6 @@ public class DocumentLoaderTest extends AndroidTestCase {
mManager = new BlockableTestMtpManager(getContext());
mResolver = new TestContentResolver();
- mLoader = new DocumentLoader(
- new MtpDeviceRecord(
- 0, "Device", "Key", true, new MtpRoot[0],
- TestUtil.OPERATIONS_SUPPORTED, new int[0]),
- mManager,
- mResolver,
- mDatabase);
}
@Override
@@ -71,6 +64,8 @@ public class DocumentLoaderTest extends AndroidTestCase {
}
public void testBasic() throws Exception {
+ setUpLoader();
+
final Uri uri = DocumentsContract.buildChildDocumentsUri(
MtpDocumentsProvider.AUTHORITY, mParentIdentifier.mDocumentId);
setUpDocument(mManager, 40);
@@ -107,6 +102,55 @@ public class DocumentLoaderTest extends AndroidTestCase {
assertEquals(2, mResolver.getChangeCount(uri));
}
+ public void testError_GetObjectHandles() throws Exception {
+ mManager = new BlockableTestMtpManager(getContext()) {
+ @Override
+ int[] getObjectHandles(int deviceId, int storageId, int parentObjectHandle)
+ throws IOException {
+ throw new IOException();
+ }
+ };
+ setUpLoader();
+ mManager.setObjectHandles(0, 0, MtpManager.OBJECT_HANDLE_ROOT_CHILDREN, null);
+ try {
+ try (final Cursor cursor = mLoader.queryChildDocuments(
+ MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {}
+ fail();
+ } catch (IOException exception) {
+ // Expect exception.
+ }
+ }
+
+ public void testError_GetObjectInfo() throws Exception {
+ mManager = new BlockableTestMtpManager(getContext()) {
+ @Override
+ MtpObjectInfo getObjectInfo(int deviceId, int objectHandle) throws IOException {
+ if (objectHandle == DocumentLoader.NUM_INITIAL_ENTRIES) {
+ throw new IOException();
+ } else {
+ return super.getObjectInfo(deviceId, objectHandle);
+ }
+ }
+ };
+ setUpLoader();
+ setUpDocument(mManager, DocumentLoader.NUM_INITIAL_ENTRIES);
+ try (final Cursor cursor = mLoader.queryChildDocuments(
+ MtpDocumentsProvider.DEFAULT_DOCUMENT_PROJECTION, mParentIdentifier)) {
+ // Even if MtpManager returns an error for a document, loading must complete.
+ assertFalse(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
+ }
+ }
+
+ private void setUpLoader() {
+ mLoader = new DocumentLoader(
+ new MtpDeviceRecord(
+ 0, "Device", "Key", true, new MtpRoot[0],
+ TestUtil.OPERATIONS_SUPPORTED, new int[0]),
+ mManager,
+ mResolver,
+ mDatabase);
+ }
+
private void setUpDocument(TestMtpManager manager, int count) {
int[] childDocuments = new int[count];
for (int i = 0; i < childDocuments.length; i++) {
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
index b74069ae36bb..284223ba9397 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDatabaseTest.java
@@ -103,7 +103,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
assertTrue(isNull(cursor, COLUMN_SUMMARY));
assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
- assertEquals(0, getInt(cursor, COLUMN_FLAGS));
+ assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
assertEquals(1000, getInt(cursor, COLUMN_SIZE));
assertEquals(
MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE,
@@ -165,7 +165,7 @@ public class MtpDatabaseTest extends AndroidTestCase {
assertTrue(isNull(cursor, COLUMN_SUMMARY));
assertTrue(isNull(cursor, COLUMN_LAST_MODIFIED));
assertEquals(R.drawable.ic_root_mtp, getInt(cursor, COLUMN_ICON));
- assertEquals(0, getInt(cursor, COLUMN_FLAGS));
+ assertEquals(Document.FLAG_DIR_SUPPORTS_CREATE, getInt(cursor, COLUMN_FLAGS));
assertEquals(1000, getInt(cursor, COLUMN_SIZE));
assertEquals(
MtpDatabaseConstants.DOCUMENT_TYPE_STORAGE, getInt(cursor, COLUMN_DOCUMENT_TYPE));
diff --git a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
index 9c1880a246a4..da6af37af075 100644
--- a/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
+++ b/packages/MtpDocumentsProvider/tests/src/com/android/mtp/MtpDocumentsProviderTest.java
@@ -351,7 +351,6 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
assertEquals(1422716400000L, cursor.getLong(3));
assertEquals(
DocumentsContract.Document.FLAG_SUPPORTS_DELETE |
- DocumentsContract.Document.FLAG_SUPPORTS_WRITE |
DocumentsContract.Document.FLAG_DIR_SUPPORTS_CREATE,
cursor.getInt(4));
assertEquals(0, cursor.getInt(5));
@@ -419,20 +418,16 @@ public class MtpDocumentsProviderTest extends AndroidTestCase {
try {
mProvider.queryChildDocuments("1", null, null);
fail();
- } catch (Throwable error) {
- assertTrue(error instanceof FileNotFoundException);
- }
+ } catch (FileNotFoundException error) {}
}
public void testQueryChildDocuments_documentError() throws Exception {
setupProvider(MtpDatabaseConstants.FLAG_DATABASE_IN_MEMORY);
setupRoots(0, new MtpRoot[] { new MtpRoot(0, 0, "Storage", 1000, 1000, "") });
mMtpManager.setObjectHandles(0, 0, -1, new int[] { 1 });
- try {
- mProvider.queryChildDocuments("1", null, null);
- fail();
- } catch (Throwable error) {
- assertTrue(error instanceof FileNotFoundException);
+ try (final Cursor cursor = mProvider.queryChildDocuments("1", null, null)) {
+ assertEquals(0, cursor.getCount());
+ assertFalse(cursor.getExtras().getBoolean(DocumentsContract.EXTRA_LOADING));
}
}
diff --git a/packages/PrintSpooler/AndroidManifest.xml b/packages/PrintSpooler/AndroidManifest.xml
index 1bdb6d8bc4a7..2bcd85141015 100644
--- a/packages/PrintSpooler/AndroidManifest.xml
+++ b/packages/PrintSpooler/AndroidManifest.xml
@@ -23,16 +23,12 @@
on the device. Usually an app can access only the print jobs it created. -->
<permission
android:name="com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS"
- android:label="@string/permlab_accessAllPrintJobs"
- android:description="@string/permdesc_accessAllPrintJobs"
android:protectionLevel="signature" />
<!-- May be required by the settings and add printer activities of a
print service if the developer wants only trusted system code to
be able to launch these activities. -->
<permission android:name="android.permission.START_PRINT_SERVICE_CONFIG_ACTIVITY"
- android:label="@string/permlab_startPrintServiceConfigActivity"
- android:description="@string/permdesc_startPrintServiceConfigActivity"
android:protectionLevel="signature" />
<uses-permission android:name="com.android.printspooler.permission.ACCESS_ALL_PRINT_JOBS"/>
diff --git a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
index 1530a02c22fe..1ce3949bbb81 100644
--- a/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
+++ b/packages/PrintSpooler/jni/com_android_printspooler_util_BitmapSerializeUtils.cpp
@@ -50,6 +50,10 @@ static bool readAllBytes(const int fd, void* buffer, const size_t byteCount) {
size_t remainingBytes = byteCount;
while (remainingBytes > 0) {
ssize_t readByteCount = read(fd, readBuffer, remainingBytes);
+
+ remainingBytes -= readByteCount;
+ readBuffer += readByteCount;
+
if (readByteCount == -1) {
if (errno == EINTR) {
continue;
@@ -57,9 +61,12 @@ static bool readAllBytes(const int fd, void* buffer, const size_t byteCount) {
__android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
"Error reading from buffer: %d", errno);
return false;
+ } else if (readByteCount == 0 && remainingBytes > 0) {
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG,
+ "File closed before all bytes were read. %zu/%zu remaining", remainingBytes,
+ byteCount);
+ return false;
}
- remainingBytes -= readByteCount;
- readBuffer += readByteCount;
}
return true;
}
diff --git a/packages/SystemUI/res/layout/recents_history.xml b/packages/PrintSpooler/res/drawable/print_warning.xml
index dc2da7270eb8..35f0fed78a7f 100644
--- a/packages/SystemUI/res/layout/recents_history.xml
+++ b/packages/PrintSpooler/res/drawable/print_warning.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
+<!-- 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.
@@ -13,13 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.systemui.recents.history.RecentsHistoryView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <android.support.v7.widget.RecyclerView
- android:id="@+id/list"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
-</com.android.systemui.recents.history.RecentsHistoryView> \ No newline at end of file
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="96dp"
+ android:height="96dp"
+ android:viewportWidth="96.0"
+ android:viewportHeight="96.0">
+ <path
+ android:fillColor="#C8CCCE"
+ android:pathData="M4,84H92L48,8 4,84zM52,72h-8v-8h8v8zM52,56H44V40h8v16z"/>
+</vector>
diff --git a/packages/PrintSpooler/res/layout/preview_page_error.xml b/packages/PrintSpooler/res/layout/preview_page_error.xml
new file mode 100644
index 000000000000..4e9fb7787010
--- /dev/null
+++ b/packages/PrintSpooler/res/layout/preview_page_error.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="fill_parent"
+ android:layout_height="fill_parent"
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <ImageView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="12dip"
+ android:src="@drawable/print_warning"
+ android:contentDescription="@null" />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginStart="16dip"
+ android:layout_marginEnd="16dip"
+ android:gravity="center_horizontal"
+ android:textColor="@android:color/black"
+ android:text="@string/print_cannot_load_page" />
+
+</LinearLayout>
diff --git a/packages/PrintSpooler/res/values/strings.xml b/packages/PrintSpooler/res/values/strings.xml
index 4b566221e4fa..2f24d2cbd240 100644
--- a/packages/PrintSpooler/res/values/strings.xml
+++ b/packages/PrintSpooler/res/values/strings.xml
@@ -211,9 +211,6 @@
<!-- Label for an unknown reason for failed or blocked print job. [CHAR LIMIT=25] -->
<string name="reason_unknown">unknown</string>
- <!-- Label for a printer that is not available. [CHAR LIMIT=25] -->
- <string name="printer_unavailable"><xliff:g id="print_job_name" example="Canon-123GHT">%1$s</xliff:g> &#8211; unavailable</string>
-
<!-- Title for a warning message about security implications of using a print service,
displayed as a dialog message when the user prints using a print service that has not been
used before. [CHAR LIMIT=NONE] -->
@@ -254,26 +251,6 @@
<item>Landscape</item>
</string-array>
- <!-- Permissions -->
-
- <!-- Title of an application permission, listed so the user can choose whether they want
- to allow the application to do this. -->
- <string name="permlab_accessAllPrintJobs" translatable="false">access all print jobs</string>
- <!-- Description of an application permission, listed so the user can choose whether
- they want to allow the application to do this. -->
- <string name="permdesc_accessAllPrintJobs" translatable="false">Allows the holder to access
- print jobs created by another app. Should never be needed for normal apps.</string>
-
- <!-- Title of an application permission, listed so the user can choose whether they want
- to allow the application to do this. -->
- <string name="permlab_startPrintServiceConfigActivity" translatable="false">start print
- service configuration activities</string>
- <!-- Description of an application permission, listed so the user can choose whether they
- want to allow the application to do this. -->
- <string name="permdesc_startPrintServiceConfigActivity" translatable="false">Allows the
- holder to start the configuration activities of a print service. Should never be needed
- for normal apps.</string>
-
<!-- Error messages -->
<!-- Message for an error when trying to print to a PDF file. [CHAR LIMIT=50] -->
@@ -288,6 +265,10 @@
<!-- Message for the currently selected printer being unavailable. [CHAR LIMIT=100] -->
<string name="print_error_printer_unavailable">This printer isn\'t available right now.</string>
+ <!-- Message for the case when a preview of a page cannot be loaded because the printing app
+ provided a broken print preview rendering for this page. [CHAR LIMIT=50] -->
+ <string name="print_cannot_load_page">Can\'t display preview</string>
+
<!-- Long running operations -->
<!-- Message long running operation when preparing print preview. [CHAR LIMIT=50] -->
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index f8b134300908..bb359176bdf1 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -75,7 +75,7 @@ public final class PageContentRepository {
private int mState;
public interface OnPageContentAvailableCallback {
- public void onPageContentAvailable(BitmapDrawable content);
+ void onPageContentAvailable(BitmapDrawable content);
}
public PageContentRepository(Context context) {
@@ -741,6 +741,7 @@ public final class PageContentRepository {
final RenderSpec mRenderSpec;
OnPageContentAvailableCallback mCallback;
RenderedPage mRenderedPage;
+ private boolean mIsFailed;
public RenderPageTask(int pageIndex, RenderSpec renderSpec,
OnPageContentAvailableCallback callback) {
@@ -826,25 +827,24 @@ public final class PageContentRepository {
Bitmap bitmap = mRenderedPage.content.getBitmap();
- ParcelFileDescriptor[] pipe = null;
+ ParcelFileDescriptor[] pipe;
try {
pipe = ParcelFileDescriptor.createPipe();
- ParcelFileDescriptor source = pipe[0];
- ParcelFileDescriptor destination = pipe[1];
-
- mRenderer.renderPage(mPageIndex, bitmap.getWidth(), bitmap.getHeight(),
- mRenderSpec.printAttributes, destination);
-
- // We passed the file descriptor to the other side which took
- // ownership, so close our copy for the write to complete.
- destination.close();
-
- BitmapSerializeUtils.readBitmapPixels(bitmap, source);
- } catch (IOException|RemoteException e) {
- Log.e(LOG_TAG, "Error rendering page:" + mPageIndex, e);
- } finally {
- IoUtils.closeQuietly(pipe[0]);
- IoUtils.closeQuietly(pipe[1]);
+
+ try (ParcelFileDescriptor source = pipe[0]) {
+ try (ParcelFileDescriptor destination = pipe[1]) {
+
+ mRenderer.renderPage(mPageIndex, bitmap.getWidth(), bitmap.getHeight(),
+ mRenderSpec.printAttributes, destination);
+ }
+
+ BitmapSerializeUtils.readBitmapPixels(bitmap, source);
+ }
+
+ mIsFailed = false;
+ } catch (IOException|RemoteException|IllegalStateException e) {
+ Log.e(LOG_TAG, "Error rendering page " + mPageIndex, e);
+ mIsFailed = true;
}
return mRenderedPage;
@@ -859,15 +859,22 @@ public final class PageContentRepository {
// This task is done.
mPageToRenderTaskMap.remove(mPageIndex);
- // Take a note that the content is rendered.
- renderedPage.state = RenderedPage.STATE_RENDERED;
+ if (mIsFailed) {
+ renderedPage.state = RenderedPage.STATE_SCRAP;
+ } else {
+ renderedPage.state = RenderedPage.STATE_RENDERED;
+ }
// Invalidate all caches of the old state of the bitmap
mRenderedPage.content.invalidateSelf();
// Announce success if needed.
if (mCallback != null) {
- mCallback.onPageContentAvailable(renderedPage.content);
+ if (mIsFailed) {
+ mCallback.onPageContentAvailable(null);
+ } else {
+ mCallback.onPageContentAvailable(renderedPage.content);
+ }
}
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
index 7db207498775..af4c34795917 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/renderer/PdfManipulationService.java
@@ -108,62 +108,65 @@ public final class PdfManipulationService extends Service {
try {
throwIfNotOpened();
- PdfRenderer.Page page = mRenderer.openPage(pageIndex);
+ try (PdfRenderer.Page page = mRenderer.openPage(pageIndex)) {
+ final int srcWidthPts = page.getWidth();
+ final int srcHeightPts = page.getHeight();
- final int srcWidthPts = page.getWidth();
- final int srcHeightPts = page.getHeight();
+ final int dstWidthPts = pointsFromMils(
+ attributes.getMediaSize().getWidthMils());
+ final int dstHeightPts = pointsFromMils(
+ attributes.getMediaSize().getHeightMils());
- final int dstWidthPts = pointsFromMils(
- attributes.getMediaSize().getWidthMils());
- final int dstHeightPts = pointsFromMils(
- attributes.getMediaSize().getHeightMils());
+ final boolean scaleContent = mRenderer.shouldScaleForPrinting();
+ final boolean contentLandscape = !attributes.getMediaSize().isPortrait();
- final boolean scaleContent = mRenderer.shouldScaleForPrinting();
- final boolean contentLandscape = !attributes.getMediaSize().isPortrait();
+ final float displayScale;
+ Matrix matrix = new Matrix();
- final float displayScale;
- Matrix matrix = new Matrix();
-
- if (scaleContent) {
- displayScale = Math.min((float) bitmapWidth / srcWidthPts,
- (float) bitmapHeight / srcHeightPts);
- } else {
- if (contentLandscape) {
- displayScale = (float) bitmapHeight / dstHeightPts;
+ if (scaleContent) {
+ displayScale = Math.min((float) bitmapWidth / srcWidthPts,
+ (float) bitmapHeight / srcHeightPts);
} else {
- displayScale = (float) bitmapWidth / dstWidthPts;
+ if (contentLandscape) {
+ displayScale = (float) bitmapHeight / dstHeightPts;
+ } else {
+ displayScale = (float) bitmapWidth / dstWidthPts;
+ }
}
- }
- matrix.postScale(displayScale, displayScale);
+ matrix.postScale(displayScale, displayScale);
- Configuration configuration = PdfManipulationService.this.getResources()
- .getConfiguration();
- if (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
- matrix.postTranslate(bitmapWidth - srcWidthPts * displayScale, 0);
- }
+ Configuration configuration = PdfManipulationService.this.getResources()
+ .getConfiguration();
+ if (configuration.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL) {
+ matrix.postTranslate(bitmapWidth - srcWidthPts * displayScale, 0);
+ }
- Margins minMargins = attributes.getMinMargins();
- final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils());
- final int paddingTopPts = pointsFromMils(minMargins.getTopMils());
- final int paddingRightPts = pointsFromMils(minMargins.getRightMils());
- final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils());
+ Margins minMargins = attributes.getMinMargins();
+ final int paddingLeftPts = pointsFromMils(minMargins.getLeftMils());
+ final int paddingTopPts = pointsFromMils(minMargins.getTopMils());
+ final int paddingRightPts = pointsFromMils(minMargins.getRightMils());
+ final int paddingBottomPts = pointsFromMils(minMargins.getBottomMils());
- Rect clip = new Rect();
- clip.left = (int) (paddingLeftPts * displayScale);
- clip.top = (int) (paddingTopPts * displayScale);
- clip.right = (int) (bitmapWidth - paddingRightPts * displayScale);
- clip.bottom = (int) (bitmapHeight - paddingBottomPts * displayScale);
+ Rect clip = new Rect();
+ clip.left = (int) (paddingLeftPts * displayScale);
+ clip.top = (int) (paddingTopPts * displayScale);
+ clip.right = (int) (bitmapWidth - paddingRightPts * displayScale);
+ clip.bottom = (int) (bitmapHeight - paddingBottomPts * displayScale);
- if (DEBUG) {
- Log.i(LOG_TAG, "Rendering page:" + pageIndex);
- }
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Rendering page:" + pageIndex);
+ }
- Bitmap bitmap = getBitmapForSize(bitmapWidth, bitmapHeight);
- page.render(bitmap, clip, matrix, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
+ Bitmap bitmap = getBitmapForSize(bitmapWidth, bitmapHeight);
+ page.render(bitmap, clip, matrix, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
- page.close();
+ BitmapSerializeUtils.writeBitmapPixels(bitmap, destination);
+ }
+ } catch (Throwable e) {
+ Log.e(LOG_TAG, "Cannot render page", e);
- BitmapSerializeUtils.writeBitmapPixels(bitmap, destination);
+ // The error is propagated to the caller when it tries to read the bitmap and
+ // the pipe is closed prematurely
} finally {
IoUtils.closeQuietly(destination);
}
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
index 645e182f0a1d..eebb60ce62e0 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PageAdapter.java
@@ -93,6 +93,7 @@ public final class PageAdapter extends Adapter<ViewHolder> {
private PageRange[] mSelectedPages;
private BitmapDrawable mEmptyState;
+ private BitmapDrawable mErrorState;
private int mDocumentPageCount = PrintDocumentInfo.PAGE_COUNT_UNKNOWN;
private int mSelectedPageCount;
@@ -329,7 +330,7 @@ public final class PageAdapter extends Adapter<ViewHolder> {
} else {
onSelectedPageNotInFile(pageInDocument);
}
- content.init(provider, mEmptyState, mMediaSize, mMinMargins);
+ content.init(provider, mEmptyState, mErrorState, mMediaSize, mMinMargins);
if (mConfirmedPagesInDocument.indexOfKey(pageInDocument) >= 0) {
page.setSelected(true, false);
@@ -448,19 +449,35 @@ public final class PageAdapter extends Adapter<ViewHolder> {
// Now update the empty state drawable, as it depends on the page
// size and is reused for all views for better performance.
LayoutInflater inflater = LayoutInflater.from(mContext);
- View content = inflater.inflate(R.layout.preview_page_loading, null, false);
- content.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY),
+ View loadingContent = inflater.inflate(R.layout.preview_page_loading, null, false);
+ loadingContent.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mPageContentHeight, MeasureSpec.EXACTLY));
- content.layout(0, 0, content.getMeasuredWidth(), content.getMeasuredHeight());
+ loadingContent.layout(0, 0, loadingContent.getMeasuredWidth(),
+ loadingContent.getMeasuredHeight());
- Bitmap bitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
+ Bitmap loadingBitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- content.draw(canvas);
+ loadingContent.draw(new Canvas(loadingBitmap));
// Do not recycle the old bitmap if such as it may be set as an empty
// state to any of the page views. Just let the GC take care of it.
- mEmptyState = new BitmapDrawable(mContext.getResources(), bitmap);
+ mEmptyState = new BitmapDrawable(mContext.getResources(), loadingBitmap);
+
+ // Now update the empty state drawable, as it depends on the page
+ // size and is reused for all views for better performance.
+ View errorContent = inflater.inflate(R.layout.preview_page_error, null, false);
+ errorContent.measure(MeasureSpec.makeMeasureSpec(mPageContentWidth, MeasureSpec.EXACTLY),
+ MeasureSpec.makeMeasureSpec(mPageContentHeight, MeasureSpec.EXACTLY));
+ errorContent.layout(0, 0, errorContent.getMeasuredWidth(),
+ errorContent.getMeasuredHeight());
+
+ Bitmap errorBitmap = Bitmap.createBitmap(mPageContentWidth, mPageContentHeight,
+ Bitmap.Config.ARGB_8888);
+ errorContent.draw(new Canvas(errorBitmap));
+
+ // Do not recycle the old bitmap if such as it may be set as an error
+ // state to any of the page views. Just let the GC take care of it.
+ mErrorState = new BitmapDrawable(mContext.getResources(), errorBitmap);
}
private PageRange[] computeSelectedPages() {
@@ -742,7 +759,7 @@ public final class PageAdapter extends Adapter<ViewHolder> {
private void recyclePageView(PageContentView page, int pageIndexInAdapter) {
PageContentProvider provider = page.getPageContentProvider();
if (provider != null) {
- page.init(null, mEmptyState, mMediaSize, mMinMargins);
+ page.init(null, mEmptyState, mErrorState, mMediaSize, mMinMargins);
mPageContentRepository.releasePageContentProvider(provider);
}
mBoundPagesInAdapter.remove(pageIndexInAdapter);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index 4e1180d051bf..bb34fcfdd96b 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -159,7 +159,6 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
private static final int STATE_PRINTER_UNAVAILABLE = 6;
private static final int STATE_UPDATE_SLOW = 7;
private static final int STATE_PRINT_COMPLETED = 8;
- private static final int STATE_FINISHING = 9;
private static final int UI_STATE_PREVIEW = 0;
private static final int UI_STATE_ERROR = 1;
@@ -255,6 +254,9 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
/** Whether at least one print services is enabled or not */
private boolean mArePrintServicesEnabled;
+ /** Is doFinish() already in progress */
+ private boolean mIsFinishing;
+
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -2035,11 +2037,11 @@ public class PrintActivity extends Activity implements RemotePrintDocument.Updat
return;
}
- if (mState == STATE_FINISHING) {
+ if (mIsFinishing) {
return;
}
- mState = STATE_FINISHING;
+ mIsFinishing = true;
if (mPrinterRegistry != null) {
mPrinterRegistry.setTrackedPrinter(null);
diff --git a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
index b79278950eb4..7ef42d149ee6 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/widget/PageContentView.java
@@ -44,8 +44,12 @@ public class PageContentView extends View
private Drawable mEmptyState;
+ private Drawable mErrorState;
+
private boolean mContentRequested;
+ private boolean mIsFailed;
+
public PageContentView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@@ -53,19 +57,26 @@ public class PageContentView extends View
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mContentRequested = false;
+
requestPageContentIfNeeded();
}
@Override
- public void onPageContentAvailable(BitmapDrawable content) {
- setBackground(content);
+ public void onPageContentAvailable(BitmapDrawable renderedPage) {
+ mIsFailed = (renderedPage == null);
+
+ if (mIsFailed) {
+ setBackground(mErrorState);
+ } else {
+ setBackground(renderedPage);
+ }
}
public PageContentProvider getPageContentProvider() {
return mProvider;
}
- public void init(PageContentProvider provider, Drawable emptyState,
+ public void init(PageContentProvider provider, Drawable emptyState, Drawable errorState,
MediaSize mediaSize, Margins minMargins) {
final boolean providerChanged = (mProvider == null)
? provider != null : !mProvider.equals(provider);
@@ -81,17 +92,21 @@ public class PageContentView extends View
return;
}
+ mIsFailed = false;
mProvider = provider;
mMediaSize = mediaSize;
mMinMargins = minMargins;
mEmptyState = emptyState;
+ mErrorState = errorState;
mContentRequested = false;
// If there is no provider we want immediately to switch to
// the empty state, so pages with no content appear blank.
- if (mProvider == null && getBackground() != mEmptyState) {
+ if (mProvider == null) {
setBackground(mEmptyState);
+ } else if (mIsFailed) {
+ setBackground(mErrorState);
}
requestPageContentIfNeeded();
diff --git a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
index 833d8b93b72b..3e3cce09c008 100644
--- a/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
+++ b/packages/SettingsLib/res/values-b+sr+Latn/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokrećite WebView prikazivače u okviru izolovanog procesa."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Primena WebView-a"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Podesite primenu WebView-a"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ovaj izbor više nije važeći. Pokušajte ponovo."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuj u šifrovanje datoteka"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuj..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Već se koristi šifrovanje datoteka"</string>
diff --git a/packages/SettingsLib/res/values-bg/strings.xml b/packages/SettingsLib/res/values-bg/strings.xml
index 4b40f65dffa0..2dbeeacc6893 100644
--- a/packages/SettingsLib/res/values-bg/strings.xml
+++ b/packages/SettingsLib/res/values-bg/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Програми за визуализация на WebView: Изпъл. в изолиран процес."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Внедряване на WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Задаване на внедряването на WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Този избор вече не е валиден. Опитайте отново."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Преобразуване към шифроване на ниво файл"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Преобразуване…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Данните вече са шифровани на ниво файл"</string>
diff --git a/packages/SettingsLib/res/values-bn-rBD/strings.xml b/packages/SettingsLib/res/values-bn-rBD/strings.xml
index f2d781d3e79c..eea4f0652edb 100644
--- a/packages/SettingsLib/res/values-bn-rBD/strings.xml
+++ b/packages/SettingsLib/res/values-bn-rBD/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"একটি বিচ্ছিন্ন প্রক্রিয়ায় ওয়েবভিউ রেন্ডারারগুলি চালান৷"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"ওয়েবভিউ প্রয়োগ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"ওয়েবভিউ প্রয়োগ সেট করুন"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"এই পছন্দটি আর বৈধ নেই৷ আবার চেষ্টা করুন৷"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ফাইল এনক্রিপশান রূপান্তর করুন"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"রূপান্তর করুন..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ফাইল ইতিমধ্যেই এনক্রিপ্ট করা রয়েছে"</string>
diff --git a/packages/SettingsLib/res/values-ca/strings.xml b/packages/SettingsLib/res/values-ca/strings.xml
index c90e4a22584d..8d158ac8e0b5 100644
--- a/packages/SettingsLib/res/values-ca/strings.xml
+++ b/packages/SettingsLib/res/values-ca/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executa els renderitzadors de WebView en un procés aïllat."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementació de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configura la implementació de WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Aquesta opció ja no és vàlida. Torna-ho a provar."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converteix en l\'encriptació de fitxers"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converteix…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"El fitxer ja està encriptat"</string>
diff --git a/packages/SettingsLib/res/values-de/strings.xml b/packages/SettingsLib/res/values-de/strings.xml
index a9b94acec004..67d0198ccd8a 100644
--- a/packages/SettingsLib/res/values-de/strings.xml
+++ b/packages/SettingsLib/res/values-de/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView-Renderer isoliert ausführen."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-Implementierung"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView-Implementierung festlegen"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Diese Auswahl ist nicht mehr gültig. Versuche es erneut."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Zu Dateiverschlüsselung wechseln"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Wechseln…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dateiverschlüsselung wird bereits verwendet."</string>
diff --git a/packages/SettingsLib/res/values-es-rUS/strings.xml b/packages/SettingsLib/res/values-es-rUS/strings.xml
index 3320c58e4dcb..b45753d73a0d 100644
--- a/packages/SettingsLib/res/values-es-rUS/strings.xml
+++ b/packages/SettingsLib/res/values-es-rUS/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ejecutar procesadores de WebView en un proceso aislado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar la implementación de WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Esta opción ya no es válida. Vuelve a intentarlo."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a encriptación de archivo"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está encriptado"</string>
diff --git a/packages/SettingsLib/res/values-es/strings.xml b/packages/SettingsLib/res/values-es/strings.xml
index 5332fc4d9da2..1e360882dcdf 100644
--- a/packages/SettingsLib/res/values-es/strings.xml
+++ b/packages/SettingsLib/res/values-es/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ejecuta procesadores de WebView en un proceso aislado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Establecer implementación de WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Esta opción ya no está disponible. Vuelve a intentarlo."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir a cifrado de archivo"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Ya está cifrado"</string>
diff --git a/packages/SettingsLib/res/values-et-rEE/strings.xml b/packages/SettingsLib/res/values-et-rEE/strings.xml
index b8f4c2b1004e..cb0e7f26cbf7 100644
--- a/packages/SettingsLib/res/values-et-rEE/strings.xml
+++ b/packages/SettingsLib/res/values-et-rEE/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView\' renderdajad käitatakse eraldi protsessis."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView\' rakendamine"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView\' rakendamise seadistamine"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"See valik ei kehti enam. Proovige uuesti."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Teisendamine failikrüpteeringuga andmeteks"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Teisenda …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Juba failikrüpteeringuga"</string>
diff --git a/packages/SettingsLib/res/values-eu-rES/strings.xml b/packages/SettingsLib/res/values-eu-rES/strings.xml
index fe133e14a857..f09949f2d45e 100644
--- a/packages/SettingsLib/res/values-eu-rES/strings.xml
+++ b/packages/SettingsLib/res/values-eu-rES/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exekutatu WebView errendatzaileak prozesu isolatu batean."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView implementation"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Set WebView implementation"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Jada ez dago erabilgarri aukera hori. Saiatu berriro."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Eman fitxategietan oinarritutako enkriptatzea"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Enkriptatu…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Fitxategietan oinarritutako enkriptatzea dauka dagoeneko"</string>
diff --git a/packages/SettingsLib/res/values-fi/strings.xml b/packages/SettingsLib/res/values-fi/strings.xml
index baf26011a6b2..8ec2f6e42ab8 100644
--- a/packages/SettingsLib/res/values-fi/strings.xml
+++ b/packages/SettingsLib/res/values-fi/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Suorita WebView\'n hahmontajat erillisinä prosesseina."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-käyttöönotto"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Määritä WebView-käyttöönotto"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Tämä valinta ei ole enää saatavilla. Yritä uudestaan."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Muunna tiedostojen salaukseksi"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Muunna…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Tiedostot on jo salattu."</string>
diff --git a/packages/SettingsLib/res/values-fr-rCA/strings.xml b/packages/SettingsLib/res/values-fr-rCA/strings.xml
index 91108c7f54aa..e2de25345b87 100644
--- a/packages/SettingsLib/res/values-fr-rCA/strings.xml
+++ b/packages/SettingsLib/res/values-fr-rCA/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Exécuter moteurs de rendu WebView dans un processus isolé."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Mise en œuvre WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Définir la mise en œuvre WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ce choix n\'est plus valide. Réessayez."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Convertir en chiffrement basé sur un fichier"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertir..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Déjà chiffré par un fichier"</string>
diff --git a/packages/SettingsLib/res/values-gl-rES/strings.xml b/packages/SettingsLib/res/values-gl-rES/strings.xml
index 95fe8eaf76fc..e75fee619c4e 100644
--- a/packages/SettingsLib/res/values-gl-rES/strings.xml
+++ b/packages/SettingsLib/res/values-gl-rES/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executa os procesadores de WebView nun proceso illado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementación de WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Definir implementación de WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Esta opción xa non é válida. Téntao de novo."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter no encriptado baseado en ficheiros"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Xa se encriptou o ficheiro"</string>
diff --git a/packages/SettingsLib/res/values-hr/strings.xml b/packages/SettingsLib/res/values-hr/strings.xml
index 53fccd6caad8..7a2acd8fe762 100644
--- a/packages/SettingsLib/res/values-hr/strings.xml
+++ b/packages/SettingsLib/res/values-hr/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Pokreni ispunjivače WebViewa u izoliranim procesima."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacija WebViewa"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Postavi implementaciju WebViewa"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Taj izbor više nije važeći. Pokušajte ponovo."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Pretvori u enkripciju datoteka"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pretvori…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkripcija datoteka već je izvršena"</string>
diff --git a/packages/SettingsLib/res/values-is-rIS/strings.xml b/packages/SettingsLib/res/values-is-rIS/strings.xml
index 511468089754..30440da9b94f 100644
--- a/packages/SettingsLib/res/values-is-rIS/strings.xml
+++ b/packages/SettingsLib/res/values-is-rIS/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Keyra WebView teiknun í lokuðu ferli."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Innleiðing WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Stilla innleiðingu WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Þetta val er ekki lengur gilt. Reyndu aftur."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Umbreyta í dulkóðun skráa"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Umbreyta…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Þegar dulkóðað á grundvelli skráa"</string>
diff --git a/packages/SettingsLib/res/values-it/strings.xml b/packages/SettingsLib/res/values-it/strings.xml
index 7653ecdc9676..40802bca25b9 100644
--- a/packages/SettingsLib/res/values-it/strings.xml
+++ b/packages/SettingsLib/res/values-it/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Esegui renderer WebView in un processo isolato."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementazione di WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Imposta l\'implementazione di WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"La selezione non è più valida. Riprova."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converti in crittografia basata su file"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converti..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Crittografia su base file già eseguita"</string>
diff --git a/packages/SettingsLib/res/values-ja/strings.xml b/packages/SettingsLib/res/values-ja/strings.xml
index 337fc5b90830..e17db519ab29 100644
--- a/packages/SettingsLib/res/values-ja/strings.xml
+++ b/packages/SettingsLib/res/values-ja/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"別個のプロセスで WebView レンダラを実行します。"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView の実装"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView の実装の設定"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"この選択は無効になりました。もう一度お試しください。"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"ファイル暗号化に変換する"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"変換…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ファイルは既に暗号化済みです"</string>
diff --git a/packages/SettingsLib/res/values-lt/strings.xml b/packages/SettingsLib/res/values-lt/strings.xml
index 3589a06682bc..fd245f3b1bdb 100644
--- a/packages/SettingsLib/res/values-lt/strings.xml
+++ b/packages/SettingsLib/res/values-lt/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Paleisti „WebView“ pateikimo priemones vienam procesui."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"„WebView“ diegimas"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"„WebView“ diegimo nustatymas"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Šios parinkties nebegalima pasirinkti. Bandykite dar kartą."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertuoti į failų šifruotę"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertuoti…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau konvertuota į failų šifruotę"</string>
diff --git a/packages/SettingsLib/res/values-lv/strings.xml b/packages/SettingsLib/res/values-lv/strings.xml
index 7fa34eadf8ca..b470fb540194 100644
--- a/packages/SettingsLib/res/values-lv/strings.xml
+++ b/packages/SettingsLib/res/values-lv/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Atsevišķā procesā tiek palaisti WebView renderētāji."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView ieviešana"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Iestatīt WebView ieviešanu"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Šī iespēja vairs nav derīga. Mēģiniet vēlreiz."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Pārvērst par failu šifrējumu"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Pārvērst…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Jau šifrēts failu līmenī"</string>
diff --git a/packages/SettingsLib/res/values-mk-rMK/strings.xml b/packages/SettingsLib/res/values-mk-rMK/strings.xml
index b148ad98dba1..7592cd32e020 100644
--- a/packages/SettingsLib/res/values-mk-rMK/strings.xml
+++ b/packages/SettingsLib/res/values-mk-rMK/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Активирајте ги WebView-прикажувачите во изолиран процес."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Воведување WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Поставете воведување WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Овој избор веќе не важи. Обидете се повторно."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертирајте до шифрирање датотеки"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертирај..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Датотеката е веќе шифрирана"</string>
diff --git a/packages/SettingsLib/res/values-ms-rMY/strings.xml b/packages/SettingsLib/res/values-ms-rMY/strings.xml
index dd01d3337f55..6ba7d201df2a 100644
--- a/packages/SettingsLib/res/values-ms-rMY/strings.xml
+++ b/packages/SettingsLib/res/values-ms-rMY/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Jalankan pemapar WebView dalam proses terpencil."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Pelaksanaan WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Tetapkan pelaksanaan WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Pilihan ini tidak lagi sah. Cuba lagi."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Tukar kepada penyulitan fail"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Tukar..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Sudah disulitkan fail"</string>
diff --git a/packages/SettingsLib/res/values-nb/strings.xml b/packages/SettingsLib/res/values-nb/strings.xml
index 40c9f087731a..de6faf46cdc6 100644
--- a/packages/SettingsLib/res/values-nb/strings.xml
+++ b/packages/SettingsLib/res/values-nb/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Kjør WebView-gjengivelser i en isolert prosess."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView-implementering"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Angi WebView-implementering"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Dette valget er ikke gyldig lenger. Prøv på nytt."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konvertér til kryptert fil"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konvertér …"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Allerede kryptert og lagret som fil"</string>
diff --git a/packages/SettingsLib/res/values-pl/strings.xml b/packages/SettingsLib/res/values-pl/strings.xml
index ad09ea4a10b9..b4c030dc6d8f 100644
--- a/packages/SettingsLib/res/values-pl/strings.xml
+++ b/packages/SettingsLib/res/values-pl/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Uruchom WebView jako izolowany proces."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementacja WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Ustaw implementację WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ta opcja nie jest już obsługiwana. Spróbuj ponownie."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Przekształć na szyfrowanie plików"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Przekształć…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Pliki są już zaszyfrowane"</string>
diff --git a/packages/SettingsLib/res/values-pt-rBR/strings.xml b/packages/SettingsLib/res/values-pt-rBR/strings.xml
index 623b1f8802c3..e76535a1f315 100644
--- a/packages/SettingsLib/res/values-pt-rBR/strings.xml
+++ b/packages/SettingsLib/res/values-pt-rBR/strings.xml
@@ -147,7 +147,7 @@
<string name="enable_adb" msgid="7982306934419797485">"Depuração USB"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Modo de depuração quando o USB estiver conectado"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"Revogar autorizações de depuração USB"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório de bugs"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório do bug"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em inatividade enquanto estiver carregando."</string>
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores de WebView em um processo isolado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Esta opção não é mais válida. Tente novamente."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
diff --git a/packages/SettingsLib/res/values-pt/strings.xml b/packages/SettingsLib/res/values-pt/strings.xml
index 623b1f8802c3..e76535a1f315 100644
--- a/packages/SettingsLib/res/values-pt/strings.xml
+++ b/packages/SettingsLib/res/values-pt/strings.xml
@@ -147,7 +147,7 @@
<string name="enable_adb" msgid="7982306934419797485">"Depuração USB"</string>
<string name="enable_adb_summary" msgid="4881186971746056635">"Modo de depuração quando o USB estiver conectado"</string>
<string name="clear_adb_keys" msgid="4038889221503122743">"Revogar autorizações de depuração USB"</string>
- <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório de bugs"</string>
+ <string name="bugreport_in_power" msgid="7923901846375587241">"Atalho para relatório do bug"</string>
<string name="bugreport_in_power_summary" msgid="1778455732762984579">"Mostrar um botão para gerar relatórios de bugs no menu do botão liga/desliga"</string>
<string name="keep_screen_on" msgid="1146389631208760344">"Permanecer ativo"</string>
<string name="keep_screen_on_summary" msgid="2173114350754293009">"A tela nunca entrará em inatividade enquanto estiver carregando."</string>
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Executar renderizadores de WebView em um processo isolado."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementação do WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Configurar implementação do WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Esta opção não é mais válida. Tente novamente."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Converter para criptografia de arquivos"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Converter..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Já criptografado com base em arquivos"</string>
diff --git a/packages/SettingsLib/res/values-ro/strings.xml b/packages/SettingsLib/res/values-ro/strings.xml
index e16c13463625..5b712d03033d 100644
--- a/packages/SettingsLib/res/values-ro/strings.xml
+++ b/packages/SettingsLib/res/values-ro/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Rulați programele de redare WebView într-un proces izolat."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Implementare WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Setați implementarea WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Această opțiune nu mai este validă. Încercați din nou."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Faceți conversia la criptarea bazată pe sistemul de fișiere"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Convertiți…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Criptarea bazată pe sistemul de fișiere este finalizată"</string>
diff --git a/packages/SettingsLib/res/values-ru/strings.xml b/packages/SettingsLib/res/values-ru/strings.xml
index eeb38b04a7ee..b233c4cb7193 100644
--- a/packages/SettingsLib/res/values-ru/strings.xml
+++ b/packages/SettingsLib/res/values-ru/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Выполнять обработчики WebView в изолированном процессе"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Сервис WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Настройки сервиса WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Вариант недействителен. Повторите попытку."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Переход к шифрованию файлов"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Перейти…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Шифрование файлов уже включено"</string>
diff --git a/packages/SettingsLib/res/values-sq-rAL/strings.xml b/packages/SettingsLib/res/values-sq-rAL/strings.xml
index 3a9494463ca2..0a069de0c521 100644
--- a/packages/SettingsLib/res/values-sq-rAL/strings.xml
+++ b/packages/SettingsLib/res/values-sq-rAL/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Ekzekuto renderizuesit e WebView në një proces të izoluar."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Zbatimi i WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Cakto zbatimin e WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Kjo zgjedhje nuk është më e vlefshme. Provo përsëri."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Konverto në enkriptimin e skedarit"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Konverto..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Enkriptimi i skedarit është kryer tashmë"</string>
diff --git a/packages/SettingsLib/res/values-sr/strings.xml b/packages/SettingsLib/res/values-sr/strings.xml
index e111f0ffdd4e..61a87b51115a 100644
--- a/packages/SettingsLib/res/values-sr/strings.xml
+++ b/packages/SettingsLib/res/values-sr/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Покрећите WebView приказиваче у оквиру изолованог процеса."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Примена WebView-а"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Подесите примену WebView-а"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Овај избор више није важећи. Покушајте поново."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертуј у шифровање датотека"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертуј..."</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Већ се користи шифровање датотека"</string>
diff --git a/packages/SettingsLib/res/values-ta-rIN/strings.xml b/packages/SettingsLib/res/values-ta-rIN/strings.xml
index 3ef51651cd91..d28fe75c9b91 100644
--- a/packages/SettingsLib/res/values-ta-rIN/strings.xml
+++ b/packages/SettingsLib/res/values-ta-rIN/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"தனிப்படுத்தப்பட்ட செயல்முறையில் WebView ரெண்டரர்களை இயக்கு."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView செயல்படுத்தல்"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView செயல்படுத்தலை அமை"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"இனி இந்தத் தேர்வைப் பயன்படுத்த முடியாது. மீண்டும் முயலவும்."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"கோப்பு முறைமையாக்கத்திற்கு மாற்று"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"மாற்று…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"ஏற்கனவே கோப்பு முறைமையாக்கப்பட்டது"</string>
diff --git a/packages/SettingsLib/res/values-tr/strings.xml b/packages/SettingsLib/res/values-tr/strings.xml
index 841e36380334..0a2c654982c7 100644
--- a/packages/SettingsLib/res/values-tr/strings.xml
+++ b/packages/SettingsLib/res/values-tr/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"WebView oluşturucuları yalıtılmış bir işlemde çalıştırın."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView kullanımı"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"WebView kullanımını ayarla"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Bu seçenek artık geçerli değil. Tekrar deneyin."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Dosya şifrelemeye dönüştür"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Dönüştür…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Dosya şifreleme zaten uygulandı"</string>
diff --git a/packages/SettingsLib/res/values-uk/strings.xml b/packages/SettingsLib/res/values-uk/strings.xml
index e94b168b7969..5b88647cbead 100644
--- a/packages/SettingsLib/res/values-uk/strings.xml
+++ b/packages/SettingsLib/res/values-uk/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"Запустити засоби обробки відео WebView окремим процесом."</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"Застосування WebView"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"Налаштувати застосування WebView"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"Ця опція більше не дійсна. Повторіть спробу."</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"Конвертувати в зашифрований файл"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"Конвертація…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"Уже конвертовано в зашифрований файл"</string>
diff --git a/packages/SettingsLib/res/values-ur-rPK/strings.xml b/packages/SettingsLib/res/values-ur-rPK/strings.xml
index 0b92416e528d..e0667360d3f6 100644
--- a/packages/SettingsLib/res/values-ur-rPK/strings.xml
+++ b/packages/SettingsLib/res/values-ur-rPK/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"‏WebView رینڈررز کو ایک علیحدہ پراسیس میں چلائیں۔"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"‏WebView کا نفاذ"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"‏WebView کا نفاذ سیٹ کریں"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"یہ انتخاب اب درست نہیں رہا۔ دوبارہ کوشش کریں۔"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"فائل مرموز کاری میں بدلیں"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"بدلیں…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"فائل پہلے ہی مرموز شدہ ہے"</string>
diff --git a/packages/SettingsLib/res/values-zh-rCN/strings.xml b/packages/SettingsLib/res/values-zh-rCN/strings.xml
index de4fe3373fa3..73cd252cd09a 100644
--- a/packages/SettingsLib/res/values-zh-rCN/strings.xml
+++ b/packages/SettingsLib/res/values-zh-rCN/strings.xml
@@ -278,8 +278,7 @@
<string name="enable_webview_multiprocess_desc" msgid="852226124223847283">"在独立进程中运行 WebView 渲染程序。"</string>
<string name="select_webview_provider_title" msgid="4628592979751918907">"WebView 实现"</string>
<string name="select_webview_provider_dialog_title" msgid="4370551378720004872">"设置 WebView 实现"</string>
- <!-- no translation found for select_webview_provider_toast_text (5466970498308266359) -->
- <skip />
+ <string name="select_webview_provider_toast_text" msgid="5466970498308266359">"此选项已失效,请重试。"</string>
<string name="convert_to_file_encryption" msgid="3060156730651061223">"转换为文件加密"</string>
<string name="convert_to_file_encryption_enabled" msgid="2861258671151428346">"转换…"</string>
<string name="convert_to_file_encryption_done" msgid="7859766358000523953">"文件已加密"</string>
diff --git a/packages/SettingsLib/res/values/strings.xml b/packages/SettingsLib/res/values/strings.xml
index 1aee490593e6..a2a3fd39128b 100644
--- a/packages/SettingsLib/res/values/strings.xml
+++ b/packages/SettingsLib/res/values/strings.xml
@@ -793,4 +793,23 @@
<!-- Label for length of time until battery is charged [CHAR LIMIT=20] -->
<string name="remaining_length_format"><xliff:g name="time" example="3 hours">%1$s</xliff:g> left</string>
+ <!-- Hint text for the IP address -->
+ <string name="wifi_ip_address_hint" translatable="false">192.168.1.128</string>
+ <!-- Hint text for DNS -->
+ <string name="wifi_dns1_hint" translatable="false">8.8.8.8</string>
+ <!-- Hint text for DNS -->
+ <string name="wifi_dns2_hint" translatable="false">8.8.4.4</string>
+ <!-- Hint text for the gateway -->
+ <string name="wifi_gateway_hint" translatable="false">192.168.1.1</string>
+ <!-- Hint text for network prefix length -->
+ <string name="wifi_network_prefix_length_hint" translatable="false">24</string>
+ <!-- HTTP proxy settings. The hint text field for port. -->
+ <string name="proxy_port_hint" translatable="false">8080</string>
+ <!-- HTTP proxy settings. Hint for Proxy-Auto Config URL. -->
+ <string name="proxy_url_hint" translatable="false">https://www.example.com/proxy.pac</string>
+ <!-- HTTP proxy settings. The hint text for proxy exclusion list. -->
+ <string name="proxy_exclusionlist_hint" translatable="false">example.com,mycomp.test.com,localhost</string>
+ <!-- HTTP proxy settings. The hint text field for the hostname. -->
+ <string name="proxy_hostname_hint" translatable="false">proxy.example.com</string>
+
</resources>
diff --git a/packages/Shell/src/com/android/shell/BugreportProgressService.java b/packages/Shell/src/com/android/shell/BugreportProgressService.java
index 7fae0ee6b660..c9582ea1aa51 100644
--- a/packages/Shell/src/com/android/shell/BugreportProgressService.java
+++ b/packages/Shell/src/com/android/shell/BugreportProgressService.java
@@ -149,6 +149,10 @@ public class BugreportProgressService extends Service {
// Passed to Message.obtain() when msg.arg2 is not used.
private static final int UNUSED_ARG2 = -2;
+ // Maximum progress displayed (like 99.00%).
+ private static final int CAPPED_PROGRESS = 9900;
+ private static final int CAPPED_MAX = 10000;
+
/**
* Delay before a screenshot is taken.
* <p>
@@ -427,7 +431,7 @@ public class BugreportProgressService extends Service {
final NumberFormat nf = NumberFormat.getPercentInstance();
nf.setMinimumFractionDigits(2);
nf.setMaximumFractionDigits(2);
- final String percentText = nf.format((double) info.progress / info.max);
+ final String percentageText = nf.format((double) info.progress / info.max);
final Action cancelAction = new Action.Builder(null, mContext.getString(
com.android.internal.R.string.cancel), newCancelIntent(mContext, info)).build();
final Intent infoIntent = new Intent(mContext, BugreportProgressService.class);
@@ -458,7 +462,7 @@ public class BugreportProgressService extends Service {
.setContentTitle(title)
.setTicker(title)
.setContentText(name)
- .setContentInfo(percentText)
+ .setContentInfo(percentageText)
.setProgress(info.max, info.progress, false)
.setOngoing(true)
.setContentIntent(infoPendingIntent)
@@ -472,7 +476,7 @@ public class BugreportProgressService extends Service {
}
if (DEBUG) {
Log.d(TAG, "Sending 'Progress' notification for id " + info.id + "(pid " + info.pid
- + "): " + percentText);
+ + "): " + percentageText);
}
NotificationManager.from(mContext).notify(TAG, info.id, notification);
}
@@ -545,25 +549,47 @@ public class BugreportProgressService extends Service {
}
activeProcesses++;
final String progressKey = DUMPSTATE_PREFIX + pid + PROGRESS_SUFFIX;
- final int progress = SystemProperties.getInt(progressKey, 0);
- if (progress == 0) {
+ info.realProgress = SystemProperties.getInt(progressKey, 0);
+ if (info.realProgress == 0) {
Log.v(TAG, "System property " + progressKey + " is not set yet");
}
- final int max = SystemProperties.getInt(DUMPSTATE_PREFIX + pid + MAX_SUFFIX, 0);
- final boolean maxChanged = max > 0 && max != info.max;
- final boolean progressChanged = progress > 0 && progress != info.progress;
-
- if (progressChanged || maxChanged) {
- if (progressChanged) {
- if (DEBUG) Log.v(TAG, "Updating progress for PID " + pid + "(id: " + id
- + ") from " + info.progress + " to " + progress);
- info.progress = progress;
- }
- if (maxChanged) {
- Log.i(TAG, "Updating max progress for PID " + pid + "(id: " + id
- + ") from " + info.max + " to " + max);
- info.max = max;
+ final String maxKey = DUMPSTATE_PREFIX + pid + MAX_SUFFIX;
+ info.realMax = SystemProperties.getInt(maxKey, info.max);
+ if (info.realMax <= 0 ) {
+ Log.w(TAG, "Property " + maxKey + " is not positive: " + info.max);
+ continue;
+ }
+ /*
+ * Checks whether the progress changed in a way that should be displayed to the user:
+ * - info.progress / info.max represents the displayed progress
+ * - info.realProgress / info.realMax represents the real progress
+ * - since the real progress can decrease, the displayed progress is only updated if it
+ * increases
+ * - the displayed progress is capped at a maximum (like 99%)
+ */
+ final int oldPercentage = (CAPPED_MAX * info.progress) / info.max;
+ int newPercentage = (CAPPED_MAX * info.realProgress) / info.realMax;
+ int max = info.realMax;
+ int progress = info.realProgress;
+
+ if (newPercentage > CAPPED_PROGRESS) {
+ progress = newPercentage = CAPPED_PROGRESS;
+ max = CAPPED_MAX;
+ }
+
+ if (newPercentage > oldPercentage) {
+ if (DEBUG) {
+ if (progress != info.progress) {
+ Log.v(TAG, "Updating progress for PID " + pid + "(id: " + id + ") from "
+ + info.progress + " to " + progress);
+ }
+ if (max != info.max) {
+ Log.v(TAG, "Updating max progress for PID " + pid + "(id: " + id + ") from "
+ + info.max + " to " + max);
+ }
}
+ info.progress = progress;
+ info.max = max;
info.lastUpdate = System.currentTimeMillis();
updateProgress(info);
} else {
@@ -1450,16 +1476,26 @@ public class BugreportProgressService extends Service {
String description;
/**
- * Maximum progress of the bugreport generation.
+ * Maximum progress of the bugreport generation as displayed by the UI.
*/
int max;
/**
- * Current progress of the bugreport generation.
+ * Current progress of the bugreport generation as displayed by the UI.
*/
int progress;
/**
+ * Maximum progress of the bugreport generation as reported by dumpstate.
+ */
+ int realMax;
+
+ /**
+ * Current progress of the bugreport generation as reported by dumpstate.
+ */
+ int realProgress;
+
+ /**
* Time of the last progress update.
*/
long lastUpdate = System.currentTimeMillis();
@@ -1568,10 +1604,12 @@ public class BugreportProgressService extends Service {
@Override
public String toString() {
final float percent = ((float) progress * 100 / max);
+ final float realPercent = ((float) realProgress * 100 / realMax);
return "id: " + id + ", pid: " + pid + ", name: " + name + ", finished: " + finished
+ "\n\ttitle: " + title + "\n\tdescription: " + description
+ "\n\tfile: " + bugreportFile + "\n\tscreenshots: " + screenshotFiles
+ "\n\tprogress: " + progress + "/" + max + " (" + percent + ")"
+ + "\n\treal progress: " + realProgress + "/" + realMax + " (" + realPercent + ")"
+ "\n\tlast_update: " + getFormattedLastUpdate()
+ "\naddingDetailsToZip: " + addingDetailsToZip
+ " addedDetailsToZip: " + addedDetailsToZip;
@@ -1587,6 +1625,8 @@ public class BugreportProgressService extends Service {
description = in.readString();
max = in.readInt();
progress = in.readInt();
+ realMax = in.readInt();
+ realProgress = in.readInt();
lastUpdate = in.readLong();
formattedLastUpdate = in.readString();
bugreportFile = readFile(in);
@@ -1609,6 +1649,8 @@ public class BugreportProgressService extends Service {
dest.writeString(description);
dest.writeInt(max);
dest.writeInt(progress);
+ dest.writeInt(realMax);
+ dest.writeInt(realProgress);
dest.writeLong(lastUpdate);
dest.writeString(getFormattedLastUpdate());
writeFile(dest, bugreportFile);
diff --git a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
index 49759c5f6ee1..814aa8cb8c06 100644
--- a/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
+++ b/packages/Shell/src/com/android/shell/BugreportStorageProvider.java
@@ -56,7 +56,7 @@ public class BugreportStorageProvider extends DocumentsProvider {
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
final RowBuilder row = result.newRow();
row.add(Root.COLUMN_ROOT_ID, DOC_ID_ROOT);
- row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY);
+ row.add(Root.COLUMN_FLAGS, Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED);
row.add(Root.COLUMN_ICON, android.R.mipmap.sym_def_app_icon);
row.add(Root.COLUMN_TITLE, getContext().getString(R.string.bugreport_storage_title));
row.add(Root.COLUMN_DOCUMENT_ID, DOC_ID_ROOT);
diff --git a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
index 17f6f6b5ac89..e1e0c3b448b7 100644
--- a/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
+++ b/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java
@@ -26,6 +26,7 @@ import static com.android.shell.BugreportProgressService.EXTRA_PID;
import static com.android.shell.BugreportProgressService.EXTRA_SCREENSHOT;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_FINISHED;
import static com.android.shell.BugreportProgressService.INTENT_BUGREPORT_STARTED;
+import static com.android.shell.BugreportProgressService.POLLING_FREQUENCY;
import static com.android.shell.BugreportProgressService.SCREENSHOT_DELAY_SECONDS;
import java.io.BufferedOutputStream;
@@ -92,7 +93,7 @@ public class BugreportReceiverTest extends InstrumentationTestCase {
private static final String TAG = "BugreportReceiverTest";
// Timeout for UI operations, in milliseconds.
- private static final int TIMEOUT = (int) BugreportProgressService.POLLING_FREQUENCY * 4;
+ private static final int TIMEOUT = (int) POLLING_FREQUENCY * 4;
// Timeout for when waiting for a screenshot to finish.
private static final int SAFE_SCREENSHOT_DELAY = SCREENSHOT_DELAY_SECONDS + 10;
@@ -190,8 +191,30 @@ public class BugreportReceiverTest extends InstrumentationTestCase {
SystemProperties.set(PROGRESS_PROPERTY, "500");
assertProgressNotification(NAME, nf.format(0.50));
+ SystemProperties.set(PROGRESS_PROPERTY, "950");
+ assertProgressNotification(NAME, nf.format(0.95));
+
+ // Make sure progress never goes back...
SystemProperties.set(MAX_PROPERTY, "2000");
- assertProgressNotification(NAME, nf.format(0.25));
+ Thread.sleep(POLLING_FREQUENCY + DateUtils.SECOND_IN_MILLIS);
+ assertProgressNotification(NAME, nf.format(0.95));
+
+ SystemProperties.set(PROGRESS_PROPERTY, "1000");
+ assertProgressNotification(NAME, nf.format(0.95));
+
+ // ...only forward...
+ SystemProperties.set(PROGRESS_PROPERTY, "1902");
+ assertProgressNotification(NAME, nf.format(0.9510));
+
+ SystemProperties.set(PROGRESS_PROPERTY, "1960");
+ assertProgressNotification(NAME, nf.format(0.98));
+
+ // ...but never more than the capped value.
+ SystemProperties.set(PROGRESS_PROPERTY, "2000");
+ assertProgressNotification(NAME, nf.format(0.99));
+
+ SystemProperties.set(PROGRESS_PROPERTY, "3000");
+ assertProgressNotification(NAME, nf.format(0.99));
Bundle extras =
sendBugreportFinishedAndGetSharedIntent(ID, mPlainTextPath, mScreenshotPath);
diff --git a/packages/Shell/tests/src/com/android/shell/UiBot.java b/packages/Shell/tests/src/com/android/shell/UiBot.java
index 384c3daa51c9..5bfe1a084bc4 100644
--- a/packages/Shell/tests/src/com/android/shell/UiBot.java
+++ b/packages/Shell/tests/src/com/android/shell/UiBot.java
@@ -32,7 +32,7 @@ import static junit.framework.Assert.assertTrue;
final class UiBot {
private static final String TAG = "UiBot";
- private static final String SYSTEMUI_PACKAGED = "com.android.systemui";
+ private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
private final UiDevice mDevice;
private final int mTimeout;
@@ -51,8 +51,8 @@ final class UiBot {
public UiObject getNotification(String text) {
boolean opened = mDevice.openNotification();
Log.v(TAG, "openNotification(): " + opened);
- boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGED)), mTimeout);
- assertTrue("could not get system ui (" + SYSTEMUI_PACKAGED + ")", gotIt);
+ boolean gotIt = mDevice.wait(Until.hasObject(By.pkg(SYSTEMUI_PACKAGE)), mTimeout);
+ assertTrue("could not get system ui (" + SYSTEMUI_PACKAGE + ")", gotIt);
return getObject(text);
}
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 073cf14d8b59..589eac65350b 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -156,6 +156,9 @@
<!-- TV picture-in-picture -->
<uses-permission android:name="android.permission.RECEIVE_MEDIA_RESOURCE_USAGE" />
+ <!-- DND access -->
+ <uses-permission android:name="android.permission.MANAGE_NOTIFICATIONS" />
+
<application
android:name=".SystemUIApplication"
android:persistent="true"
diff --git a/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
deleted file mode 100644
index 7de4460d4bb1..000000000000
--- a/packages/SystemUI/res/anim/recents_from_search_launcher_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, 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.
-*/
--->
-<!-- Recents Activity -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false"
- android:zAdjustment="normal">
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:fillEnabled="true"
- android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/linear"
- android:duration="1"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
deleted file mode 100644
index 23cedf85adf6..000000000000
--- a/packages/SystemUI/res/anim/recents_from_search_launcher_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, 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.
-*/
--->
-<!-- Launcher Activity -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false"
- android:zAdjustment="top">
- <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
- android:fillEnabled="true"
- android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/recents_from_launcher_exit_interpolator"
- android:duration="133"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
deleted file mode 100644
index 657b2164d6f2..000000000000
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_enter.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, 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.
-*/
--->
-<!-- Launcher Activity -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false"
- android:zAdjustment="normal">
- <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
- android:fillEnabled="true"
- android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@interpolator/recents_to_launcher_enter_interpolator"
- android:duration="133"/>
-</set>
diff --git a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
deleted file mode 100644
index 5182cab29ee4..000000000000
--- a/packages/SystemUI/res/anim/recents_to_search_launcher_exit.xml
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-/*
-** Copyright 2012, 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.
-*/
--->
-<!-- Recents Activity -->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
- android:shareInterpolator="false"
- android:zAdjustment="top">
- <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
- android:fillEnabled="true"
- android:fillBefore="true" android:fillAfter="true"
- android:interpolator="@android:interpolator/linear"
- android:duration="1"/>
-</set>
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png b/packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png
new file mode 100644
index 000000000000..73f5116bd71f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_cancel_white_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..0622ddc420e3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..c03ad203f47b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-hdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..bfe2b4a973c6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..5ed0ee8c74f7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..d1811629f417
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land-xxxhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-land/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-land/ic_sysbar_docked.png
new file mode 100755
index 000000000000..236b70afffef
--- /dev/null
+++ b/packages/SystemUI/res/drawable-land/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png b/packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png
new file mode 100644
index 000000000000..787e2593789b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_cancel_white_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..93d1905d8c48
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png b/packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png
new file mode 100644
index 000000000000..6ebbc831605f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_cancel_white_24dp.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..73ddde86cda4
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked.png
new file mode 100755
index 000000000000..1e84732f755a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.png b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.png
index f3be2ee1ecb0..ee3ffde568bc 100644..100755
--- a/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.png
+++ b/packages/SystemUI/res/drawable-xxxhdpi/ic_sysbar_docked.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/hybrid_notification.xml b/packages/SystemUI/res/layout/hybrid_notification.xml
index f6678593084c..476f52b11c0f 100644
--- a/packages/SystemUI/res/layout/hybrid_notification.xml
+++ b/packages/SystemUI/res/layout/hybrid_notification.xml
@@ -21,7 +21,7 @@
android:layout_height="wrap_content"
android:paddingStart="@*android:dimen/notification_content_margin_start"
android:paddingEnd="12dp"
- android:gravity="bottom">
+ android:gravity="bottom|start">
<TextView
android:id="@+id/notification_title"
android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/hybrid_overflow_number.xml b/packages/SystemUI/res/layout/hybrid_overflow_number.xml
new file mode 100644
index 000000000000..f3dde8dcd455
--- /dev/null
+++ b/packages/SystemUI/res/layout/hybrid_overflow_number.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ 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
+ -->
+<TextView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/notification_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textAppearance="@*android:style/TextAppearance.Material.Notification"
+ android:paddingEnd="@*android:dimen/notification_content_margin_end"
+ android:gravity="end"
+ android:singleLine="true"
+ /> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/notification_guts.xml b/packages/SystemUI/res/layout/notification_guts.xml
index 1ab6bf9f22ce..062ae35d2750 100644
--- a/packages/SystemUI/res/layout/notification_guts.xml
+++ b/packages/SystemUI/res/layout/notification_guts.xml
@@ -31,12 +31,12 @@
<!-- header -->
<LinearLayout
android:layout_width="match_parent"
- android:layout_height="30dp"
- android:paddingTop="9dp"
+ android:layout_height="wrap_content"
+ android:paddingTop="14dp"
android:paddingEnd="8dp"
android:id="@+id/notification_guts_header"
android:orientation="horizontal"
- android:layout_gravity="center_vertical|start">
+ android:layout_gravity="start">
<ImageView
android:id="@+id/app_icon"
@@ -64,7 +64,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="4dp"
- android:paddingBottom="16dip"
android:paddingEnd="8dp" >
<RadioButton
android:id="@+id/silent_importance"
@@ -99,7 +98,6 @@
android:orientation="vertical"
android:clickable="false"
android:focusable="false"
- android:paddingBottom="8dip"
android:paddingEnd="8dp"
android:visibility="gone">
<TextView
@@ -166,13 +164,14 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
+ android:paddingTop="16dp"
android:paddingBottom="8dp" >
<TextView
android:id="@+id/more_settings"
android:text="@string/notification_more_settings"
android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_height="36dp"
style="@style/TextAppearance.NotificationGuts.Button"
android:background="@drawable/btn_borderless_rect"
android:gravity="center"
@@ -184,7 +183,7 @@
android:id="@+id/done"
android:text="@string/notification_done"
android:layout_width="wrap_content"
- android:layout_height="48dp"
+ android:layout_height="36dp"
style="@style/TextAppearance.NotificationGuts.Button"
android:background="@drawable/btn_borderless_rect"
android:gravity="center"
diff --git a/packages/SystemUI/res/layout/qs_detail.xml b/packages/SystemUI/res/layout/qs_detail.xml
index 858f48737544..3358a1869bdf 100644
--- a/packages/SystemUI/res/layout/qs_detail.xml
+++ b/packages/SystemUI/res/layout/qs_detail.xml
@@ -17,7 +17,6 @@
<!-- Extends LinearLayout -->
<com.android.systemui.qs.QSDetail
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/qs_detail_background"
@@ -41,7 +40,6 @@
android:background="@color/qs_detail_progress_track"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- systemui:hasOverlappingRendering="false"
/>
<FrameLayout
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 0a9baa0aac09..cb861ec0a6e2 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -184,7 +184,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- systemui:hasOverlappingRendering="false"
/>
<TextView
diff --git a/packages/SystemUI/res/layout/recents_history_clear_all_button.xml b/packages/SystemUI/res/layout/recents_history_clear_all_button.xml
deleted file mode 100644
index 05f0979eaf9a..000000000000
--- a/packages/SystemUI/res/layout/recents_history_clear_all_button.xml
+++ /dev/null
@@ -1,37 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- 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.
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/button"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:gravity="start|center_vertical"
- android:paddingStart="16dp"
- android:paddingEnd="16dp"
- android:paddingTop="14dp"
- android:paddingBottom="14dp"
- android:drawableStart="@drawable/recents_dismiss_all_history"
- android:contentDescription="@string/recents_history_clear_all_button_label"
- android:textSize="14sp"
- android:textColor="#FFFFFF"
- android:textAllCaps="true"
- android:shadowColor="#99000000"
- android:shadowDx="0"
- android:shadowDy="2"
- android:shadowRadius="5"
- android:fontFamily="sans-serif-medium"
- android:background="?android:selectableItemBackground"
- android:visibility="invisible" />
diff --git a/packages/SystemUI/res/layout/recents_history_date.xml b/packages/SystemUI/res/layout/recents_history_date.xml
deleted file mode 100644
index 13c7dbed004b..000000000000
--- a/packages/SystemUI/res/layout/recents_history_date.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<TextView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:paddingStart="4dp"
- android:paddingEnd="4dp"
- android:paddingTop="12dp"
- android:paddingBottom="12dp"
- android:gravity="start"
- android:textSize="14sp"
- android:textColor="#009688"
- android:textAllCaps="true"
- android:fontFamily="sans-serif-medium"
- android:background="?android:selectableItemBackground"
- android:alpha="1" /> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_history_task.xml b/packages/SystemUI/res/layout/recents_history_task.xml
deleted file mode 100644
index e92c24a74bf9..000000000000
--- a/packages/SystemUI/res/layout/recents_history_task.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2015 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-<LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="48dp"
- android:orientation="horizontal"
- android:clickable="true"
- android:focusable="true"
- android:background="?android:selectableItemBackground">
- <ImageView
- android:id="@+id/icon"
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:layout_gravity="center"
- android:layout_marginStart="4dp"
- android:layout_marginEnd="12dp" />
- <TextView
- android:id="@+id/description"
- android:layout_width="0dp"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:layout_gravity="end"
- android:paddingStart="16dp"
- android:gravity="start|center_vertical"
- android:textSize="14sp"
- android:textColor="#FFFFFF"
- android:fontFamily="sans-serif-medium" />
-</LinearLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_on_tv.xml b/packages/SystemUI/res/layout/recents_on_tv.xml
index 567e009d07ee..f0bfebe7ef7c 100644
--- a/packages/SystemUI/res/layout/recents_on_tv.xml
+++ b/packages/SystemUI/res/layout/recents_on_tv.xml
@@ -28,26 +28,21 @@
android:clipChildren="false"
android:clipToPadding="false"
android:descendantFocusability="beforeDescendants"
- android:layout_gravity="center"
- android:gravity="center"
- android:paddingStart="@dimen/recents_tv_grid_row_padding"
- android:paddingEnd="@dimen/recents_tv_grid_row_padding"
+ android:layout_marginTop="@dimen/recents_tv_gird_row_top_margin"
android:focusable="true" />
-
<View
android:id="@+id/pip_shade"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:visibility="invisible"
+ android:visibility="gone"
android:background="#76000000"/>
<!-- Placeholder view to handle key events for PIP when it's focused.
- Size and positions will be adjusted to comply with
- config_pictureInPictureBoundsInRecents -->
+ Size and positions will be adjusted to comply with the PIP bounds -->
<View
android:id="@+id/pip"
android:layout_width="0dp"
android:layout_height="0dp"
- android:visibility="invisible"
+ android:visibility="gone"
android:focusable="true" />
</com.android.systemui.recents.tv.views.RecentsTvView>
diff --git a/packages/SystemUI/res/layout/recents_history_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml
index 538bad1fcf1e..87832616f710 100644
--- a/packages/SystemUI/res/layout/recents_history_button.xml
+++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml
@@ -23,7 +23,7 @@
android:paddingEnd="14dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
- android:text="@string/recents_history_button_label"
+ android:text="@string/recents_stack_action_button_label"
android:textSize="14sp"
android:textColor="#FFFFFF"
android:textAllCaps="true"
diff --git a/packages/SystemUI/res/layout/recents_task_view_header.xml b/packages/SystemUI/res/layout/recents_task_view_header.xml
index fa6575824552..59a2bd90e2b0 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header.xml
@@ -18,7 +18,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/task_view_bar"
android:layout_width="match_parent"
- android:layout_height="@dimen/recents_task_bar_height"
+ android:layout_height="@dimen/recents_task_view_header_height"
android:layout_gravity="top|center_horizontal">
<com.android.systemui.recents.views.FixedSizeImageView
android:id="@+id/icon"
@@ -28,8 +28,8 @@
android:layout_gravity="center_vertical|start"
android:paddingTop="8dp"
android:paddingBottom="8dp"
- android:paddingStart="12dp"
- android:paddingEnd="16dp" />
+ android:paddingStart="16dp"
+ android:paddingEnd="12dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -71,7 +71,7 @@
android:layout_height="@dimen/recents_task_view_header_button_height"
android:layout_marginEnd="@dimen/recents_task_view_header_button_width"
android:layout_gravity="center_vertical|end"
- android:padding="13dp"
+ android:padding="16dp"
android:src="@drawable/star"
android:background="?android:selectableItemBackground"
android:alpha="0"
@@ -81,7 +81,7 @@
android:layout_width="@dimen/recents_task_view_header_button_width"
android:layout_height="@dimen/recents_task_view_header_button_height"
android:layout_gravity="center_vertical|end"
- android:padding="13dp"
+ android:padding="16dp"
android:src="@drawable/recents_dismiss_light"
android:background="?android:selectableItemBackground"
android:alpha="0"
diff --git a/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml b/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
index 1becdab0e39f..433e69e4bd2c 100644
--- a/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
+++ b/packages/SystemUI/res/layout/recents_task_view_header_overlay.xml
@@ -25,8 +25,8 @@
android:layout_gravity="center_vertical|start"
android:paddingTop="8dp"
android:paddingBottom="8dp"
- android:paddingStart="12dp"
- android:paddingEnd="16dp" />
+ android:paddingStart="16dp"
+ android:paddingEnd="12dp" />
<TextView
android:id="@+id/app_title"
android:layout_width="match_parent"
@@ -45,9 +45,9 @@
<com.android.systemui.recents.views.FixedSizeImageView
android:id="@+id/app_info"
android:layout_width="@dimen/recents_task_view_header_button_width"
- android:layout_height="@dimen/recents_task_bar_height"
+ android:layout_height="@dimen/recents_task_view_header_button_height"
android:layout_gravity="center_vertical|end"
- android:padding="13dp"
+ android:padding="16dp"
android:background="?android:selectableItemBackground"
android:src="@drawable/recents_info_light" />
</FrameLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
index 54e97da1471e..766ef602293a 100644
--- a/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
+++ b/packages/SystemUI/res/layout/recents_tv_task_card_view.xml
@@ -21,9 +21,11 @@
android:focusableInTouchMode="true"
android:layout_gravity="center"
android:layout_centerInParent="true"
+ android:orientation="vertical"
android:layoutDirection="ltr">
<LinearLayout
+ android:id="@+id/recents_tv_card"
android:layout_width="@dimen/recents_tv_card_width"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
@@ -66,4 +68,30 @@
android:layout_centerHorizontal="true"
android:layout_below="@id/card_title_text" />
</LinearLayout>
+ <LinearLayout
+ android:id="@+id/card_dismiss"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical"
+ android:layout_gravity="center_horizontal"
+ android:layout_below="@id/recents_tv_card"
+ android:alpha="0.0">
+ <ImageView
+ android:id="@+id/card_dismiss_icon"
+ android:layout_width="@dimen/recents_tv_dismiss_icon_size"
+ android:layout_height="@dimen/recents_tv_dismiss_icon_size"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="@dimen/recents_tv_dismiss_icon_top_margin"
+ android:layout_marginBottom="@dimen/recents_tv_dismiss_icon_bottom_margin"
+ android:src="@drawable/ic_cancel_white_24dp" />
+ <TextView
+ android:id="@+id/card_dismiss_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:textSize="@dimen/recents_tv_dismiss_text_size"
+ android:fontFamily="@string/font_roboto_light"
+ android:textColor="@color/recents_tv_dismiss_text_color"
+ android:text="@string/recents_tv_dismiss"
+ android:layout_gravity="center_horizontal" />
+ </LinearLayout>
</com.android.systemui.recents.tv.views.TaskCardView> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index c634cd61afe1..9df5dbf74609 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -19,7 +19,6 @@
<!-- extends LinearLayout -->
<com.android.systemui.statusbar.SignalClusterView
xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:systemui="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:gravity="center_vertical"
@@ -43,7 +42,6 @@
android:id="@+id/ethernet"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- systemui:hasOverlappingRendering="false"
/>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="@style/DualToneDarkTheme"
@@ -51,7 +49,6 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:alpha="0.0"
- systemui:hasOverlappingRendering="false"
/>
</FrameLayout>
<FrameLayout
@@ -64,7 +61,6 @@
android:id="@+id/wifi_signal"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
- systemui:hasOverlappingRendering="false"
/>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="@style/DualToneDarkTheme"
@@ -72,7 +68,6 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:alpha="0.0"
- systemui:hasOverlappingRendering="false"
/>
</FrameLayout>
<View
@@ -98,7 +93,6 @@
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/stat_sys_no_sims"
- systemui:hasOverlappingRendering="false"
/>
<com.android.systemui.statusbar.AlphaOptimizedImageView
android:theme="@style/DualToneDarkTheme"
@@ -107,7 +101,6 @@
android:layout_width="wrap_content"
android:src="@drawable/stat_sys_no_sims"
android:alpha="0.0"
- systemui:hasOverlappingRendering="false"
/>
</FrameLayout>
<View
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index dd75dbfd47dc..c5cd65ea3cf9 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -177,7 +177,6 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
- systemui:hasOverlappingRendering="false"
/>
<TextView
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index dece11d4852b..d89795617b3a 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ligging deur GPS gestel"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Liggingversoeke aktief"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Verwyder alle kennisgewings."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Kennisgewingsinstellings"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>-instellings"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Die skerm sal outomaties draai."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Wys boaan die kennisgewingslys, verskyn vlugtig op die skerm en laat klank toe"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellings"</string>
<string name="notification_done" msgid="5279426047273930175">"Klaar"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Kleur en voorkoms"</string>
<string name="night_mode" msgid="3540405868248625488">"Nagmodus"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibreer skerm"</string>
diff --git a/packages/SystemUI/res/values-af/strings_tv.xml b/packages/SystemUI/res/values-af/strings_tv.xml
index f595479c6059..391bf7d11378 100644
--- a/packages/SystemUI/res/values-af/strings_tv.xml
+++ b/packages/SystemUI/res/values-af/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Hou "<b>"TUIS"</b>" om PIP te beheer"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Druk en hou die TUIS-knoppie om PIP te beheer"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Het dit"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 80540c3ad59a..4286af0e32f9 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"በ GPS የተዘጋጀ ሥፍራ"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"የአካባቢ ጥያቄዎች ነቅተዋል"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ሁሉንም ማሳወቂያዎች አጽዳ"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"የማሳወቂያ ቅንብሮች"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"የ<xliff:g id="APP_NAME">%s</xliff:g> ቅንብሮች"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ማያ ገጽ በራስ ሰር ይዞራል።"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"በማሳወቂያዎች ዝርዝር አናት ላይ አሳይ፣ ወደ ማያ ገጹ አሳይና ድምፅ ፍቀድ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ተጨማሪ ቅንብሮች"</string>
<string name="notification_done" msgid="5279426047273930175">"ተከናውኗል"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"ቀለም እና መልክ"</string>
<string name="night_mode" msgid="3540405868248625488">"የሌሊት ሁነታ"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ማሳያን ይለኩ"</string>
diff --git a/packages/SystemUI/res/values-am/strings_tv.xml b/packages/SystemUI/res/values-am/strings_tv.xml
index 95e480c3301a..19e27ca31d00 100644
--- a/packages/SystemUI/res/values-am/strings_tv.xml
+++ b/packages/SystemUI/res/values-am/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIPን ለመቆጣጠር "<b>"መነሻ"</b>"ን ይያዙ"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIPን ለመቆጣጠር የመነሻ አዝራሩን ተጭነው ይያዙ"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ገባኝ"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 82f4c215a344..5d859ac341c0 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -240,6 +240,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"‏تم تعيين الموقع بواسطة GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"طلبات الموقع نشطة"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"محو جميع الإشعارات."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"إعدادات الإشعارات"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"إعدادات <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"سيتم تدوير الشاشة تلقائيًا."</string>
@@ -482,6 +484,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"عرض هذا الإشعار بأعلى قائمة الإشعارات وعرضه بسرعة على الشاشة مع السماح بإصدار تنبيه صوتي"</string>
<string name="notification_more_settings" msgid="816306283396553571">"المزيد من الإعدادات"</string>
<string name="notification_done" msgid="5279426047273930175">"تم"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"اللون والمظهر"</string>
<string name="night_mode" msgid="3540405868248625488">"الوضع الليلي"</string>
<string name="calibrate_display" msgid="5974642573432039217">"معايرة الشاشة"</string>
diff --git a/packages/SystemUI/res/values-ar/strings_tv.xml b/packages/SystemUI/res/values-ar/strings_tv.xml
index a54e0ab86aa3..db91b69dc23e 100644
--- a/packages/SystemUI/res/values-ar/strings_tv.xml
+++ b/packages/SystemUI/res/values-ar/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"‏اضغط "<b>"الرئيسية"</b>" للتحكم في PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"‏اضغط مع الاستمرار على زر الشاشة الرئيسية للتحكم في PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"حسنًا"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings.xml b/packages/SystemUI/res/values-az-rAZ/strings.xml
index 8be927767121..ad106f4816c7 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Yer GPS tərəfindən müəyyən edildi"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Məkan sorğuları arxivi"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Bütün bildirişləri sil."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Bildiriş ayarları"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ayarları"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran avtomatik döndəriləcək."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Bildirişlər siyahısında yuxarıda göstərin, ekrana nəzər salın və səsə icazə verin"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Daha çox ayar"</string>
<string name="notification_done" msgid="5279426047273930175">"Hazırdır"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Rəng və görünüş"</string>
<string name="night_mode" msgid="3540405868248625488">"Gecə rejimi"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Ekranı kalibrləyin"</string>
diff --git a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
index b3ac6d403ea0..a7a6c5d9f6ec 100644
--- a/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-az-rAZ/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP idarı etmək üçün "<b>"Əsas səhifəni"</b>" tutub saxlayın"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PİP nəzarət etmək üçün ƏSAS EKRAN düyməni basıb saxlayın"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index dc08feccefc7..edec332199bb 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -237,6 +237,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju je podesio GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Ima aktivnih zahteva za lokaciju"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Obriši sva obaveštenja."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Podešavanja obaveštenja"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Podešavanja za <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran će se automatski rotirati."</string>
@@ -479,6 +481,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Prikazuju se u vrhu liste obaveštenja, nakratko se prikazuju na ekranu i emituju zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Još podešavanja"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
<string name="night_mode" msgid="3540405868248625488">"Noćni režim"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibrišite ekran"</string>
@@ -537,8 +541,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Izaberite dugme za tastaturu"</string>
<string name="preview" msgid="9077832302472282938">"Pregled"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Prevucite da biste dodali pločice"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Prevucite ovde da biste uklonili"</string>
<string name="qs_edit" msgid="2232596095725105230">"Izmeni"</string>
<string name="tuner_time" msgid="6572217313285536011">"Vreme"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
index d78f8d33ea30..a28562716b88 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109"><b>"POČETNI EKRAN"</b>" kont. PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Pritisnite i zadržite dugme POČETNI EKRAN da biste kontrolisali PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Važi"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-be-rBY/strings.xml b/packages/SystemUI/res/values-be-rBY/strings.xml
index cdc266d141bd..e5771d70b343 100644
--- a/packages/SystemUI/res/values-be-rBY/strings.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings.xml
@@ -240,6 +240,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Месца задана праз GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Ёсць актыўныя запыты пра месцазнаходжанне"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Выдалiць усе апавяшчэннi."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Налады апавяшчэнняў"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Налады <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран паварочваецца аўтаматычна."</string>
@@ -482,6 +484,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Паказваць уверсе спіса апавяшчэнняў, хутка паказаць на экране і дазволіць прайграванне гуку"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Дадатковыя налады"</string>
<string name="notification_done" msgid="5279426047273930175">"Гатова"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Колер і выгляд"</string>
<string name="night_mode" msgid="3540405868248625488">"Начны рэжым"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Каліброўка дысплэя"</string>
diff --git a/packages/SystemUI/res/values-be-rBY/strings_tv.xml b/packages/SystemUI/res/values-be-rBY/strings_tv.xml
index 6eb49467a6bb..1c93d249300f 100644
--- a/packages/SystemUI/res/values-be-rBY/strings_tv.xml
+++ b/packages/SystemUI/res/values-be-rBY/strings_tv.xml
@@ -29,4 +29,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Утрым. "<b>"HOME"</b>" для кір. PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Націсніце і ўтрымлівайце кнопку HOME для кіравання PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Зразумела"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 08a7b5c39658..6c65f9f1cc3c 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Местоположението е зададено от GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Активни заявки за местоположение"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Изчистване на всички известия."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Настройки за известия"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Настройки за <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранът ще се завърта автоматично."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Показване най-горе в списъка с известия, както и на екрана и разрешаване на звуков сигнал"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Още настройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Цвят и облик"</string>
<string name="night_mode" msgid="3540405868248625488">"Нощен режим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Калибриране на дисплея"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Избиране на клавиш от клавиатурата"</string>
<string name="preview" msgid="9077832302472282938">"Визуализация"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Преместете с плъзгане, за да добавите плочки"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Преместете тук с плъзгане за премахване"</string>
<string name="qs_edit" msgid="2232596095725105230">"Редактиране"</string>
<string name="tuner_time" msgid="6572217313285536011">"Час"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-bg/strings_tv.xml b/packages/SystemUI/res/values-bg/strings_tv.xml
index c5230a48749a..9926ef8e6954 100644
--- a/packages/SystemUI/res/values-bg/strings_tv.xml
+++ b/packages/SystemUI/res/values-bg/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Контр. на PIP: Задр. "<b>"HOME"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"За контролиране на PIP натиснете и задръжте бутона „HOME“"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрах"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bn-rBD/strings.xml b/packages/SystemUI/res/values-bn-rBD/strings.xml
index e39ece9cb068..446d4afa88fd 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS এর দ্বারা সেট করা অবস্থান"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"অবস্থান অনুরোধ সক্রিয় রয়েছে"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"সমস্ত বিজ্ঞপ্তি সাফ করুন৷"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"বিজ্ঞপ্তির সেটিংস"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> সেটিংস"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"স্ক্রীন স্বয়ংক্রিয়ভাবে ঘুরে যাবে৷"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"বিজ্ঞপ্তি তালিকার শীর্ষে দেখানো হয় এবং স্ক্রীনের উপরে প্রদর্শিত এবং শব্দ করার মঞ্জুরি দেয়"</string>
<string name="notification_more_settings" msgid="816306283396553571">"আরো সেটিংস"</string>
<string name="notification_done" msgid="5279426047273930175">"সম্পন্ন"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"রঙ এবং চেহারা"</string>
<string name="night_mode" msgid="3540405868248625488">"রাতের মোড"</string>
<string name="calibrate_display" msgid="5974642573432039217">"প্রদর্শন ক্যালিব্রেট করুন"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"কীবোর্ডের বোতাম নির্বাচন করুন"</string>
<string name="preview" msgid="9077832302472282938">"পূর্বরূপ দেখুন"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"টাইলগুলি যোগ করার জন্য টেনে আনুন"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"সরানোর জন্য এখানে টেনে আনুন"</string>
<string name="qs_edit" msgid="2232596095725105230">"সম্পাদনা করুন"</string>
<string name="tuner_time" msgid="6572217313285536011">"সময়"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
index 6bb19f5a87b1..cbed4a184e36 100644
--- a/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
+++ b/packages/SystemUI/res/values-bn-rBD/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP নিয়ন্ত্রণ করতে "<b>"হোম"</b>" কী ধরে রাখুন"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP নিয়ন্ত্রণ করতে HOME বোতামটিকে টিপুন ও ধরে থাকুন"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"বুঝেছি"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings.xml b/packages/SystemUI/res/values-bs-rBA/strings.xml
index 6677ffb2850c..024bf707f547 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings.xml
@@ -237,6 +237,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija utvrđena GPS signalom"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktiviran je zahtjev za lokaciju"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Uklanjanje svih obavještenja."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Postavke obavještenja"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Postavke aplikacije <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran će se automatski rotirati."</string>
@@ -479,6 +481,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Prikaži na vrhu liste obavještenja, kratko prikaži na ekranu i dozvoli zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
<string name="night_mode" msgid="3540405868248625488">"Noćni način rada"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibracija zaslona"</string>
diff --git a/packages/SystemUI/res/values-bs-rBA/strings_tv.xml b/packages/SystemUI/res/values-bs-rBA/strings_tv.xml
index dd4a518f6db3..5d20c8c3a15a 100644
--- a/packages/SystemUI/res/values-bs-rBA/strings_tv.xml
+++ b/packages/SystemUI/res/values-bs-rBA/strings_tv.xml
@@ -29,4 +29,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Za kontr. PIP držite "<b>"HOME"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Za kontrolu PIP, pritisnite i držite dugme POČETAK"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Jasno mi je"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index a2647604e555..645c84f83ece 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"S\'ha establert la ubicació per GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Sol·licituds d\'ubicació actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Esborra totes les notificacions."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Configuració de les notificacions"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Configuració de l\'aplicació <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girarà automàticament."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Les notificacions es mostren al capdamunt de la llista, apareixen a la pantalla i poden emetre sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Més opcions"</string>
<string name="notification_done" msgid="5279426047273930175">"Fet"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Color i aparença"</string>
<string name="night_mode" msgid="3540405868248625488">"Mode nocturn"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibra la pantalla"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Selecciona un botó de teclat"</string>
<string name="preview" msgid="9077832302472282938">"Previsualització"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrossega per afegir camps"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrossega\'ls aquí per suprimir-los"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edita"</string>
<string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-ca/strings_tv.xml b/packages/SystemUI/res/values-ca/strings_tv.xml
index 3634b994c105..35482d4c800b 100644
--- a/packages/SystemUI/res/values-ca/strings_tv.xml
+++ b/packages/SystemUI/res/values-ca/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Prem "<b>"INICI"</b>" per controlar PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén premut el botó INICI per controlar PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"D\'acord"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 5dd196e959ba..5ce6bd94592c 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -238,6 +238,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavena pomocí systému GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktivní žádosti o polohu"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazat všechna oznámení."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"a ještě <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Nastavení oznámení"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Nastavení aplikace <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka se automaticky otočí."</string>
@@ -480,6 +481,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Tato oznámení zobrazovat na začátku seznamu, zobrazit přímo na obrazovce a upozornit na ně zvukem"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Další nastavení"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"Nastavení oznámení aplikace <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Barva a vzhled"</string>
<string name="night_mode" msgid="3540405868248625488">"Noční režim"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibrovat displej"</string>
diff --git a/packages/SystemUI/res/values-cs/strings_tv.xml b/packages/SystemUI/res/values-cs/strings_tv.xml
index b65b08e2254f..3ee822ad324c 100644
--- a/packages/SystemUI/res/values-cs/strings_tv.xml
+++ b/packages/SystemUI/res/values-cs/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Funkci PIP lze ovládat podržením tlačítka "<b>"PLOCHA"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Funkci PIP lze ovládat podržením tlačítka PLOCHA"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Rozumím"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Zavřít"</string>
</resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index c2db83dc5dc0..0538bdbf1370 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Placeringen er angivet ved hjælp af GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktive placeringsanmodninger"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ryd alle underretninger."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Underretningsindstillinger"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Indstillinger for <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skærmen roterer automatisk."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på listen over underretninger, vis på skærmen, og tillad lyd"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere indstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Færdig"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Farve og udseende"</string>
<string name="night_mode" msgid="3540405868248625488">"Nattilstand"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibrer skærmen"</string>
diff --git a/packages/SystemUI/res/values-da/strings_tv.xml b/packages/SystemUI/res/values-da/strings_tv.xml
index b51c5df95375..51b85820f18f 100644
--- a/packages/SystemUI/res/values-da/strings_tv.xml
+++ b/packages/SystemUI/res/values-da/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" nede for at styre PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Tryk på HOME-knappen, og hold den nede for at styre PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index 6d3906d18820..4cd031662647 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Standortanfragen aktiv"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Benachrichtigungseinstellungen"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Einstellungen von <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Bildschirm wird automatisch gedreht."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Ganz oben in der Benachrichtigungsliste anzeigen, auf dem Display einblenden und Ton zulassen"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Weitere Einstellungen"</string>
<string name="notification_done" msgid="5279426047273930175">"Fertig"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Farbe und Darstellung"</string>
<string name="night_mode" msgid="3540405868248625488">"Nachtmodus"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Bildschirm kalibrieren"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Taste auswählen"</string>
<string name="preview" msgid="9077832302472282938">"Vorschau"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Zum Hinzufügen von Kacheln ziehen"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Zum Entfernen hierher ziehen"</string>
<string name="qs_edit" msgid="2232596095725105230">"Bearbeiten"</string>
<string name="tuner_time" msgid="6572217313285536011">"Uhrzeit"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-de/strings_tv.xml b/packages/SystemUI/res/values-de/strings_tv.xml
index b96669b1c7c0..f4487373b97e 100644
--- a/packages/SystemUI/res/values-de/strings_tv.xml
+++ b/packages/SystemUI/res/values-de/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109"><b>"STARTBILDSCHIRMTASTE"</b>" drücken, um PIP zu steuern"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Halte die Taste für die Startseite gedrückt, um das Bild-in-Bild zu steuern"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index d3971b158138..59810c27ca3b 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ρύθμιση τοποθεσίας με GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Τα αιτήματα τοποθεσίας έχουν ενεργοποιηθεί"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Εκκαθάριση όλων των ειδοποιήσεων."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Ρυθμίσεις ειδοποιήσεων"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Ρυθμίσεις <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Θα γίνεται αυτόματη περιστροφή της οθόνης."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Να εμφανίζονται στην κορυφή της λίστας ειδοποιήσεων, να προβάλλονται στην οθόνη και να επιτρέπεται ο ήχος"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Περισσότερες ρυθμίσεις"</string>
<string name="notification_done" msgid="5279426047273930175">"Τέλος"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Χρώμα και εμφάνιση"</string>
<string name="night_mode" msgid="3540405868248625488">"Νυχτερινή λειτουργία"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Βαθμονόμηση οθόνης"</string>
diff --git a/packages/SystemUI/res/values-el/strings_tv.xml b/packages/SystemUI/res/values-el/strings_tv.xml
index e72d579acdc8..355c9b0ff7ac 100644
--- a/packages/SystemUI/res/values-el/strings_tv.xml
+++ b/packages/SystemUI/res/values-el/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Κρατήστε το πλήκτρο "<b>"HOME"</b>" πατημένο για έλεγχο του PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Πιέστε παρατεταμένα το κουμπί HOME, για να ελέγξετε τη λειτουργία PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Κατάλαβα"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 18dabd2fae42..93461884ada3 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Notification settings"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> settings"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Finished"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> notification controls"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
<string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
diff --git a/packages/SystemUI/res/values-en-rAU/strings_tv.xml b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
index 5711c352aa1a..87255aeb0628 100644
--- a/packages/SystemUI/res/values-en-rAU/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Dismiss"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 18dabd2fae42..93461884ada3 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Notification settings"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> settings"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Finished"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> notification controls"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
<string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings_tv.xml b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
index 5711c352aa1a..87255aeb0628 100644
--- a/packages/SystemUI/res/values-en-rGB/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Dismiss"</string>
</resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 18dabd2fae42..93461884ada3 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Location set by GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Location requests active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Clear all notifications."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+<xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Notification settings"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> settings"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Screen will rotate automatically."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Show at the top of the notifications list, peek on to the screen and allow sound"</string>
<string name="notification_more_settings" msgid="816306283396553571">"More settings"</string>
<string name="notification_done" msgid="5279426047273930175">"Finished"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> notification controls"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Colour and appearance"</string>
<string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrate display"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings_tv.xml b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
index 5711c352aa1a..87255aeb0628 100644
--- a/packages/SystemUI/res/values-en-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Hold "<b>"HOME"</b>" to control PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Press and hold the HOME button to control PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Understood"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Dismiss"</string>
</resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index c9a4f83e3f0b..45b40203f9f8 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"La ubicación se estableció por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas las notificaciones"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Configuración de notificaciones"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Configuración de <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, ver en la pantalla y permitir sonidos"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más opciones de configuración"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Color y apariencia"</string>
<string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Selecciona un botón del teclado"</string>
<string name="preview" msgid="9077832302472282938">"Vista previa"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastra los mosaicos para agregarlos"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra aquí para quitar"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
<string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-es-rUS/strings_tv.xml b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
index 99913e644cf8..98ad35bd9fe7 100644
--- a/packages/SystemUI/res/values-es-rUS/strings_tv.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Mantén presionado "<b>"INICIO"</b>" para controlar PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén presionado el botón INICIO para controlar PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index 987f4b57b8c5..5c84999dfebc 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Ubicación definida por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de ubicación activas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Borrar todas las notificaciones"</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ de <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Ajustes de notificaciones"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Ajustes de <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"La pantalla girará automáticamente."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Mostrar en la parte superior de la lista de notificaciones, mostrar en la pantalla y permitir sonido"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Más ajustes"</string>
<string name="notification_done" msgid="5279426047273930175">"Listo"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"Controles de notificaciones de <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Color y aspecto"</string>
<string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
@@ -536,8 +538,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Selecciona un botón de teclado"</string>
<string name="preview" msgid="9077832302472282938">"Vista previa"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastrar para añadir mosaicos"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastrar aquí para eliminar"</string>
<string name="qs_edit" msgid="2232596095725105230">"Cambiar"</string>
<string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-es/strings_tv.xml b/packages/SystemUI/res/values-es/strings_tv.xml
index 200410cee2c8..c0b0afe9789a 100644
--- a/packages/SystemUI/res/values-es/strings_tv.xml
+++ b/packages/SystemUI/res/values-es/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Mantén el botón "<b>"INICIO"</b>" pulsado para control de PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén el botón de INICIO pulsado para controlar el modo PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendido"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Ignorar"</string>
</resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index 6384805a5221..423166fd0d7f 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-i määratud asukoht"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Asukoha taotlused on aktiivsed"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Kustuta kõik teatised."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Märguandeseaded"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Rakenduse <xliff:g id="APP_NAME">%s</xliff:g> seaded"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekraani pööramine toimub automaatselt."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Kuva märguannete loendi ülaservas, kuva ekraani servas ja luba heli"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Rohkem seadeid"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"Rakenduse <xliff:g id="APP_NAME">%1$s</xliff:g> märguannete juhtnupud"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Värv ja ilme"</string>
<string name="night_mode" msgid="3540405868248625488">"Öörežiim"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Ekraani kalibreerimine"</string>
@@ -536,8 +538,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Klaviatuuri nupu valimine"</string>
<string name="preview" msgid="9077832302472282938">"Eelvaade"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Lohistage paanide lisamiseks"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Lohistage eemaldamiseks siia"</string>
<string name="qs_edit" msgid="2232596095725105230">"Muuda"</string>
<string name="tuner_time" msgid="6572217313285536011">"Kellaaeg"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-et-rEE/strings_tv.xml b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
index 972083b4a100..f427b80f7bcb 100644
--- a/packages/SystemUI/res/values-et-rEE/strings_tv.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP juht. hoidke all nuppu "<b>"AVAEKRAAN"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP juhtimiseks vajutage pikalt nuppu AVAEKRAAN"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Selge"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Loobu"</string>
</resources>
diff --git a/packages/SystemUI/res/values-eu-rES/strings.xml b/packages/SystemUI/res/values-eu-rES/strings.xml
index 14bb06387bd4..435e8213fdb2 100644
--- a/packages/SystemUI/res/values-eu-rES/strings.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Kokapena GPS bidez ezarri da"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aplikazioen kokapen-eskaerak aktibo daude"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Garbitu jakinarazpen guztiak."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Jakinarazpen-ezarpenak"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ezarpenak"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Pantaila automatikoki biratuko da."</string>
@@ -301,7 +303,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"Muga: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"Abisua: <xliff:g id="DATA_LIMIT">%s</xliff:g>"</string>
<string name="quick_settings_work_mode_label" msgid="6244915274350490429">"Lan modua"</string>
- <string name="recents_empty_message" msgid="808480104164008572">"Ez dago duela gutxiko ezer"</string>
+ <string name="recents_empty_message" msgid="808480104164008572">"Ez dago azkenaldi honetako ezer"</string>
<string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"Dena garbitu duzu"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Aplikazioaren informazioa"</string>
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"pantaila-ainguratzea"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Erakutsi jakinarazpen hauek zerrendaren goialdean, agerrarazi pantailan eta egin soinua"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ezarpen gehiago"</string>
<string name="notification_done" msgid="5279426047273930175">"Eginda"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Kolorea eta itxura"</string>
<string name="night_mode" msgid="3540405868248625488">"Gau modua"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibratu pantaila"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Hautatu teklatuko botoia"</string>
<string name="preview" msgid="9077832302472282938">"Aurrebista"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastatu lauzak hemen gehitzeko"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kentzeko, arrastatu hona"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editatu"</string>
<string name="tuner_time" msgid="6572217313285536011">"Ordua"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-eu-rES/strings_tv.xml b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
index a312ea48bd4a..f28ec5e73ce4 100644
--- a/packages/SystemUI/res/values-eu-rES/strings_tv.xml
+++ b/packages/SystemUI/res/values-eu-rES/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109"><b>"HASIERA"</b>" PIP kontrolatzeko"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Eduki sakatuta hasierako botoia pantaila txikia kontrolatzeko"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ados"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 2f78d8c4cd3b..f2e977c55819 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"‏مکان تنظیم شده توسط GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"درخواست‌های موقعیت مکانی فعال است"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"پاک کردن تمام اعلان‌ها"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"تنظیمات اعلان"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"تنظیمات <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"صفحه به صورت خودکار می‌چرخد."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"در بالای فهرست اعلان نشان داده شوند، در صفحه نشان داده شوند و صدادار باشند"</string>
<string name="notification_more_settings" msgid="816306283396553571">"تنظیمات بیشتر"</string>
<string name="notification_done" msgid="5279426047273930175">"تمام"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"رنگ و ظاهر"</string>
<string name="night_mode" msgid="3540405868248625488">"حالت شب"</string>
<string name="calibrate_display" msgid="5974642573432039217">"درجه‌بندی نمایشگر"</string>
diff --git a/packages/SystemUI/res/values-fa/strings_tv.xml b/packages/SystemUI/res/values-fa/strings_tv.xml
index cf37db108277..51777243d19b 100644
--- a/packages/SystemUI/res/values-fa/strings_tv.xml
+++ b/packages/SystemUI/res/values-fa/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"‏کنترل PIP ‏با نگه‌داشتن "<b>"HOME"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"‏برای کنترل PIP دکمه صفحه اصلی را فشار داده و نگه‌دارید"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"متوجه شدم"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index dd826164f7f6..11cb91ef4e62 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Sijaintipyynnöt aktiiviset"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tyhjennä kaikki ilmoitukset."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Ilmoitusasetukset"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Asetukset – <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ruutu kääntyy automaattisesti."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Näytä ilmoitukset näytöllä ja ilmoitusluettelon yläosassa ja salli niiden äänet."</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lisäasetukset"</string>
<string name="notification_done" msgid="5279426047273930175">"Valmis"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Väri ja ulkoasu"</string>
<string name="night_mode" msgid="3540405868248625488">"Yötila"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibroi näyttö"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Valitse näppäimistön näppäin"</string>
<string name="preview" msgid="9077832302472282938">"Esikatselu"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Lisää osioita vetämällä."</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Poista vetämällä tähän."</string>
<string name="qs_edit" msgid="2232596095725105230">"Muokkaa"</string>
<string name="tuner_time" msgid="6572217313285536011">"Aika"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-fi/strings_tv.xml b/packages/SystemUI/res/values-fi/strings_tv.xml
index 94c780628ad9..642ed208df48 100644
--- a/packages/SystemUI/res/values-fi/strings_tv.xml
+++ b/packages/SystemUI/res/values-fi/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP: paina pitkään "<b>"aloituspain"</b>"."</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Hallinnoi PIP-tilaa painamalla ALOITUSNÄYTTÖ-painiketta pitkään."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Selvä"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 7f6be2827394..c647cc965537 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Paramètres de notification"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Paramètres de <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
<string name="night_mode" msgid="3540405868248625488">"Mode Nuit"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrer l\'affichage"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Sélectionnez la touche du clavier"</string>
<string name="preview" msgid="9077832302472282938">"Aperçu"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Faites glisser des tuiles ici pour les ajouter"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Faites glisser les tuiles ici pour les supprimer"</string>
<string name="qs_edit" msgid="2232596095725105230">"Modifier"</string>
<string name="tuner_time" msgid="6572217313285536011">"Heure"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
index 9fc21df14652..1ae3c5c16e43 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Maint. enf. "<b>"ACC."</b>" pr gér. mode IDI"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Maintenez enfoncé le bouton ACCUEIL pour gérer le mode IDI."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index f252977c90fc..7d91f6f108ab 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Position définie par GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Demandes de localisation actives"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Supprimer toutes les notifications"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Paramètres de notification"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Paramètres de <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"L\'écran pivote automatiquement."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Afficher en haut de la liste des notifications, afficher sur l\'écran et émettre un son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Plus de paramètres"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminé"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Couleur et apparence"</string>
<string name="night_mode" msgid="3540405868248625488">"Mode Nuit"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrer l\'affichage"</string>
diff --git a/packages/SystemUI/res/values-fr/strings_tv.xml b/packages/SystemUI/res/values-fr/strings_tv.xml
index 27c62fb50c41..68c4dcb56cce 100644
--- a/packages/SystemUI/res/values-fr/strings_tv.xml
+++ b/packages/SystemUI/res/values-fr/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Appui long "<b>"ACCUEIL"</b>" pour contrôler PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Appuyez de manière prolongée sur le bouton ACCUEIL pour contrôler le mode PIP."</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gl-rES/strings.xml b/packages/SystemUI/res/values-gl-rES/strings.xml
index 4574838b9c35..1474acff91a6 100644
--- a/packages/SystemUI/res/values-gl-rES/strings.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Localización establecida polo GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitudes de localización activas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Eliminar todas as notificacións."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Configuración das notificacións"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Configuración de <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A pantalla xirará automaticamente."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificacións, amosar na pantalla e permitir que emita son"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Máis opcións"</string>
<string name="notification_done" msgid="5279426047273930175">"Feito"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspecto"</string>
<string name="night_mode" msgid="3540405868248625488">"Modo nocturno"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrar pantalla"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Selecciona o botón do teclado"</string>
<string name="preview" msgid="9077832302472282938">"Vista previa"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arrastrar para engadir mosaicos"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arrastra o elemento ata aquí para eliminalo"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
<string name="tuner_time" msgid="6572217313285536011">"Hora"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-gl-rES/strings_tv.xml b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
index b0343e16ebdb..11d2d4c844dc 100644
--- a/packages/SystemUI/res/values-gl-rES/strings_tv.xml
+++ b/packages/SystemUI/res/values-gl-rES/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Manter premido "<b>"INICIO"</b>" para controlar PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Mantén premido o botón de INICIO para controlar PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"De acordo"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings.xml b/packages/SystemUI/res/values-gu-rIN/strings.xml
index 2fd9682106ce..7b6421462341 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS દ્વારા સ્થાન સેટ કરાયું"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"સ્થાન વિનંતીઓ સક્રિય"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"બધા સૂચનો સાફ કરો."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"સૂચનાઓની સેટિંગ્સ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> સેટિંગ્સ"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"સ્ક્રીન આપમેળે ફરશે."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"સૂચનાઓની સૂચિની ટોચ પર બતાવો, સ્ક્રીન પર ત્વરિત દ્રષ્ટિ કરો અને અવાજને મંજૂરી આપો"</string>
<string name="notification_more_settings" msgid="816306283396553571">"વધુ સેટિંગ્સ"</string>
<string name="notification_done" msgid="5279426047273930175">"થઈ ગયું"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> સૂચના નિયંત્રણો"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"રંગ અને દેખાવ"</string>
<string name="night_mode" msgid="3540405868248625488">"રાત્રિ મોડ"</string>
<string name="calibrate_display" msgid="5974642573432039217">"પ્રદર્શન કૅલિબ્રેટ કરો"</string>
diff --git a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
index 3f2f68a93520..878e91fd393b 100644
--- a/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-gu-rIN/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP નિયંત્રિત કરવા માટે "<b>"હોમ"</b>" પકડી રાખો"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP નિયંત્રિત કરવા માટે હોમ બટન દબાવો અને પકડી રાખો"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"સમજાઈ ગયું"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"છોડી દો"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index fba548051426..84c073d81f1b 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा सेट किया गया स्‍थान"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोध सक्रिय"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सभी सूचनाएं साफ़ करें."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"नोटिफिकेशन सेटिंग"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> सेटिंग"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्‍क्रीन स्‍वचालित रूप से घूमेगी."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"नोटिफिकेशन सूची के शीर्ष पर दिखाएं, स्क्रीन पर झलक दिखाएं और ध्वनि करें"</string>
<string name="notification_more_settings" msgid="816306283396553571">"और सेटिंग"</string>
<string name="notification_done" msgid="5279426047273930175">"हो गया"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> नोटिफ़िकेशन नियंत्रण"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"रंग और दिखावट"</string>
<string name="night_mode" msgid="3540405868248625488">"रात्रि मोड"</string>
<string name="calibrate_display" msgid="5974642573432039217">"स्क्रीन को कैलिब्रेट करें"</string>
diff --git a/packages/SystemUI/res/values-hi/strings_tv.xml b/packages/SystemUI/res/values-hi/strings_tv.xml
index cf259ddc9012..0b4f3e58fedf 100644
--- a/packages/SystemUI/res/values-hi/strings_tv.xml
+++ b/packages/SystemUI/res/values-hi/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रण हेतु "<b>"HOME"</b>" होल्ड करें"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP नियंत्रण के लिए HOME बटन को दबाए रखें"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"समझ लिया"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"ख़ारिज करें"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index e45e14ecba66..e69ad3188cf4 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -237,6 +237,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokaciju utvrdio GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Zahtjevi za lokaciju aktivni su"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Brisanje svih obavijesti."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Postavke obavijesti"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Postavke aplikacije <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon će se automatski zakrenuti."</string>
@@ -479,6 +481,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Prikaži pri vrhu popisa obavijesti, prikaži na zaslonu i dopusti zvuk"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Više postavki"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotovo"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Boja i izgled"</string>
<string name="night_mode" msgid="3540405868248625488">"Noćni način rada"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibriranje zaslona"</string>
@@ -537,8 +541,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Odaberite gumb tipkovnice"</string>
<string name="preview" msgid="9077832302472282938">"Pregled"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Povucite da biste dodali pločice"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Povucite ovdje za uklanjanje"</string>
<string name="qs_edit" msgid="2232596095725105230">"Uredi"</string>
<string name="tuner_time" msgid="6572217313285536011">"Vrijeme"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-hr/strings_tv.xml b/packages/SystemUI/res/values-hr/strings_tv.xml
index 424c68b06ce5..3d5c8f818773 100644
--- a/packages/SystemUI/res/values-hr/strings_tv.xml
+++ b/packages/SystemUI/res/values-hr/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Držite "<b>"POČETNI"</b>" za PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Pritisnite i zadržite tipku POČETNI ZASLON da biste upravljali slikom u slici"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Shvaćam"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 605f0bed24af..a7d62c3675a3 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"A GPS beállította a helyet"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktív helylekérések"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Minden értesítés törlése"</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Értesítési beállítások"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> beállításai"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A képernyő automatikusan forogni fog."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Az értesítési lista tetején jelennek meg, illetve felugranak a képernyőn hangjelzéssel"</string>
<string name="notification_more_settings" msgid="816306283396553571">"További beállítások"</string>
<string name="notification_done" msgid="5279426047273930175">"Kész"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g>-értesítések vezérlői"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Szín és megjelenés"</string>
<string name="night_mode" msgid="3540405868248625488">"Éjszakai mód"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kijelző kalibrálása"</string>
diff --git a/packages/SystemUI/res/values-hu/strings_tv.xml b/packages/SystemUI/res/values-hu/strings_tv.xml
index 5271a4a24102..97d6cdd0ac70 100644
--- a/packages/SystemUI/res/values-hu/strings_tv.xml
+++ b/packages/SystemUI/res/values-hu/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP vezérlése a "<b>"HOME"</b>"-mal"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"A PIP vezérléséhez tartsa nyomva a HOME gombot"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Rendben"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Elvetés"</string>
</resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 11a94d9ce92d..79e5268c904a 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Տեղադրությունը կարգավորվել է GPS-ի կողմից"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Տեղադրության հարցումներն ակտիվ են"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Մաքրել բոլոր ծանուցումները:"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Ծանուցման կարգավորումներ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>-ի կարգավորումներ"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Էկրանը ինքնաշխատ կպտտվի:"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Ցույց տալ ծանուցումների ցանկի վերևում, թռուցիկ ցուցադրել էկրանին և թույլատրել ձայնային ազդանշանը"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Այլ կարգավորումներ"</string>
<string name="notification_done" msgid="5279426047273930175">"Պատրաստ է"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Գույնը և արտաքին տեսքը"</string>
<string name="night_mode" msgid="3540405868248625488">"Գիշերային ռեժիմ"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Չափաբերել էկրանը"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
index 280d733afd80..dc4c312cc13d 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP-ն կառավարելու համար սեղմած պահեք "<b>"HOME"</b>" կոճակը"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP-ն կառավարելու համար սեղմեք և պահեք HOME կոճակը"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Պարզ է"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 6a83bc99ebbd..3ac5904baa84 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi yang disetel oleh GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Menghapus semua pemberitahuan."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Setelan pemberitahuan"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> setelan"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Layar akan diputar secara otomatis."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Tampilkan di bagian atas daftar notifikasi, muncul di layar, dan izinkan suara"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Setelan lainnya"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Warna dan tampilan"</string>
<string name="night_mode" msgid="3540405868248625488">"Mode malam"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibrasi layar"</string>
diff --git a/packages/SystemUI/res/values-in/strings_tv.xml b/packages/SystemUI/res/values-in/strings_tv.xml
index c12fa9c92a76..8e3a5e0638da 100644
--- a/packages/SystemUI/res/values-in/strings_tv.xml
+++ b/packages/SystemUI/res/values-in/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Tahan "<b>"LAYAR UTAMA"</b>" untuk mengontrol PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Tekan dan tahan tombol LAYAR UTAMA untuk mengontrol PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Mengerti"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-is-rIS/strings.xml b/packages/SystemUI/res/values-is-rIS/strings.xml
index 9bb08465c132..c063c73a0bbd 100644
--- a/packages/SystemUI/res/values-is-rIS/strings.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Staðsetning valin með GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Staðsetningarbeiðnir virkar"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Hreinsa allar tilkynningar."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Tilkynningastillingar"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Stillingar fyrir <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjárinn snýst sjálfkrafa."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Sýna efst á tilkynningalistanum, birta á skjánum og leyfa hljóð"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fleiri stillingar"</string>
<string name="notification_done" msgid="5279426047273930175">"Lokið"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Litur og útlit"</string>
<string name="night_mode" msgid="3540405868248625488">"Næturstilling"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kvarða skjáinn"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Veldu lyklaborðshnapp"</string>
<string name="preview" msgid="9077832302472282938">"Forskoðun"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Dragðu til að bæta við reitum"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Dragðu hingað til að fjarlægja"</string>
<string name="qs_edit" msgid="2232596095725105230">"Breyta"</string>
<string name="tuner_time" msgid="6572217313285536011">"Tími"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-is-rIS/strings_tv.xml b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
index 9c3db2f9ea9c..053beaffa763 100644
--- a/packages/SystemUI/res/values-is-rIS/strings_tv.xml
+++ b/packages/SystemUI/res/values-is-rIS/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Haltu "<b>"HOME"</b>"-hnappinum inni til að stjórna innfelldri mynd"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Haltu „Home“-hnappinum inni til að stjórna innfelldri mynd"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ég skil"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 63e71eeb1974..5ccc39cea60d 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posizione stabilita dal GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Richieste di accesso alla posizione attive"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Cancella tutte le notifiche."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Impostazioni di notifica"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Impostazioni di <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Lo schermo ruoterà automaticamente."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Mostra in cima all\'elenco delle notifiche, visualizza sullo schermo e attiva l\'audio"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Altre impostazioni"</string>
<string name="notification_done" msgid="5279426047273930175">"Fine"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Colore e aspetto"</string>
<string name="night_mode" msgid="3540405868248625488">"Modalità notturna"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibra display"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Seleziona il tasto della tastiera"</string>
<string name="preview" msgid="9077832302472282938">"Anteprima"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Trascina per aggiungere i riquadri"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Trascinali qui per rimuoverli"</string>
<string name="qs_edit" msgid="2232596095725105230">"Modifica"</string>
<string name="tuner_time" msgid="6572217313285536011">"Ora"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-it/strings_tv.xml b/packages/SystemUI/res/values-it/strings_tv.xml
index dc79802aeb45..5001b959bf1a 100644
--- a/packages/SystemUI/res/values-it/strings_tv.xml
+++ b/packages/SystemUI/res/values-it/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Tieni premuto "<b>"HOME"</b>" per controllare PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Tieni premuto il pulsante HOME per controllare PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9ccb9d2d68d8..52c83ba9b0d9 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -238,6 +238,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"‏מיקום מוגדר על ידי GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"בקשות מיקום פעילות"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"נקה את כל ההתראות."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"הגדרות עבור הודעות"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"הגדרות <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"המסך יסתובב באופן אוטומטי."</string>
@@ -480,6 +482,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"הצג בראש רשימת ההודעות, הצג לרגע על גבי המסך ואשר השמעת צליל"</string>
<string name="notification_more_settings" msgid="816306283396553571">"הגדרות נוספות"</string>
<string name="notification_done" msgid="5279426047273930175">"סיום"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"צבע ומראה"</string>
<string name="night_mode" msgid="3540405868248625488">"מצב לילה"</string>
<string name="calibrate_display" msgid="5974642573432039217">"כיול תצוגה"</string>
diff --git a/packages/SystemUI/res/values-iw/strings_tv.xml b/packages/SystemUI/res/values-iw/strings_tv.xml
index 77deaf613e6c..f4d4094e4cc3 100644
--- a/packages/SystemUI/res/values-iw/strings_tv.xml
+++ b/packages/SystemUI/res/values-iw/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"‏לחץ לחיצה ארוכה על "<b>"דף הבית"</b>" כדי לשלוט ב-PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"‏לחץ לחיצה ממושכת על לחצן דף הבית כדי לשלוט ב-PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"הבנתי"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 84b504eac84e..f7aaceebf83f 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPSにより現在地が設定されました"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"現在地リクエストがアクティブ"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"通知をすべて消去。"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"通知設定"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>の設定"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"画面は自動的に回転します。"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"通知リストの先頭に表示し、画面に数秒間表示し、音声でも知らせる"</string>
<string name="notification_more_settings" msgid="816306283396553571">"詳細設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完了"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"色と表示"</string>
<string name="night_mode" msgid="3540405868248625488">"夜間モード"</string>
<string name="calibrate_display" msgid="5974642573432039217">"表示の調整"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"キーボードのボタンの選択"</string>
<string name="preview" msgid="9077832302472282938">"プレビュー"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"タイルを追加するにはドラッグしてください"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"削除するにはここにドラッグ"</string>
<string name="qs_edit" msgid="2232596095725105230">"編集"</string>
<string name="tuner_time" msgid="6572217313285536011">"時間"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-ja/strings_tv.xml b/packages/SystemUI/res/values-ja/strings_tv.xml
index 48e38497e689..a4c49b3dd8a6 100644
--- a/packages/SystemUI/res/values-ja/strings_tv.xml
+++ b/packages/SystemUI/res/values-ja/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP を管理するには ["<b>"ホーム"</b>"] を押し続けます"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP を管理するには [ホーム] ボタンを押し続けます"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"閉じる"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index 7c701cca692d..9730323e2de0 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS-ით დადგენილი მდებარეობა"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"მდებარეობის მოთხოვნები აქტიურია"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ყველა შეტყობინების წაშლა"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"შეტყობინების პარამეტრები"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> პარამეტრები"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ეკრანი შეტრიალდება ავტომატურად."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"შეტყობინებების სიის თავში ჩვენება, პირდაპირ ეკრანზე გამოჩენა და ხმის დაშვება"</string>
<string name="notification_more_settings" msgid="816306283396553571">"დამატებითი პარამეტრები"</string>
<string name="notification_done" msgid="5279426047273930175">"მზადაა"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"ფერი და იერსახე"</string>
<string name="night_mode" msgid="3540405868248625488">"ღამის რეჟიმი"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ეკრანის კალიბრაცია"</string>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
index e525eba29588..3a556ae2815a 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP-ის სამართავად, გეჭიროთ "<b>"მთავარ ღილაკზე"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP-ის სამართავად, ხანგრძლივად დააჭირეთ მთავარ ღილაკს"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"გასაგებია"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings.xml b/packages/SystemUI/res/values-kk-rKZ/strings.xml
index a08d81f7178b..f6c11520663f 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Орын GPS арқылы орнатылған"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Орын өтініштері қосылған"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Барлық хабарларды жойыңыз."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Хабарландыру параметрлері"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> параметрлері"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран автоматты түрде бұрылады."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Хабарландырулар тізімінің жоғарғы жағында көрсету, экранда көрсету және дыбысқа рұқсат ету"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Қосымша параметрлер"</string>
<string name="notification_done" msgid="5279426047273930175">"Дайын"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Түс және сыртқы түрі"</string>
<string name="night_mode" msgid="3540405868248625488">"Түнгі режим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Дисплейді калибрлеу"</string>
diff --git a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
index 40108641c371..ef930b0a723f 100644
--- a/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-kk-rKZ/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP басқару үшін "<b>"HOME"</b>" басып тұрыңыз"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP функциясын басқару үшін HOME түймесін басып тұрыңыз"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Түсіндім"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index df69de53135f..4a306daf268e 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ទីតាំង​​​​​កំណត់​ដោយ GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"សំណើ​ទីតាំង​សកម្ម"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"សម្អាត​ការ​ជូន​ដំណឹង​ទាំងអស់។"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"​កំណត់​ការ​ជូនដំណឹង"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"ការ​កំណត់ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"នឹង​បង្វិល​អេក្រង់​ស្វ័យ​ប្រវត្តិ។"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"បង្ហាញនៅផ្នែកខាងលើបញ្ជីនៃការជូនដំណឹង លោតបង្ហាញនៅលើអេក្រង់ និងអនុញ្ញាតឲ្យបន្លឺសំឡេង"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ការកំណត់ច្រើនទៀត"</string>
<string name="notification_done" msgid="5279426047273930175">"រួចរាល់"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"ពណ៌ និងរូបរាង"</string>
<string name="night_mode" msgid="3540405868248625488">"របៀបពេលយប់"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ការបង្ហាញក្រិត"</string>
diff --git a/packages/SystemUI/res/values-km-rKH/strings_tv.xml b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
index 1faa564af4d2..8076010571ab 100644
--- a/packages/SystemUI/res/values-km-rKH/strings_tv.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"សង្កត់ប៊ូតុង "<b>"ដើម"</b>" ដើម្បីគ្រប់គ្រង PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"ចុច និងសង្កត់ប៊ូតុង ដើម ដើម្បីគ្រប់គ្រង PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"យល់ហើយ"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings.xml b/packages/SystemUI/res/values-kn-rIN/strings.xml
index 046b9abf8da4..046d5d8eba87 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ಸ್ಥಾನವನ್ನು GPS ಮೂಲಕ ಹೊಂದಿಸಲಾಗಿದೆ"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"ಸ್ಥಾನ ವಿನಂತಿಗಳು ಸಕ್ರಿಯವಾಗಿವೆ"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ಎಲ್ಲಾ ಅಧಿಸೂಚನೆಗಳನ್ನು ತೆರವುಗೊಳಿಸು."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"ಅಧಿಸೂಚನೆ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ಪರದೆಯು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ತಿರುಗುತ್ತದೆ."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"ಅಧಿಸೂಚನೆಗಳ ಪಟ್ಟಿಯ ಮೇಲ್ಭಾಗದಲ್ಲಿ ತೋರಿಸು, ಪರದೆಯನ್ನು ವೀಕ್ಷಿಸಿ ಮತ್ತು ಧ್ವನಿ ಅನುಮತಿಸಿ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ಹೆಚ್ಚಿನ ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
<string name="notification_done" msgid="5279426047273930175">"ಮುಗಿದಿದೆ"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"ಬಣ್ಣ ಮತ್ತು ಗೋಚರತೆ"</string>
<string name="night_mode" msgid="3540405868248625488">"ರಾತ್ರಿ ಮೋಡ್"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ಅಣಿಗೊಳಿಸುವ ಪ್ರದರ್ಶನ"</string>
diff --git a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
index 5ed77050ae29..d275de61d16b 100644
--- a/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-kn-rIN/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP ನಿಯಂತ್ರಿಸಲು "<b>"HOME"</b>" ಕೀಯನ್ನು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ನಿಯಂತ್ರಿಸಲು HOME ಬಟನ್ ಒತ್ತಿರಿ ಮತ್ತು ಹಿಡಿದುಕೊಳ್ಳಿ"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ಅರ್ಥವಾಯಿತು"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c7987a0db52e..5e16258652e3 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS에서 위치 설정"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"위치 요청 있음"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"모든 알림 지우기"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"알림 설정"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> 설정"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"화면이 자동으로 회전됩니다."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"알림 목록 맨 위에 표시, 화면에 표시하고 소리로 알림"</string>
<string name="notification_more_settings" msgid="816306283396553571">"설정 더보기"</string>
<string name="notification_done" msgid="5279426047273930175">"완료"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"색상 및 모양"</string>
<string name="night_mode" msgid="3540405868248625488">"야간 모드"</string>
<string name="calibrate_display" msgid="5974642573432039217">"디스플레이 보정"</string>
diff --git a/packages/SystemUI/res/values-ko/strings_tv.xml b/packages/SystemUI/res/values-ko/strings_tv.xml
index 57ea77c0a5b9..52747b4feb32 100644
--- a/packages/SystemUI/res/values-ko/strings_tv.xml
+++ b/packages/SystemUI/res/values-ko/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109"><b>"HOME"</b>"을 눌러 PIP 제어"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"홈 버튼을 길게 눌러 PIP 제어"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"확인"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings.xml b/packages/SystemUI/res/values-ky-rKG/strings.xml
index b6a7bdab3ed4..60db439c34f0 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS боюнча аныкталган жайгашуу"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Жайгаштыруу талаптары иштелүүдө"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Бардык эскертмелерди тазалоо."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Эскертме жөндөөлөрү"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> жөндөөлөрү"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран автоматтык түрдө бурулат."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Эскертмелер тизмесинин эң башында көрсөтүлүп, үн менен коштолуп, экранга чыгарылсын"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Дагы жөндөөлөр"</string>
<string name="notification_done" msgid="5279426047273930175">"Аткарылды"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Түсү жана көрүнүшү"</string>
<string name="night_mode" msgid="3540405868248625488">"Түнкү режим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Дисплейди калибрлөө"</string>
diff --git a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
index d00c9cffb6ac..e54aae2e7dbd 100644
--- a/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
+++ b/packages/SystemUI/res/values-ky-rKG/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109"><b>"БАШКЫ БЕТ"</b>" басып туруп PIP\'ти башкарыңыз"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP башкаруу үчүн БАШКЫ БЕТ баскычын басып, кармап туруңуз"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Түшүндүм"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index 43e7bacd3d41..f7e23449fa0a 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -28,14 +28,4 @@
<!-- We have only space for one notification on phone landscape layouts. -->
<integer name="keyguard_max_notification_count">1</integer>
-
- <!-- Recents: The relative range of visible tasks from the current scroll position
- while the stack is focused. -->
- <item name="recents_layout_focused_range_min" format="float" type="integer">-3</item>
- <item name="recents_layout_focused_range_max" format="float" type="integer">2</item>
-
- <!-- Recents: The relative range of visible tasks from the current scroll position
- while the stack is not focused. -->
- <item name="recents_layout_unfocused_range_min" format="float" type="integer">-2</item>
- <item name="recents_layout_unfocused_range_max" format="float" type="integer">1.5</item>
</resources>
diff --git a/packages/SystemUI/res/values-land/dimens.xml b/packages/SystemUI/res/values-land/dimens.xml
index 585984c9c99f..26a81c8d835c 100644
--- a/packages/SystemUI/res/values-land/dimens.xml
+++ b/packages/SystemUI/res/values-land/dimens.xml
@@ -22,9 +22,6 @@
<!-- Standard notification gravity -->
<integer name="notification_panel_layout_gravity">@integer/standard_notification_panel_layout_gravity</integer>
- <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
- <dimen name="recents_initial_bottom_peek_size">@dimen/recents_task_bar_height</dimen>
-
<dimen name="docked_divider_handle_width">2dp</dimen>
<dimen name="docked_divider_handle_height">16dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 6de06f07d0f5..ecb1eb339b0c 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ສະຖານທີ່ກຳນົດໂດຍ GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"ການຮ້ອງຂໍສະຖານທີ່ທີ່ເຮັດວຽກຢູ່"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ລຶບການແຈ້ງເຕືອນທັງໝົດ."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"​ການ​ຕັ້ງ​ຄ່າ​ການ​ແຈ້ງ​ເຕືອນ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"ການ​ຕັ້ງ​ຄ່າ <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ໜ້າຈໍຈະໝຸນໂດຍອັດຕະໂນມັດ."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"ສະແດງຢູ່ເທິງສຸດຂອງລາຍການແຈ້ງເຕືອນ, ແຈ້ງໄປໜ້າຈໍ ແລະ ອະນຸຍາດໃຫ້ໃຊ້ສຽງໄດ້"</string>
<string name="notification_more_settings" msgid="816306283396553571">"​ການ​ຕັ້ງ​ຄ່າ​ເພີ່ມ​ເຕີມ"</string>
<string name="notification_done" msgid="5279426047273930175">"ສຳເລັດແລ້ວ"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"ສີ ແລະ ລັກສະນະ"</string>
<string name="night_mode" msgid="3540405868248625488">"ໂໝດກາງຄືນ"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ປັບໜ້າຈໍ"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
index ade0ed89861e..911dcf9fc623 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"ກົດ "<b>"HOME"</b>" ຄ້າງໄວ້ເພື່ອຄວບຄຸມ PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"ແຕະປຸ່ມ HOME ຄ້າງໄວ້ເພື່ອຄວບຄຸມຮູບນ້ອຍ"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ເຂົ້າໃຈແລ້ວ"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index cb4e225b5524..4de42c0f8c84 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -238,6 +238,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS nustatyta vieta"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Vietovės užklausos aktyvios"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Išvalyti visus pranešimus."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Pranešimų nustatymai"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"„<xliff:g id="APP_NAME">%s</xliff:g>“ nustatymai"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekranas bus sukamas automatiškai."</string>
@@ -480,6 +482,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Rodyti pranešimų sąrašo viršuje, rodyti ekrane ir leisti skambėti"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Daugiau nustatymų"</string>
<string name="notification_done" msgid="5279426047273930175">"Atlikta"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Spalva ir išvaizda"</string>
<string name="night_mode" msgid="3540405868248625488">"Naktinis režimas"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibruoti ekraną"</string>
@@ -538,8 +542,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Klaviatūros mygtuko pasirinkimas"</string>
<string name="preview" msgid="9077832302472282938">"Peržiūrėti"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Nuvilkite, kad pridėtumėte išklotinės elementų"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Vilkite čia, jei norite pašalinti"</string>
<string name="qs_edit" msgid="2232596095725105230">"Redaguoti"</string>
<string name="tuner_time" msgid="6572217313285536011">"Laikas"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-lt/strings_tv.xml b/packages/SystemUI/res/values-lt/strings_tv.xml
index 8c60970b8c78..928b4c7b4d26 100644
--- a/packages/SystemUI/res/values-lt/strings_tv.xml
+++ b/packages/SystemUI/res/values-lt/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Kad vald. PIP, pal. pasp. m. "<b>"PAGRINDINIS"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Jei norite valdyti PIP, paspauskite ir palaikykite pagrindinio puslapio mygtuką"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Supratau"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index a79d27af87d9..f47397146635 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -237,6 +237,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS iestatītā atrašanās vieta"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktīvi atrašanās vietu pieprasījumi"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Notīrīt visus paziņojumus"</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"vēl <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Paziņojumu iestatījumi"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> iestatījumi"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrāns tiks pagriezts automātiski."</string>
@@ -479,6 +480,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Rādīt paziņojumu saraksta augšdaļā, rādīt ekrānā ar skaņas signālu"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Citi iestatījumi"</string>
<string name="notification_done" msgid="5279426047273930175">"Gatavs"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> paziņojumu vadīklas"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Krāsas un izskats"</string>
<string name="night_mode" msgid="3540405868248625488">"Nakts režīms"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Ekrāna kalibrēšana"</string>
@@ -537,8 +539,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Tastatūras pogas atlase"</string>
<string name="preview" msgid="9077832302472282938">"Priekšskatījums"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Velciet elementus, lai tos pievienotu"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Lai noņemtu vienumus, velciet tos šeit."</string>
<string name="qs_edit" msgid="2232596095725105230">"Rediģēt"</string>
<string name="tuner_time" msgid="6572217313285536011">"Laiks"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-lv/strings_tv.xml b/packages/SystemUI/res/values-lv/strings_tv.xml
index 397376a2700a..9e4b236ccfec 100644
--- a/packages/SystemUI/res/values-lv/strings_tv.xml
+++ b/packages/SystemUI/res/values-lv/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Turiet taustiņu "<b>"SĀKUMS"</b>", lai kontrolētu PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Nospiediet un turiet pogu SĀKUMS, lai kontrolētu PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Labi"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Nerādīt"</string>
</resources>
diff --git a/packages/SystemUI/res/values-mk-rMK/strings.xml b/packages/SystemUI/res/values-mk-rMK/strings.xml
index 8d14a6182e19..1666273976df 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Локацијата е поставена со ГПС"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Активни барања за локација"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Исчисти ги сите известувања."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Поставки на известувања"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Поставки на <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екранот ќе ротира автоматски."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Прикажувај ги на врвот на списокот со известувања, ѕиркање на екранот и овозможи звук"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Повеќе поставки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
<string name="night_mode" msgid="3540405868248625488">"Ноќен режим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Калибрирај го екранот"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Изберете копче за тастатура"</string>
<string name="preview" msgid="9077832302472282938">"Преглед"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Повлечете за додавање плочки"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Повлечете тука за да се отстрани"</string>
<string name="qs_edit" msgid="2232596095725105230">"Уреди"</string>
<string name="tuner_time" msgid="6572217313285536011">"Време"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
index e8fbcabd88ec..10bf41f3e924 100644
--- a/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
+++ b/packages/SystemUI/res/values-mk-rMK/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Задржете "<b>"ДОМА"</b>" за кон. PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Притиснете и задржете го копчето ДОМА за контролирање PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Разбрав"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings.xml b/packages/SystemUI/res/values-ml-rIN/strings.xml
index 52fe7bf6802d..882f1897a1b9 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ലൊക്കേഷൻ സജ്ജീകരിച്ചത് GPS ആണ്"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"ലൊക്കേഷൻ അഭ്യർത്ഥനകൾ സജീവമാണ്"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"എല്ലാ വിവരങ്ങളും മായ്‌ക്കുക."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"അറിയിപ്പ് ക്രമീകരണങ്ങൾ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ക്രമീകരണങ്ങൾ"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"സ്‌ക്രീൻ യാന്ത്രികമായി തിരിയും."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"അറിയിപ്പ് ലിസ്റ്റിന്റെ ഏറ്റവും മുകളിൽ കാണിക്കുക, ശബ്ദമുണ്ടാക്കുക"</string>
<string name="notification_more_settings" msgid="816306283396553571">"കൂടുതൽ ക്രമീകരണം"</string>
<string name="notification_done" msgid="5279426047273930175">"പൂർത്തിയായി"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"വർണ്ണവും രൂപഭാവവും"</string>
<string name="night_mode" msgid="3540405868248625488">"നൈറ്റ് മോഡ്"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ഡിസ്പ്ലേ കാലിബ്രേറ്റുചെയ്യുക"</string>
diff --git a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
index 96c5e3290f14..c054eedef6f8 100644
--- a/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-ml-rIN/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP നിയന്ത്രിക്കാൻ "<b>"ഹോം"</b>" പിടിക്കുക"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP നിയന്ത്രിക്കാൻ ഹോം ബട്ടൺ അമർത്തിപ്പിടിക്കുക"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"മനസ്സിലായി"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index e4f6621f5750..b9ddad7f4016 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -234,6 +234,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS байршил"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Байршлын хүсэлтүүд идэвхтэй"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Бүх мэдэгдлийг цэвэрлэх."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Мэдэгдлийн тохиргоо"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> тохиргоо"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Дэлгэц автоматаар эргэнэ."</string>
@@ -476,6 +478,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Мэдэгдлийг жагсаалтын эхэнд яаралтай дуутай харуулах"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Бусад тохиргоо"</string>
<string name="notification_done" msgid="5279426047273930175">"Дууссан"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Өнгө, харагдах байдал"</string>
<string name="night_mode" msgid="3540405868248625488">"Шөнийн горим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Дэлгэцийг тохируулах"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
index 06e0996be552..54f2282677a6 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP-г удирдахын тулд "<b>"HOME"</b>" товчлуурыг дарна уу"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP-г удирдахын тулд НҮҮР ХУУДАС товчлуурыг дараад хүлээнэ үү"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ойлголоо"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings.xml b/packages/SystemUI/res/values-mr-rIN/strings.xml
index 5f219e5720e5..e65897cfc4b5 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारे स्थान सेट केले"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान विनंत्या सक्रिय"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सर्व सूचना साफ करा."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"सूचना सेटिंग्ज"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> सेटिंग्ज"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रीन स्वयंचलितपणे फिरेल."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"सूचनांच्या शीर्षस्थानी दर्शवा, स्क्रीनवर पहा आणि ध्वनीस अनुमती द्या"</string>
<string name="notification_more_settings" msgid="816306283396553571">"अधिक सेटिंग्ज"</string>
<string name="notification_done" msgid="5279426047273930175">"पूर्ण झाले"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"रंग आणि स्वरूप"</string>
<string name="night_mode" msgid="3540405868248625488">"रात्र मोड"</string>
<string name="calibrate_display" msgid="5974642573432039217">"प्रदर्शनाचे मापन करा"</string>
diff --git a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
index 2f56b0aa0178..6a298679fddc 100644
--- a/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-mr-rIN/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP नियंत्रित करण्यासाठी "<b>"मुख्यपृष्ठ"</b>" धरून ठेवा"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP नियंत्रित करण्यासाठी मुख्यपृष्ठ बटण दाबा आणि धरून ठेवा"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"समजले"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index d7bee1e135ef..432110ce53a6 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasi ditetapkan oleh GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Permintaan lokasi aktif"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Padamkan semua pemberitahuan."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Tetapan pemberitahuan"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> tetapan"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrin akan berputar secara automatik."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Tunjukkan pada bahagian atas senarai pemberitahuan, intai pada skrin dan benarkan bunyi"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Lagi tetapan"</string>
<string name="notification_done" msgid="5279426047273930175">"Selesai"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Warna dan penampilan"</string>
<string name="night_mode" msgid="3540405868248625488">"Mod malam"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Tentukur paparan"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Pilih Butang Papan Kekunci"</string>
<string name="preview" msgid="9077832302472282938">"Pratonton"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Seret untuk menambahkan jubin"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Seret ke sini untuk mengalih keluar"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edit"</string>
<string name="tuner_time" msgid="6572217313285536011">"Masa"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
index 4ef341c44884..d358cc0d6d3d 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Thn "<b>"SKRN UTMA"</b>" utk kwl PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Tekan dan tahan butang SKRIN UTAMA untuk mengawal PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-my-rMM/strings.xml b/packages/SystemUI/res/values-my-rMM/strings.xml
index 4d5b83e3fa16..8994499569e8 100644
--- a/packages/SystemUI/res/values-my-rMM/strings.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPSမှတည်နေရာကိုအတည်ပြုသည်"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"တည်နေရာပြ တောင်းဆိုချက်များ အသက်ဝင်ရန်"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"သတိပေးချက်အားလုံးအား ဖယ်ရှားခြင်း။"</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"အကြောင်းကြားချက် ဆက်တင်များ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ဆက်တင်များ"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ဖန်သားပြင်ပေါ်မှာ ပြသမှုက အလိုအလျောက် လှည့်သွားပါမည်"</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"သတိပေးချက်စာရင်း၏ ထိပ်ဆုံးတွင်ပြပြီး ဖန်သားပြင်ပေါ်တွင် ပေါ်စေကာ အသံထွက်ခွင့်ပြုပါ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"နောက်ထပ် ဆက်တင်များ"</string>
<string name="notification_done" msgid="5279426047273930175">"ပြီးပါပြီ"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> အကြောင်းကြားချက် ထိန်းချုပ်မှုများ"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"အရောင်နှင့် အပြင်အဆင်"</string>
<string name="night_mode" msgid="3540405868248625488">"ညသုံးမုဒ်"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ပြသမှုအချိန်အဆကို ညှိပါ"</string>
diff --git a/packages/SystemUI/res/values-my-rMM/strings_tv.xml b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
index 616acda0b567..ffb0d90e6a0e 100644
--- a/packages/SystemUI/res/values-my-rMM/strings_tv.xml
+++ b/packages/SystemUI/res/values-my-rMM/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP ကိုထိန်းချုပ်ရန် "<b>"ပင်မ"</b>" ခလုတ်ကို ဖိထားပါ"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ကိုထိန်းချုပ်ရန် ပင်မခလုတ်ကို နှိပ်ပြီးဖိထားပါ"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ရပါပြီ"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"ပယ်ပါ"</string>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index d4eb2cb32428..9ee29ab5908f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Posisjon angitt av GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktive stedsforespørsler"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Fjern alle varslinger."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Varselinnstillinger"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>-innstillinger"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skjermen roterer automatisk."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Vis øverst på varsellisten, vis fort på skjermen og tillat lyd"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Flere innstillinger"</string>
<string name="notification_done" msgid="5279426047273930175">"Ferdig"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"Varselinnstillinger for <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Farge og utseende"</string>
<string name="night_mode" msgid="3540405868248625488">"Nattmodus"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibrer skjermen"</string>
@@ -536,8 +538,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Velg tastaturtast"</string>
<string name="preview" msgid="9077832302472282938">"Forhåndsvisning"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Dra for å legge til fliser"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Dra hit for å fjerne"</string>
<string name="qs_edit" msgid="2232596095725105230">"Endre"</string>
<string name="tuner_time" msgid="6572217313285536011">"Tid"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-nb/strings_tv.xml b/packages/SystemUI/res/values-nb/strings_tv.xml
index 921744e575cf..33bd1aa44be8 100644
--- a/packages/SystemUI/res/values-nb/strings_tv.xml
+++ b/packages/SystemUI/res/values-nb/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Hold inne "<b>"STARTSIDE"</b>" for å kontrollere PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Trykk og hold inne STARTSIDE-knappen for å kontrollere PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Greit"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Avvis"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings.xml b/packages/SystemUI/res/values-ne-rNP/strings.xml
index 3f94b38f5d54..5b139d1d1e9b 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS द्वारा स्थान सेट गरिएको"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"स्थान अनुरोधहरू सक्रिय"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"सबै सूचनाहरू हटाउनुहोस्।"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"अधिसूचना सेटिङ्हरू"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> सेटिङ्हरू"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्क्रिन स्वतः घुम्ने छ।"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"सूचना सूचीको शीर्षमा देखाउने, स्क्रिनमा चियाउने र ध्वनि निकाल्न अनुमति दिने"</string>
<string name="notification_more_settings" msgid="816306283396553571">"थप सेटिङहरू"</string>
<string name="notification_done" msgid="5279426047273930175">"सम्पन्‍न भयो"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"रंग र रूप"</string>
<string name="night_mode" msgid="3540405868248625488">"रात्री मोड"</string>
<string name="calibrate_display" msgid="5974642573432039217">"प्रदर्शनको स्तर मिलाउनुहोस्"</string>
diff --git a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
index adfb4433d361..7234d3b5fbda 100644
--- a/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
+++ b/packages/SystemUI/res/values-ne-rNP/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP लाई नियन्त्रण गर्न "<b>"गृह"</b>" कुञ्जीलाई थिचिरहनुहोस्"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"IP लाई नियन्त्रण गर्न गृह बटनलाई थिची होल्ड गर्नुहोस्"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"बुझेँ"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c1d0b5ff865e..b49cf66150ed 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locatie bepaald met GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Locatieverzoeken actief"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Alle meldingen wissen."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Instellingen voor meldingen"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>-instellingen"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Scherm wordt automatisch geroteerd."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Boven aan de lijst met meldingen weergeven, op het scherm weergeven en geluid toestaan"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Meer instellingen"</string>
<string name="notification_done" msgid="5279426047273930175">"Gereed"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"Beheeropties voor <xliff:g id="APP_NAME">%1$s</xliff:g>-meldingen"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Kleur en uiterlijk"</string>
<string name="night_mode" msgid="3540405868248625488">"Nachtmodus"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Display kalibreren"</string>
diff --git a/packages/SystemUI/res/values-nl/strings_tv.xml b/packages/SystemUI/res/values-nl/strings_tv.xml
index 8ccf464e5b04..62c364ec2d5c 100644
--- a/packages/SystemUI/res/values-nl/strings_tv.xml
+++ b/packages/SystemUI/res/values-nl/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Bedien PIP met "<b>"HOME"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Houd HOME ingedrukt om PIP te bedienen"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Sluiten"</string>
</resources>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings.xml b/packages/SystemUI/res/values-pa-rIN/strings.xml
index e529b70fb50a..f67c51a589a2 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS ਵੱਲੋਂ ਸੈਟ ਕੀਤਾ ਨਿਰਧਾਰਿਤ ਸਥਾਨ"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"ਨਿਰਧਾਰਿਤ ਸਥਾਨ ਸੇਵਾ ਬੇਨਤੀਆਂ ਸਕਿਰਿਆ"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ਸਾਰੀਆਂ ਸੂਚਨਾਵਾਂ ਹਟਾਓ।"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"ਸੂਚਨਾ ਸੈਟਿੰਗਾਂ"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ਸੈਟਿੰਗਾਂ"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"ਸਕ੍ਰੀਨ ਆਟੋਮੈਟਿਕਲੀ ਰੋਟੇਟ ਕਰੇਗੀ।"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"ਸੂਚਨਾਵਾਂ ਸੂਚੀ ਦੇ ਸਿਖਰ \'ਤੇ ਵਿਖਾਓ, ਸਕ੍ਰੀਨ \'ਤੇ ਝਲਕ ਵਿਖਾਉਣ ਅਤੇ ਧੁਨੀ ਦੀ ਮਨਜ਼ੂਰੀ ਦਿਓ"</string>
<string name="notification_more_settings" msgid="816306283396553571">"ਹੋਰ ਸੈਟਿੰਗਾਂ"</string>
<string name="notification_done" msgid="5279426047273930175">"ਹੋ ਗਿਆ"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"ਰੰਗ ਅਤੇ ਵਿਖਾਲਾ"</string>
<string name="night_mode" msgid="3540405868248625488">"ਰਾਤ ਮੋਡ"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ਡਿਸਪਲੇ ਨੂੰ ਕੈਲੀਬ੍ਰੇਟ ਕਰੋ"</string>
diff --git a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
index fafcd622c545..78a532268a10 100644
--- a/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-pa-rIN/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP ਕੰਟਰੋਲ ਕਰਨ ਲਈ "<b>"ਹੋਮ"</b>" ਦਬਾਈ ਰੱਖੋ"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP ਨੂੰ ਕੰਟਰੋਲ ਕਰਨ ਲਈ ਹੋਮ ਬਟਨ ਨੂੰ ਦੱਬੋ ਅਤੇ ਦਬਾਈ ਰੱਖੋ"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ਸਮਝ ਲਿਆ"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index ab79fc926370..12452f62fa19 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -238,6 +238,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokalizacja z GPSa"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Prośby o lokalizację są aktywne"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Usuń wszystkie powiadomienia."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Ustawienia powiadomień"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Ustawienia aplikacji <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran zostanie obrócony automatycznie."</string>
@@ -480,6 +482,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Pokazuj na początku listy powiadomień, wyświetlaj na ekranie i sygnalizuj dźwiękiem"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Więcej ustawień"</string>
<string name="notification_done" msgid="5279426047273930175">"Gotowe"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Kolor i wygląd"</string>
<string name="night_mode" msgid="3540405868248625488">"Tryb nocny"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibracja wyświetlacza"</string>
@@ -538,8 +542,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Wybierz przycisk klawiatury"</string>
<string name="preview" msgid="9077832302472282938">"Podgląd"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Przeciągnij, aby dodać kafelki"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Przeciągnij tutaj, by usunąć"</string>
<string name="qs_edit" msgid="2232596095725105230">"Edytuj"</string>
<string name="tuner_time" msgid="6572217313285536011">"Godzina"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-pl/strings_tv.xml b/packages/SystemUI/res/values-pl/strings_tv.xml
index d0371b05725a..78bb18e1c09e 100644
--- a/packages/SystemUI/res/values-pl/strings_tv.xml
+++ b/packages/SystemUI/res/values-pl/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Przytrzymaj "<b>"EKRAN GŁÓWNY"</b>", by sterować PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Przytrzymaj przycisk EKRAN GŁÓWNY, by sterować PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 6b08b8c98aae..10d3181a354f 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitações de localização ativas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Configurações de notificação"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Configurações de <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
<string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrar tela"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Escolha um botão do teclado"</string>
<string name="preview" msgid="9077832302472282938">"Visualização"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arraste para adicionar blocos"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arraste aqui para remover"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
<string name="tuner_time" msgid="6572217313285536011">"Horas"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
index 36ba02db88ba..6061af3e1d24 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Mantenha a tecla \"HOME\" pressionada para controlar o PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index a2174e99d190..7a2866d8452f 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Localização definida por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Pedidos de localização ativos"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Definições de notificação"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Definições do <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"O ecrã será rodado automaticamente."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar no ecrã e permitir som"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais definições"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aspeto"</string>
<string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrar ecrã"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
index b588c7bf7691..78d135234e54 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Prima sem soltar o botão "<b>"HOME"</b>" para controlar o PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Prima sem soltar o botão HOME para controlar o PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Compreendi"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 6b08b8c98aae..10d3181a354f 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Local definido por GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitações de localização ativas"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Configurações de notificação"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Configurações de <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"A tela girará automaticamente."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Mostrar na parte superior da lista de notificações, mostrar parcialmente na tela e permitir sons"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mais configurações"</string>
<string name="notification_done" msgid="5279426047273930175">"Concluído"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Cor e aparência"</string>
<string name="night_mode" msgid="3540405868248625488">"Modo noturno"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrar tela"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Escolha um botão do teclado"</string>
<string name="preview" msgid="9077832302472282938">"Visualização"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Arraste para adicionar blocos"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Arraste aqui para remover"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editar"</string>
<string name="tuner_time" msgid="6572217313285536011">"Horas"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-pt/strings_tv.xml b/packages/SystemUI/res/values-pt/strings_tv.xml
index 36ba02db88ba..6061af3e1d24 100644
--- a/packages/SystemUI/res/values-pt/strings_tv.xml
+++ b/packages/SystemUI/res/values-pt/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Mantenha "<b>"INÍCIO"</b>" pressionado para controlar o PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Mantenha a tecla \"HOME\" pressionada para controlar o PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Entendi"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index ddf2ff4f241d..5f71c41ec761 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -237,6 +237,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Locație setată prin GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Solicitări locație active"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ștergeți toate notificările."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Setări pentru notificări"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Setări <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ecranul se va roti în mod automat."</string>
@@ -479,6 +481,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Apar în partea de sus a listei cu notificări, se afișează pentru scurt timp pe ecran și se permite un sunet"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mai multe setări"</string>
<string name="notification_done" msgid="5279426047273930175">"Terminat"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Culoare și aspect"</string>
<string name="night_mode" msgid="3540405868248625488">"Modul Noapte"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Calibrați afișarea"</string>
@@ -537,8 +541,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Selectați butonul de la tastatură"</string>
<string name="preview" msgid="9077832302472282938">"Previzualizare"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Trageți pentru a adăuga sectoare"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Trageți aici pentru a elimina"</string>
<string name="qs_edit" msgid="2232596095725105230">"Editați"</string>
<string name="tuner_time" msgid="6572217313285536011">"Oră"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-ro/strings_tv.xml b/packages/SystemUI/res/values-ro/strings_tv.xml
index b562265481e9..fcbfd0776cbb 100644
--- a/packages/SystemUI/res/values-ro/strings_tv.xml
+++ b/packages/SystemUI/res/values-ro/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Apăsați lung "<b>"ACASĂ"</b>" pentru a controla PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Apăsați lung butonul ECRAN DE PORNIRE pentru a controla PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Am înțeles"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d723379e2b94..ffb0a7329de3 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -238,6 +238,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Координаты по GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Есть активные запросы на определение местоположения"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Удалить все уведомления"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Настройки уведомлений"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Настройки приложения \"<xliff:g id="APP_NAME">%s</xliff:g>\""</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Экран будет поворачиваться автоматически."</string>
@@ -480,6 +482,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Показывать со звуком в начале списка уведомлений и поверх всех окон"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Другие настройки"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Цвета и стиль"</string>
<string name="night_mode" msgid="3540405868248625488">"Ночной режим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Калибровка дисплея"</string>
@@ -538,8 +542,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Выберите клавишу"</string>
<string name="preview" msgid="9077832302472282938">"Просмотр"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Перетащите нужные элементы"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Чтобы удалить, перетащите сюда"</string>
<string name="qs_edit" msgid="2232596095725105230">"Изменить"</string>
<string name="tuner_time" msgid="6572217313285536011">"Время"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-ru/strings_tv.xml b/packages/SystemUI/res/values-ru/strings_tv.xml
index 30f55cbca9c9..309ce7387a11 100644
--- a/packages/SystemUI/res/values-ru/strings_tv.xml
+++ b/packages/SystemUI/res/values-ru/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Управляйте кадром в кадре, удерживая кнопку "<b>"ГЛАВНАЯ"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Управляйте режимом \"Кадр в кадре\", удерживая кнопку ГЛАВНАЯ"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"ОК"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-si-rLK/strings.xml b/packages/SystemUI/res/values-si-rLK/strings.xml
index 2a47a5537810..84c2f1b91259 100644
--- a/packages/SystemUI/res/values-si-rLK/strings.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS මඟින් ස්ථානය සකසා ඇත"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"පිහිටීම් ඉල්ලීම් සක්‍රියයි"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"සියලු දැනුම්දීම් හිස් කරන්න."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"දැනුම්දීම් සැකසීම්"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> සැකසීම්"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"තිරය ස්වයංක්‍රීයව කරකැවේ."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"දැනුම්දීම් ලැයිස්තුවෙහි ඉහළින්ම පෙන්වන්න, තිරයට එබිකම් කර ශබ්දයට ඉඩ දෙන්න"</string>
<string name="notification_more_settings" msgid="816306283396553571">"තව සැකසීම්"</string>
<string name="notification_done" msgid="5279426047273930175">"නිමයි"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"වර්ණය සහ පෙනුම"</string>
<string name="night_mode" msgid="3540405868248625488">"රාත්‍රී ප්‍රකාරය"</string>
<string name="calibrate_display" msgid="5974642573432039217">"සංදර්ශකය ක්‍රමාංකනය කරන්න"</string>
diff --git a/packages/SystemUI/res/values-si-rLK/strings_tv.xml b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
index 559d072e19a8..f3e95a160a4f 100644
--- a/packages/SystemUI/res/values-si-rLK/strings_tv.xml
+++ b/packages/SystemUI/res/values-si-rLK/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP පාලනයට "<b>"HOME"</b>" අල්ලාගන්න"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP පාලනය කිරීමට HOME බොත්තම ඔබා අල්ලාගෙන සිටින්න"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"හරි, තේරුණා"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 3178bec27ac3..e53b037e9c18 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -238,6 +238,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Poloha nastavená pomocou GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Žiadosti o polohu sú aktívne"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Vymazať všetky upozornenia."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Nastavenia upozornení"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Nastavenia aplikácie <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Obrazovka sa automaticky otočí."</string>
@@ -480,6 +482,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Zobrazovať v hornej časti zoznamu upozornení, zobrazovať cez obrazovku a povoliť zvukový signál"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Ďalšie nastavenia"</string>
<string name="notification_done" msgid="5279426047273930175">"Hotovo"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Farba a vzhľad"</string>
<string name="night_mode" msgid="3540405868248625488">"Nočný režim"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibrovať obrazovku"</string>
diff --git a/packages/SystemUI/res/values-sk/strings_tv.xml b/packages/SystemUI/res/values-sk/strings_tv.xml
index 98a67f877d5c..64fa0e8f3d49 100644
--- a/packages/SystemUI/res/values-sk/strings_tv.xml
+++ b/packages/SystemUI/res/values-sk/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Režim PIP ovládajte pomocou tlačidla "<b>"PLOCHA"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Režim PIP ovládajte stlačením a podržaním tlačidla PLOCHA"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Dobre"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index b0aa633ec3a5..8cff73b1f837 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -238,6 +238,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokacija nastavljena z GPS-om"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktivne zahteve za lokacijo"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Izbriši vsa obvestila."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Nastavitve obvestil"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Nastavitve aplikacije <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Zaslon se bo samodejno zasukal."</string>
@@ -480,6 +482,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Prikaži na vrhu seznama obvestil, za hip pokaži predogled na zaslonu in dovoli zvok"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Več nastavitev"</string>
<string name="notification_done" msgid="5279426047273930175">"Dokončano"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Barva in videz"</string>
<string name="night_mode" msgid="3540405868248625488">"Nočni način"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Umerjanje zaslona"</string>
diff --git a/packages/SystemUI/res/values-sl/strings_tv.xml b/packages/SystemUI/res/values-sl/strings_tv.xml
index 20de9c5fb30c..4d0576b2dc85 100644
--- a/packages/SystemUI/res/values-sl/strings_tv.xml
+++ b/packages/SystemUI/res/values-sl/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Pridr. "<b>"HOME"</b>" za up. n. PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Pridržite gumb HOME za upravljanje načina PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Razumem"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sq-rAL/strings.xml b/packages/SystemUI/res/values-sq-rAL/strings.xml
index 1deaee748478..35b4dc73a1a9 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Vendndodhja është caktuar nga GPS-ja"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Kërkesat për vendodhje janë aktive"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Pastro të gjitha njoftimet."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Cilësimet e njoftimeve"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Cilësimet e <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekrani do të rrotullohet automatikisht."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Shfaqi në krye të listës së njoftimeve, shfaq vështrim të shpejtë në ekran dhe lësho një tingull"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Cilësime të tjera"</string>
<string name="notification_done" msgid="5279426047273930175">"U krye"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Ngjyra dhe pamja"</string>
<string name="night_mode" msgid="3540405868248625488">"Modaliteti i natës"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibro ekranin"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Zgjidh butonin e tastierës"</string>
<string name="preview" msgid="9077832302472282938">"Pamja paraprake"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Zvarrit për të shtuar pllakëzat"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Zvarrit këtu për ta hequr"</string>
<string name="qs_edit" msgid="2232596095725105230">"Redakto"</string>
<string name="tuner_time" msgid="6572217313285536011">"Ora"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
index 481662ffabd4..bcb53fc6b759 100644
--- a/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
+++ b/packages/SystemUI/res/values-sq-rAL/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Mbaj shtypur "<b>"HOME"</b>" për të kontrolluar PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Shtyp dhe mbaj shtypur butonin HOME për të kontrolluar PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"E kuptova"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 0f2418873ddd..5bc07fa1fb8f 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -237,6 +237,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Локацију је подесио GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Има активних захтева за локацију"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Обриши сва обавештења."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Подешавања обавештења"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Подешавања за <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран ће се аутоматски ротирати."</string>
@@ -479,6 +481,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Приказују се у врху листе обавештења, накратко се приказују на екрану и емитују звук"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Још подешавања"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Боја и изглед"</string>
<string name="night_mode" msgid="3540405868248625488">"Ноћни режим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Калибришите екран"</string>
@@ -537,8 +541,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Изаберите дугме за тастатуру"</string>
<string name="preview" msgid="9077832302472282938">"Преглед"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Превуците да бисте додали плочице"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Превуците овде да бисте уклонили"</string>
<string name="qs_edit" msgid="2232596095725105230">"Измени"</string>
<string name="tuner_time" msgid="6572217313285536011">"Време"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-sr/strings_tv.xml b/packages/SystemUI/res/values-sr/strings_tv.xml
index eed8f51c6d80..a92374f44f43 100644
--- a/packages/SystemUI/res/values-sr/strings_tv.xml
+++ b/packages/SystemUI/res/values-sr/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109"><b>"ПОЧЕТНИ ЕКРАН"</b>" конт. PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Притисните и задржите дугме ПОЧЕТНИ ЕКРАН да бисте контролисали PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Важи"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 76003188fba1..7e40ce03521f 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Platsen har identifierats av GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Det finns aktiva platsbegäranden"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Ta bort alla meddelanden."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Aviseringsinställningar"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Inställningar för <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skärmen roteras automatiskt."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Visa högst upp i aviseringslistan och med snabbtitt på skärmen samt tillåt ljud"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Fler inställningar"</string>
<string name="notification_done" msgid="5279426047273930175">"Klar"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Färg och utseende"</string>
<string name="night_mode" msgid="3540405868248625488">"Nattläge"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Kalibrera skärmen"</string>
diff --git a/packages/SystemUI/res/values-sv/strings_tv.xml b/packages/SystemUI/res/values-sv/strings_tv.xml
index 2b2c5c282a4e..790ef76507c6 100644
--- a/packages/SystemUI/res/values-sv/strings_tv.xml
+++ b/packages/SystemUI/res/values-sv/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Styr PIP med "<b>"startknappen"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Styr bild-i-bild genom att hålla ned startsideknappen"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 8554da221767..aa9ed8a903c4 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Mahali pamewekwa na GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Maombi ya eneo yanatumika"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Futa arifa zote."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Mipangilio ya arifa"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Mipangilio ya <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Skrini itazunguka kiotomatiki."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Onyesha katika sehemu ya juu ya orodha ya arifa, chungulia kwenye skrini na uruhusu sauti"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Mipangilio zaidi"</string>
<string name="notification_done" msgid="5279426047273930175">"Nimemaliza"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Rangi na mwonekano"</string>
<string name="night_mode" msgid="3540405868248625488">"Hali ya usiku"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Rekebisha onyesho"</string>
diff --git a/packages/SystemUI/res/values-sw/strings_tv.xml b/packages/SystemUI/res/values-sw/strings_tv.xml
index 337c1360f3cf..bd297054895d 100644
--- a/packages/SystemUI/res/values-sw/strings_tv.xml
+++ b/packages/SystemUI/res/values-sw/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Shikilia kitufe cha "<b>"HOME"</b>" ili udhibiti PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Bonyeza na ushikilie kitufe cha HOME ili kudhibiti PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Nimeelewa"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index db4da10756ed..1f6bbd342b39 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -33,16 +33,6 @@
<!-- Set to true to enable the user switcher on the keyguard. -->
<bool name="config_keyguardUserSwitcher">true</bool>
- <!-- Recents: The relative range of visible tasks from the current scroll position
- while the stack is focused. -->
- <item name="recents_layout_focused_range_min" format="float" type="integer">-3</item>
- <item name="recents_layout_focused_range_max" format="float" type="integer">3</item>
-
- <!-- Recents: The relative range of visible tasks from the current scroll position
- while the stack is not focused. -->
- <item name="recents_layout_unfocused_range_min" format="float" type="integer">-2</item>
- <item name="recents_layout_unfocused_range_max" format="float" type="integer">2.5</item>
-
<!-- Nav bar button default ordering/layout -->
<string name="config_navBarLayout" translatable="false">space;back,home,recent;menu_ime</string>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 66963c43e8dc..a2010be4f6a1 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -96,15 +96,6 @@
<dimen name="qs_expand_margin">0dp</dimen>
- <!-- The top padding for the task stack. -->
- <dimen name="recents_stack_top_padding">40dp</dimen>
-
- <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
- <dimen name="recents_initial_bottom_peek_size">100dp</dimen>
-
- <!-- The side padding for the task stack. -->
- <dimen name="recents_stack_left_right_padding">64dp</dimen>
-
<!-- Keyboard shortcuts helper -->
<dimen name="ksh_layout_width">488dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values-sw720dp/dimens.xml b/packages/SystemUI/res/values-sw720dp/dimens.xml
index 8fe6be93917a..25e96c8848db 100644
--- a/packages/SystemUI/res/values-sw720dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw720dp/dimens.xml
@@ -29,11 +29,6 @@
<!-- Bottom margin (from display edge) for status bar panels -->
<dimen name="panel_float">56dp</dimen>
- <!-- The radius of the rounded corners on a task view. -->
- <dimen name="recents_task_view_rounded_corners_radius">3dp</dimen>
- <!-- The radius of the rounded corners on a task view's shadow. -->
- <dimen name="recents_task_view_shadow_rounded_corners_radius">12dp</dimen>
-
<!-- The fraction of the screen height where the clock on the Keyguard has its center. The
max value is used when no notifications are displaying, and the min value is when the
highest possible number of notifications are showing. -->
diff --git a/packages/SystemUI/res/values-ta-rIN/strings.xml b/packages/SystemUI/res/values-ta-rIN/strings.xml
index 1463449e42bb..3eb7565308c8 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS அமைத்த இருப்பிடம்"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"இருப்பிடக் கோரிக்கைகள் இயக்கப்பட்டன"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"எல்லா அறிவிப்புகளையும் அழி."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"அறிவிப்பு அமைப்புகள்"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> அமைப்புகள்"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"திரை தானாகச் சுழலும்."</string>
@@ -301,7 +303,7 @@
<string name="quick_settings_cellular_detail_data_limit" msgid="56011158504994128">"<xliff:g id="DATA_LIMIT">%s</xliff:g> வரம்பு"</string>
<string name="quick_settings_cellular_detail_data_warning" msgid="2440098045692399009">"<xliff:g id="DATA_LIMIT">%s</xliff:g> எச்சரிக்கை"</string>
<string name="quick_settings_work_mode_label" msgid="6244915274350490429">"பணிப் பயன்முறை"</string>
- <string name="recents_empty_message" msgid="808480104164008572">"சமீபத்திய செய்திகள் இல்லை"</string>
+ <string name="recents_empty_message" msgid="808480104164008572">"சமீபத்திய பணிகள் இல்லை"</string>
<string name="recents_empty_message_dismissed_all" msgid="2791312568666558651">"எல்லாவற்றையும் அழித்துவிட்டீர்கள்"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"பயன்பாட்டு தகவல்"</string>
<string name="recents_lock_to_app_button_label" msgid="6942899049072506044">"திரையை பின் செய்தல்"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"அறிவிப்புகள் பட்டியலின் மேற்பகுதியில், சில வினாடிகளுக்கு ஒலியுடன் திரையில் காட்டு"</string>
<string name="notification_more_settings" msgid="816306283396553571">"மேலும் அமைப்புகள்"</string>
<string name="notification_done" msgid="5279426047273930175">"முடிந்தது"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"வண்ணமும் தோற்றமும்"</string>
<string name="night_mode" msgid="3540405868248625488">"இரவுப் பயன்முறை"</string>
<string name="calibrate_display" msgid="5974642573432039217">"திரையை அளவுத்திருத்தம் செய்"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"விசைப்பலகைப் பொத்தானைத் தேர்ந்தெடுக்கவும்"</string>
<string name="preview" msgid="9077832302472282938">"மாதிரிக்காட்சி"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"கட்டங்களைச் சேர்க்க, இழுக்கவும்"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"அகற்ற, இங்கே இழுக்கவும்"</string>
<string name="qs_edit" msgid="2232596095725105230">"மாற்று"</string>
<string name="tuner_time" msgid="6572217313285536011">"நேரம்"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
index 20e30f737a9d..e75d86aa5638 100644
--- a/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-ta-rIN/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIPஐக் கட்டுப்படுத்த, "<b>"முகப்பைப்"</b>" பிடித்திருக்கவும்"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIPஐக் கட்டுப்படுத்த, முகப்புப் பொத்தானை அழுத்திப் பிடிக்கவும்"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"சரி"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-te-rIN/strings.xml b/packages/SystemUI/res/values-te-rIN/strings.xml
index ffb59a12ecdf..4a6e2d787683 100644
--- a/packages/SystemUI/res/values-te-rIN/strings.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"స్థానం GPS ద్వారా సెట్ చేయబడింది"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"స్థాన అభ్యర్థనలు సక్రియంగా ఉన్నాయి"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"అన్ని నోటిఫికేషన్‌లను క్లియర్ చేయండి."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"నోటిఫికేషన్ సెట్టింగ్‌లు"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> సెట్టింగ్‌లు"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"స్క్రీన్ స్వయంచాలకంగా తిప్పబడుతుంది."</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"నోటిఫికేషన్‌ల జాబితా అగ్ర భాగాన, స్క్రీన్‌పై శీఘ్రంగా శబ్దంతో చూపుతుంది"</string>
<string name="notification_more_settings" msgid="816306283396553571">"మరిన్ని సెట్టింగ్‌లు"</string>
<string name="notification_done" msgid="5279426047273930175">"పూర్తయింది"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"<xliff:g id="APP_NAME">%1$s</xliff:g> నోటిఫికేషన్ నియంత్రణలు"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"రంగు మరియు కనిపించే తీరు"</string>
<string name="night_mode" msgid="3540405868248625488">"రాత్రి మోడ్"</string>
<string name="calibrate_display" msgid="5974642573432039217">"డిస్‌ప్లేని క్రమాంకనం చేయండి"</string>
diff --git a/packages/SystemUI/res/values-te-rIN/strings_tv.xml b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
index 7ce24cb4fdc1..32820c3aba13 100644
--- a/packages/SystemUI/res/values-te-rIN/strings_tv.xml
+++ b/packages/SystemUI/res/values-te-rIN/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP నియం. "<b>"HOME"</b>"నొక్కిఉంచండి"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIPని నియంత్రించడానికి హోమ్ బటన్‌ను నొక్కి పట్టుకోండి"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"అర్థమైంది"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"తీసివేస్తుంది"</string>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index a5134392b714..33e4346f3b9f 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"ตำแหน่งที่กำหนดโดย GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"คำขอตำแหน่งที่มีการใช้งาน"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"ล้างการแจ้งเตือนทั้งหมด"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"การตั้งค่าการแจ้งเตือน"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"การตั้งค่า <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"หน้าจอจะหมุนโดยอัตโนมัติ"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"แสดงที่ด้านบนของรายการการแจ้งเตือน แสดงบนหน้าจอและให้ส่งเสียงได้"</string>
<string name="notification_more_settings" msgid="816306283396553571">"การตั้งค่าเพิ่มเติม"</string>
<string name="notification_done" msgid="5279426047273930175">"เสร็จสิ้น"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"สีและลักษณะที่ปรากฏ"</string>
<string name="night_mode" msgid="3540405868248625488">"โหมดกลางคืน"</string>
<string name="calibrate_display" msgid="5974642573432039217">"ปรับเทียบการแสดงผล"</string>
diff --git a/packages/SystemUI/res/values-th/strings_tv.xml b/packages/SystemUI/res/values-th/strings_tv.xml
index b5d522ed8024..b43078d89d59 100644
--- a/packages/SystemUI/res/values-th/strings_tv.xml
+++ b/packages/SystemUI/res/values-th/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"กด "<b>"HOME"</b>" ค้างไว้เพื่อควบคุม PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"กดปุ่ม HOME ค้างไว้เพื่อควบคุม PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"รับทราบ"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 16a69928c1a8..61eaa9d05df4 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Lokasyong itinatakda ng GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Aktibo ang mga kahilingan ng lokasyon"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"I-clear ang lahat ng notification."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Mga setting ng notification"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Mg setting ng <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Awtomatikong iikot ang screen."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Ipakita sa itaas ng listahan ng mga notification, palitawin sa screen at payagang tumunog"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Higit pang mga setting"</string>
<string name="notification_done" msgid="5279426047273930175">"Tapos Na"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Kulay at hitsura"</string>
<string name="night_mode" msgid="3540405868248625488">"Night mode"</string>
<string name="calibrate_display" msgid="5974642573432039217">"I-calibrate ang display"</string>
diff --git a/packages/SystemUI/res/values-tl/strings_tv.xml b/packages/SystemUI/res/values-tl/strings_tv.xml
index c084170890f4..8d4b1b0ff013 100644
--- a/packages/SystemUI/res/values-tl/strings_tv.xml
+++ b/packages/SystemUI/res/values-tl/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"I-hold ang "<b>"HOME"</b>" para makontrol ang PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Pindutin nang matagal ang button ng HOME upang makontrol ang PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index b0edefa543cc..d5a8b9b52107 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Konum GPS ile belirlendi"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Konum bilgisi istekleri etkin"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Tüm bildirimleri temizle"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Bildirim ayarları"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ayarları"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran otomatik olarak dönecektir."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Bildirim listesinin üstünde göster, ekrana getir ve sesli bildirime izin ver"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Diğer ayarlar"</string>
<string name="notification_done" msgid="5279426047273930175">"Bitti"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Renk ve görünüm"</string>
<string name="night_mode" msgid="3540405868248625488">"Gece modu"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Ekranı kalibre et"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Klavye Düğmesini Seçin"</string>
<string name="preview" msgid="9077832302472282938">"Önizle"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Blok eklemek için sürükleyin"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Kaldırmak için buraya sürükleyin"</string>
<string name="qs_edit" msgid="2232596095725105230">"Düzenle"</string>
<string name="tuner_time" msgid="6572217313285536011">"Saat"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-tr/strings_tv.xml b/packages/SystemUI/res/values-tr/strings_tv.xml
index 07fa9a5d514e..a5be6a2f0e09 100644
--- a/packages/SystemUI/res/values-tr/strings_tv.xml
+++ b/packages/SystemUI/res/values-tr/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"PIP\'yi kontrol etmek için "<b>"ANA EKRAN"</b>"\'ı basılı tutun"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"PIP\'yi kontrol etmek için ANA EKRAN düğmesini basılı tutun"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Anladım"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 02e9a7fa31b9..398dea1194e2 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -238,6 +238,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Місцезнаходження встановлено за допомогою GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Запити про місцезнаходження активні"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Очистити всі сповіщення."</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Налаштування сповіщень"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Налаштування додатка <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Екран обертатиметься автоматично."</string>
@@ -480,6 +481,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Показувати сповіщення вгорі списку, на екрані та зі звуковим сигналом"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Більше налаштувань"</string>
<string name="notification_done" msgid="5279426047273930175">"Готово"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"Елементи керування сповіщеннями додатка <xliff:g id="APP_NAME">%1$s</xliff:g>"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"Колір і вигляд"</string>
<string name="night_mode" msgid="3540405868248625488">"Нічний режим"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Калібрувати дисплей"</string>
@@ -538,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"Вибрати кнопку клавіатури"</string>
<string name="preview" msgid="9077832302472282938">"Переглянути"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"Перетягуйте фрагменти, щоб додавати їх"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"Перетягніть сюди, щоб видалити"</string>
<string name="qs_edit" msgid="2232596095725105230">"Редагувати"</string>
<string name="tuner_time" msgid="6572217313285536011">"Час"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-uk/strings_tv.xml b/packages/SystemUI/res/values-uk/strings_tv.xml
index dcb7a52ccbad..1091547b917e 100644
--- a/packages/SystemUI/res/values-uk/strings_tv.xml
+++ b/packages/SystemUI/res/values-uk/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"Щоб керувати PIP, утримуйте кнопку "<b>"ГОЛОВНИЙ ЕКРАН"</b></string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Щоб керувати PIP, утримуйте кнопку \"ГОЛОВНИЙ ЕКРАН\""</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"Закрити"</string>
</resources>
diff --git a/packages/SystemUI/res/values-ur-rPK/strings.xml b/packages/SystemUI/res/values-ur-rPK/strings.xml
index e4a84f81b1c5..7b5013fe4f7e 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"‏مقام متعین کیا گیا بذریعہ GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"مقام کی درخواستیں فعال ہیں"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"سبھی اطلاعات صاف کریں۔"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"اطلاع کی ترتیبات"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> ترتیبات"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"اسکرین خود بخود گردش کرے گی۔"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"اطلاعات کی فہرست پر سب سے اوپر دکھائیں، اسکرین پر دکھائیں اور آواز کی اجازت دیں"</string>
<string name="notification_more_settings" msgid="816306283396553571">"مزید ترتیبات"</string>
<string name="notification_done" msgid="5279426047273930175">"ہوگیا"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"رنگ اور ظہور"</string>
<string name="night_mode" msgid="3540405868248625488">"رات موڈ"</string>
<string name="calibrate_display" msgid="5974642573432039217">"نشان زد ڈسپلے"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"کی بورڈ بٹن منتخب کریں"</string>
<string name="preview" msgid="9077832302472282938">"پیش منظر"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"ٹائٹلز شامل کرنے کیلئے گھسیٹیں"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"ہٹانے کیلئے یہاں گھسیٹیں؟"</string>
<string name="qs_edit" msgid="2232596095725105230">"ترمیم کریں"</string>
<string name="tuner_time" msgid="6572217313285536011">"وقت"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
index 4216e9e85d5e..aff14b29f10b 100644
--- a/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
+++ b/packages/SystemUI/res/values-ur-rPK/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"‏PIP کنٹرول کرنے کیلئے "<b>"ہوم"</b>" پکڑے رکھیں"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"‏PIP کنٹرول کرنے کیلئے ہوم بٹن دبائیں اور پکڑے رکھیں"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"سمجھ آ گئی"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings.xml b/packages/SystemUI/res/values-uz-rUZ/strings.xml
index 22eccca9d7d7..bd606c210c32 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS yordamida manzilni o‘rnatish"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Joylashuv so‘rovlari yoniq"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Barcha eslatmalarni tozalash."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Bildirishnoma sozlamalari"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> sozlamalari"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Ekran avtomatik buriladi."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Bildirishnomalar ro‘yxatining boshida va barcha oynalar ustida ovoz bilan ko‘rsatilsin"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Boshqa sozlamalar"</string>
<string name="notification_done" msgid="5279426047273930175">"Tayyor"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Rang va ko‘rinishi"</string>
<string name="night_mode" msgid="3540405868248625488">"Tungi rejim"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Ekranni kalibrlash"</string>
diff --git a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
index d9db7d233b3d..3a4d17625459 100644
--- a/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
+++ b/packages/SystemUI/res/values-uz-rUZ/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"“Kadr ichida kadr” rejimini boshqarish uchun "<b>"BOSHI"</b>" tugmasini bosib turing"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"“Kadr ichida kadr” rejimini boshqarish uchun BOSHIGA tugmasini bosib turing"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index bc570cae303e..edd0a8bec156 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Vị trí đặt bởi GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Yêu cầu về thông tin vị trí đang hoạt động"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Xóa tất cả thông báo."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Cài đặt thông báo"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"Cài đặt <xliff:g id="APP_NAME">%s</xliff:g>"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Màn hình sẽ xoay tự động."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Hiển thị ở đầu danh sách thông báo, hiển thị trên màn hình và phát ra âm thanh"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Cài đặt khác"</string>
<string name="notification_done" msgid="5279426047273930175">"Xong"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Màu sắc và giao diện"</string>
<string name="night_mode" msgid="3540405868248625488">"Chế độ ban đêm"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Hiệu chỉnh hiển thị"</string>
diff --git a/packages/SystemUI/res/values-vi/strings_tv.xml b/packages/SystemUI/res/values-vi/strings_tv.xml
index 7bc921b8f9a1..7a5e34ad5c8d 100644
--- a/packages/SystemUI/res/values-vi/strings_tv.xml
+++ b/packages/SystemUI/res/values-vi/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Giữ "<b>"HOME"</b>" để đ.khiển PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Bấm và giữ nút HOME để điều khiển PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"OK"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 4004521f8e17..23fb020400c1 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"已通过GPS确定位置"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"应用发出了有效位置信息请求"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"通知设置"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>设置"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"屏幕会自动旋转。"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"在通知列表顶部显示,同时在屏幕上短暂显示,并允许发出提示音"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多设置"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"颜色和外观"</string>
<string name="night_mode" msgid="3540405868248625488">"夜间模式"</string>
<string name="calibrate_display" msgid="5974642573432039217">"校准显示画面"</string>
@@ -536,8 +540,7 @@
<string name="select_keycode" msgid="7413765103381924584">"选择键盘按钮"</string>
<string name="preview" msgid="9077832302472282938">"预览"</string>
<string name="drag_to_add_tiles" msgid="7058945779098711293">"拖动即可添加图块"</string>
- <!-- no translation found for drag_to_remove_tiles (3361212377437088062) -->
- <skip />
+ <string name="drag_to_remove_tiles" msgid="3361212377437088062">"拖动到此处即可移除"</string>
<string name="qs_edit" msgid="2232596095725105230">"修改"</string>
<string name="tuner_time" msgid="6572217313285536011">"时间"</string>
<string-array name="clock_options">
diff --git a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
index 5071622ba050..2bfe478e799b 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"按住"<b>"主屏幕"</b>"按钮即可控制画中画功能"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"按住主屏幕按钮即可控制画中画功能"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index f2e4687622df..902cf714c99d 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -236,6 +236,7 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"位置要求啟動中"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
+ <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"通知設定"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>設定"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
@@ -478,6 +479,7 @@
<string name="notification_importance_max" msgid="5806278962376556491">"在通知清單頂部顯示,並不時於螢幕出現及發出音效"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
+ <string name="notification_gear_accessibility" msgid="94429150213089611">"「<xliff:g id="APP_NAME">%1$s</xliff:g>」通知控制項"</string>
<string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
<string name="night_mode" msgid="3540405868248625488">"夜間模式"</string>
<string name="calibrate_display" msgid="5974642573432039217">"校準螢幕"</string>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
index 4485449a6ca6..10c3141c4696 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings_tv.xml
@@ -26,4 +26,5 @@
<string name="pip_hold_home" msgid="340086535668778109">"按住"<b>"主按鈕"</b>"即可控制 PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"按住主按鈕即可控制 PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"知道了"</string>
+ <string name="recents_tv_dismiss" msgid="3555093879593377731">"關閉"</string>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 8d0a092e8e51..ea3293078763 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"GPS 已定位"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"有位置資訊要求"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"清除所有通知。"</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"通知設定"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g>設定"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"螢幕會自動旋轉。"</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"顯示在通知清單頂端,同時短暫顯示在畫面上並發出音效"</string>
<string name="notification_more_settings" msgid="816306283396553571">"更多設定"</string>
<string name="notification_done" msgid="5279426047273930175">"完成"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"顏色和外觀"</string>
<string name="night_mode" msgid="3540405868248625488">"夜間模式"</string>
<string name="calibrate_display" msgid="5974642573432039217">"校正顯示畫面"</string>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
index 22f72c455f01..a6744e7e31f2 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"按住「主畫面」"<b></b>"按鈕即可控制子母畫面"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"按住「主畫面」按鈕即可控制子母畫面"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"我知道了"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index ed379c0a20a3..9f8f29801408 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -236,6 +236,8 @@
<string name="gps_notification_found_text" msgid="4619274244146446464">"Indawo ihlelwe i-GPS"</string>
<string name="accessibility_location_active" msgid="2427290146138169014">"Izicelo zendawo ziyasebenza"</string>
<string name="accessibility_clear_all" msgid="5235938559247164925">"Susa zonke izaziso."</string>
+ <!-- no translation found for notification_group_overflow_indicator (1863231301642314183) -->
+ <skip />
<string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Izilungiselelo zesaziso"</string>
<string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> izilungiselelo"</string>
<string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"Isikrini sizophenduka ngokuzenzakalela."</string>
@@ -478,6 +480,8 @@
<string name="notification_importance_max" msgid="5806278962376556491">"Bonisa phezulu kohlu lwezaziso, beka phezu kwesikrini futhi uvumele umsindo"</string>
<string name="notification_more_settings" msgid="816306283396553571">"Izilungiselelo eziningi"</string>
<string name="notification_done" msgid="5279426047273930175">"Kwenziwe"</string>
+ <!-- no translation found for notification_gear_accessibility (94429150213089611) -->
+ <skip />
<string name="color_and_appearance" msgid="1254323855964993144">"Umbala nokubonakala"</string>
<string name="night_mode" msgid="3540405868248625488">"Imodi yasebusuku"</string>
<string name="calibrate_display" msgid="5974642573432039217">"Sika isibonisi"</string>
diff --git a/packages/SystemUI/res/values-zu/strings_tv.xml b/packages/SystemUI/res/values-zu/strings_tv.xml
index b0105560d877..5fb063d75a27 100644
--- a/packages/SystemUI/res/values-zu/strings_tv.xml
+++ b/packages/SystemUI/res/values-zu/strings_tv.xml
@@ -26,4 +26,6 @@
<string name="pip_hold_home" msgid="340086535668778109">"Bamba "<b>"IKHAYA"</b>" ukuze ulawule i-PIP"</string>
<string name="pip_onboarding_description" msgid="2882896641362814195">"Cindezela futhi ubambe inkinobho EKHAYA ukuze ulawule i-PIP"</string>
<string name="pip_onboarding_button" msgid="3957426748484904611">"Ngiyezwa"</string>
+ <!-- no translation found for recents_tv_dismiss (3555093879593377731) -->
+ <skip />
</resources>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index e040ab26f97a..1e979fda17bd 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -85,7 +85,7 @@
<attr name="ignoreRightInset" format="boolean" />
</declare-styleable>
- <declare-styleable name="AlphaOptimizedImageView">
+ <declare-styleable name="AnimatedImageView">
<attr name="hasOverlappingRendering" format="boolean" />
</declare-styleable>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index a3f8b8551def..4f3db05aca58 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -63,7 +63,7 @@
<!-- The recents task bar dark text color to be drawn on top of light backgrounds. -->
<color name="recents_task_bar_dark_text_color">#cc000000</color>
<!-- The recents task bar light dismiss icon color to be drawn on top of dark backgrounds. -->
- <color name="recents_task_bar_light_icon_color">#ffeeeeee</color>
+ <color name="recents_task_bar_light_icon_color">#ccffffff</color>
<!-- The recents task bar dark dismiss icon color to be drawn on top of light backgrounds. -->
<color name="recents_task_bar_dark_icon_color">#99000000</color>
<!-- The lock to task button background color. -->
@@ -79,7 +79,7 @@
<color name="notification_legacy_background_color">#ff1a1a1a</color>
<!-- The color of the material notification background -->
- <color name="notification_material_background_color">#ffffffff</color>
+ <color name="notification_material_background_color">@*android:color/notification_material_background_color</color>
<!-- The color of the material notification background when dimmed -->
<color name="notification_material_background_dimmed_color">#ccffffff</color>
@@ -153,7 +153,7 @@
<color name="docked_divider_handle">#ffffff</color>
<color name="default_remote_input_background">@*android:color/notification_default_color</color>
- <color name="remote_input_hint">#4dffffff</color>
+ <color name="remote_input_hint">#99ffffff</color>
<color name="remote_input_accent">#eeeeee</color>
diff --git a/packages/SystemUI/res/values/colors_tv.xml b/packages/SystemUI/res/values/colors_tv.xml
index af99aaecf62a..4126d3cdad68 100644
--- a/packages/SystemUI/res/values/colors_tv.xml
+++ b/packages/SystemUI/res/values/colors_tv.xml
@@ -19,4 +19,5 @@
<resources>
<color name="recents_tv_card_background_color">#FF37474F</color>
<color name="recents_tv_card_title_text_color">#CCEEEEEE</color>
+ <color name="recents_tv_dismiss_text_color">#7FEEEEEE</color>
</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 4e1680d54653..622ae717058c 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -86,9 +86,6 @@
<bool name="config_dead_zone_flash">false</bool>
- <!-- Min alpha % that recent items will fade to while being dismissed -->
- <integer name="config_recent_item_min_alpha">3</integer>
-
<!-- Whether QuickSettings is in a phone landscape -->
<bool name="quick_settings_wide">false</bool>
@@ -165,9 +162,6 @@
<!-- The animation duration for subsequent scrolling the stack to a particular item. -->
<integer name="recents_subsequent_auto_advance_duration">1000</integer>
- <!-- The animation duration for entering and exiting the history. -->
- <integer name="recents_history_transition_duration">250</integer>
-
<!-- The delay to enforce between each alt-tab key press. -->
<integer name="recents_alt_tab_key_delay">200</integer>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 8b433f984d65..541748035a5a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -234,85 +234,6 @@
<!-- Default distance from each snap target that GlowPadView considers a "hit" -->
<dimen name="glowpadview_inner_radius">15dip</dimen>
- <!-- The size of the icon in the recents task view header. -->
- <dimen name="recents_task_view_header_icon_width">56dp</dimen>
- <dimen name="recents_task_view_header_icon_height">@dimen/recents_task_bar_height</dimen>
-
- <!-- The size of a button in the recents task view header. -->
- <dimen name="recents_task_view_header_button_width">@dimen/recents_task_bar_height</dimen>
- <dimen name="recents_task_view_header_button_height">@dimen/recents_task_bar_height</dimen>
-
- <!-- The radius of the rounded corners on a task view. -->
- <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
- <!-- The radius of the rounded corners on a task view's shadow. -->
- <dimen name="recents_task_view_shadow_rounded_corners_radius">12dp</dimen>
-
- <!-- The min translation in the Z index for the last task. -->
- <dimen name="recents_task_view_z_min">3dp</dimen>
-
- <!-- The max translation in the Z index for the last task. -->
- <dimen name="recents_task_view_z_max">24dp</dimen>
-
- <!-- The amount to translate when animating the removal of a task. -->
- <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
-
- <!-- The amount of highlight to make on each task view. -->
- <dimen name="recents_task_view_highlight">1dp</dimen>
-
- <!-- The amount to offset when animating into an affiliate group. -->
- <dimen name="recents_task_view_affiliate_group_enter_offset">32dp</dimen>
-
- <!-- The height of a task view bar. -->
- <dimen name="recents_task_bar_height">50dp</dimen>
-
- <!-- The height of the search bar space. -->
- <dimen name="recents_search_bar_space_height">64dp</dimen>
-
- <!-- The overscroll percentage allowed on the stack. -->
- <item name="recents_stack_overscroll_percentage" format="float" type="dimen">0.0875</item>
-
- <!-- The top padding for the task stack. -->
- <dimen name="recents_stack_top_padding">16dp</dimen>
-
- <!-- The side padding for the task stack. -->
- <dimen name="recents_stack_left_right_padding">16dp</dimen>
-
- <!-- The dimesnsions of the dismiss all recents button. -->
- <dimen name="recents_dismiss_all_button_size">48dp</dimen>
-
- <!-- The min alpha to apply to a task affiliation group color. -->
- <item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
-
- <!-- The size of the lock-to-app button. -->
- <dimen name="recents_lock_to_app_size">56dp</dimen>
-
- <!-- The size of the lock-to-app button icon. -->
- <dimen name="recents_lock_to_app_icon_size">28dp</dimen>
-
- <!-- The amount to allow the stack to overscroll. -->
- <dimen name="recents_stack_overscroll">24dp</dimen>
-
- <!-- The size of the initial peek area at the top of the stack (below the status bar). -->
- <dimen name="recents_initial_top_peek_size">8dp</dimen>
-
- <!-- The size of the initial peek area at the bottom of the stack (above the nav bar). -->
- <dimen name="recents_initial_bottom_peek_size">100dp</dimen>
-
- <!-- The size of the peek area at the top of the stack (below the status bar). -->
- <dimen name="recents_layout_focused_top_peek_size">@dimen/recents_history_button_height</dimen>
-
- <!-- The size of each task peek area at the bottom of the stack (above the nav bar). -->
- <dimen name="recents_layout_focused_bottom_task_peek_size">16dp</dimen>
-
- <!-- The height of the history button. -->
- <dimen name="recents_history_button_height">48dp</dimen>
-
- <!-- The padding between freeform workspace tasks -->
- <dimen name="recents_freeform_workspace_task_padding">8dp</dimen>
-
- <!-- The offsets the tasks animate from when recents is launched while docking -->
- <dimen name="recents_task_view_launched_while_docking_offset">144dp</dimen>
-
<!-- Space reserved for the cards behind the top card in the bottom stack -->
<dimen name="bottom_stack_peek_amount">12dp</dimen>
@@ -397,9 +318,6 @@
<!-- The padding on top of the first notification to the children container -->
<dimen name="notification_children_container_top_padding">8dp</dimen>
- <!-- The vertical distance from which the notification appear when children are expanded -->
- <dimen name="notification_appear_distance">140dp</dimen>
-
<!-- end margin for multi user switch in expanded quick settings -->
<dimen name="multi_user_switch_expanded_margin">8dp</dimen>
@@ -642,4 +560,85 @@
<!-- Keyboard shortcuts helper -->
<dimen name="ksh_layout_width">@dimen/match_parent</dimen>
+
+<!-- Recents Layout -->
+
+ <!-- The amount to inset the stack, specifically at the top and the other sides. We also
+ don't want this to change across configurations that Recents can be opened in, so we
+ define them statically for all display sizes. -->
+ <dimen name="recents_layout_min_margin">16dp</dimen>
+ <dimen name="recents_layout_top_margin_phone">16dp</dimen>
+ <dimen name="recents_layout_top_margin_tablet">32dp</dimen>
+ <dimen name="recents_layout_top_margin_tablet_xlarge">40dp</dimen>
+ <dimen name="recents_layout_bottom_margin">16dp</dimen>
+ <dimen name="recents_layout_side_margin_phone">16dp</dimen>
+ <dimen name="recents_layout_side_margin_tablet">48dp</dimen>
+ <dimen name="recents_layout_side_margin_tablet_xlarge">64dp</dimen>
+
+ <!-- The height between the top margin and the top of the focused task. -->
+ <dimen name="recents_layout_top_peek_size">56dp</dimen>
+ <!-- The height between the bottom margin and the top of task in front of the focused task. -->
+ <dimen name="recents_layout_bottom_peek_size">56dp</dimen>
+
+ <!-- The offset from the top and bottom of the stack of the focused task. The bottom offset
+ will be additionally offset by the bottom system insets since it goes under the nav bar
+ in certain orientations. -->
+ <dimen name="recents_layout_initial_top_offset_phone_port">128dp</dimen>
+ <dimen name="recents_layout_initial_bottom_offset_phone_port">80dp</dimen>
+ <dimen name="recents_layout_initial_top_offset_phone_land">72dp</dimen>
+ <dimen name="recents_layout_initial_bottom_offset_phone_land">72dp</dimen>
+ <dimen name="recents_layout_initial_top_offset_tablet">160dp</dimen>
+ <dimen name="recents_layout_initial_bottom_offset_tablet">112dp</dimen>
+
+ <!-- The min/max translationZ for the tasks in the stack. -->
+ <dimen name="recents_layout_z_min">3dp</dimen>
+ <dimen name="recents_layout_z_max">24dp</dimen>
+
+ <!-- The margin between the freeform and stack. We also don't want this to change across
+ configurations that Recents can be opened in, so we define them statically for all
+ display sizes. -->
+ <dimen name="recents_freeform_layout_bottom_margin">16dp</dimen>
+
+ <!-- The padding between each freeform task. -->
+ <dimen name="recents_freeform_layout_task_padding">8dp</dimen>
+
+<!-- Recents Views -->
+
+ <!-- The height of a task view bar. -->
+ <dimen name="recents_task_view_header_height">56dp</dimen>
+
+ <!-- The size of the icon in the recents task view header. -->
+ <dimen name="recents_task_view_header_icon_width">@dimen/recents_task_view_header_height</dimen>
+ <dimen name="recents_task_view_header_icon_height">@dimen/recents_task_view_header_height</dimen>
+
+ <!-- The size of a button in the recents task view header. -->
+ <dimen name="recents_task_view_header_button_width">@dimen/recents_task_view_header_height</dimen>
+ <dimen name="recents_task_view_header_button_height">@dimen/recents_task_view_header_height</dimen>
+
+ <!-- The radius of the rounded corners on a task view and its shadow (which can be larger
+ to create a softer corner effect. -->
+ <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
+ <dimen name="recents_task_view_shadow_rounded_corners_radius">6dp</dimen>
+
+ <!-- The amount of highlight to make on each task view. -->
+ <dimen name="recents_task_view_highlight">1dp</dimen>
+
+ <!-- The size of the lock-to-app button and its icon. -->
+ <dimen name="recents_lock_to_app_size">56dp</dimen>
+ <dimen name="recents_lock_to_app_icon_size">28dp</dimen>
+
+ <!-- The amount of overscroll allowed when flinging to the end of the stack. -->
+ <dimen name="recents_fling_overscroll_distance">24dp</dimen>
+
+ <!-- The min alpha to apply to a task affiliation group color. -->
+ <item name="recents_task_affiliation_color_min_alpha_percentage" format="float" type="dimen">0.6</item>
+
+ <!-- The amount to offset when animating into an affiliate group. -->
+ <dimen name="recents_task_stack_animation_affiliate_enter_offset">32dp</dimen>
+
+ <!-- The offsets the tasks animate from when recents is launched while docking -->
+ <dimen name="recents_task_stack_animation_launched_while_docking_offset">144dp</dimen>
+
+ <!-- The amount to translate when animating the removal of a task. -->
+ <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/dimens_tv.xml b/packages/SystemUI/res/values/dimens_tv.xml
index 6b153d1117ea..953dd650b2aa 100644
--- a/packages/SystemUI/res/values/dimens_tv.xml
+++ b/packages/SystemUI/res/values/dimens_tv.xml
@@ -18,8 +18,8 @@
-->
<resources>
<!-- Dimens for recents card in the recents view on tv -->
- <dimen name="recents_tv_card_width">268dip</dimen>
- <dimen name="recents_tv_screenshot_height">151dip</dimen>
+ <dimen name="recents_tv_card_width">240dip</dimen>
+ <dimen name="recents_tv_screenshot_height">135dip</dimen>
<dimen name="recents_tv_card_extra_badge_size">20dip</dimen>
<dimen name="recents_tv_banner_width">114dip</dimen>
<dimen name="recents_tv_banner_height">64dip</dimen>
@@ -29,10 +29,10 @@
<dimen name="recents_tv_text_padding_bottom">12dip</dimen>
<!-- Padding for grid view in recents view on tv -->
- <dimen name="recents_tv_grid_row_padding">56dip</dimen>
- <dimen name="recents_tv_gird_row_top_padding">57dip</dimen>
+ <dimen name="recents_tv_gird_row_top_margin">215dip</dimen>
<dimen name="recents_tv_grid_max_row_height">268dip</dimen>
- <dimen name="recents_tv_gird_card_spacing">20dip</dimen>
+ <dimen name="recents_tv_gird_card_spacing">8dip</dimen>
+ <dimen name="recents_tv_gird_focused_card_delta">44dip</dimen>
<!-- Values for focus animation -->
<dimen name="recents_tv_unselected_item_z">6dp</dimen>
@@ -43,4 +43,13 @@
<!-- Values for text on recents cards on tv -->
<dimen name="recents_tv_title_text_size">12sp</dimen>
+
+ <!-- Values for card dismiss state -->
+ <dimen name="recents_tv_dismiss_shift_down">48dip</dimen>
+ <dimen name="recents_tv_dismiss_top_margin">356dip</dimen>
+ <dimen name="recents_tv_dismiss_icon_size">24dip</dimen>
+ <dimen name="recents_tv_dismiss_icon_top_margin">38dip</dimen>
+ <dimen name="recents_tv_dismiss_icon_bottom_margin">1dip</dimen>
+ <dimen name="recents_tv_dismiss_text_size">12sp</dimen>
+
</resources>
diff --git a/packages/SystemUI/res/values/integers_tv.xml b/packages/SystemUI/res/values/integers_tv.xml
index bfd8f8beb958..c60c24556ca6 100644
--- a/packages/SystemUI/res/values/integers_tv.xml
+++ b/packages/SystemUI/res/values/integers_tv.xml
@@ -15,4 +15,6 @@
-->
<resources>
<integer name="item_scale_anim_duration">150</integer>
+ <integer name="dismiss_short_duration">200</integer>
+ <integer name="dismiss_long_duration">400</integer>
</resources> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 5295ccb77012..c9aa714e1fe2 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -570,6 +570,9 @@
<!-- Content description of the clear button in the notification panel for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
<string name="accessibility_clear_all">Clear all notifications.</string>
+ <!-- The overflow indicator shown when a group has more notification inside the group than the visible ones. An example is "+ 3" [CHAR LIMIT=5] -->
+ <string name="notification_group_overflow_indicator">+ <xliff:g id="number" example="3">%s</xliff:g></string>
+
<!-- Content description of button in notification inspector for system settings relating to
notifications from this application [CHAR LIMIT=NONE] -->
<string name="status_bar_notification_inspect_item_title">Notification settings</string>
@@ -728,10 +731,8 @@
<string name="recents_launch_error_message">Could not start <xliff:g id="app" example="Calendar">%s</xliff:g>.</string>
<!-- Recents: Launch disabled string. [CHAR LIMIT=NONE] -->
<string name="recents_launch_disabled_message"><xliff:g id="app" example="Calendar">%s</xliff:g> is disabled in safe-mode.</string>
- <!-- Recents: Show history string. [CHAR LIMIT=NONE] -->
- <string name="recents_history_button_label">History</string>
- <!-- Recents: History clear all string. [CHAR LIMIT=NONE] -->
- <string name="recents_history_clear_all_button_label">Clear</string>
+ <!-- Recents: Stack action button string. [CHAR LIMIT=NONE] -->
+ <string name="recents_stack_action_button_label">Clear all</string>
<!-- Recents: Non-dockable task drag message. [CHAR LIMIT=NONE] -->
<string name="recents_drag_non_dockable_task_message">This app does not support multi-window</string>
<!-- Recents: Non-dockable task launch sub header. [CHAR LIMIT=NONE] -->
@@ -1258,6 +1259,9 @@
<!-- Notification: Control panel: Label for button that dismisses control panel. [CHAR LIMIT=NONE] -->
<string name="notification_done">Done</string>
+ <!-- Notification: Gear: Content description for the gear. [CHAR LIMIT=NONE] -->
+ <string name="notification_gear_accessibility"><xliff:g id="app_name" example="YouTube">%1$s</xliff:g> notification controls</string>
+
<!-- SysUI Tuner: Color and appearance screen title [CHAR LIMIT=50] -->
<string name="color_and_appearance">Color and appearance</string>
diff --git a/packages/SystemUI/res/values/strings_tv.xml b/packages/SystemUI/res/values/strings_tv.xml
index 0e1fe8fa3384..52aba0d92883 100644
--- a/packages/SystemUI/res/values/strings_tv.xml
+++ b/packages/SystemUI/res/values/strings_tv.xml
@@ -19,13 +19,13 @@
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Picture-in-Picture (PIP) menu -->
<eat-comment />
- <!-- Button to close picture-in-picture (PIP) in PIP menu [CHAR LIMIT=16] -->
+ <!-- Button to close picture-in-picture (PIP) in PIP menu [CHAR LIMIT=30] -->
<string name="pip_close">Close PIP</string>
- <!-- Button to move picture-in-picture (PIP) screen to the fullscreen in PIP menu [CHAR LIMIT=16] -->
+ <!-- Button to move picture-in-picture (PIP) screen to the fullscreen in PIP menu [CHAR LIMIT=30] -->
<string name="pip_fullscreen">Full screen</string>
- <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=16] -->
+ <!-- Button to play the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
<string name="pip_play">Play</string>
- <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=16] -->
+ <!-- Button to pause the current media on picture-in-picture (PIP) [CHAR LIMIT=30] -->
<string name="pip_pause">Pause</string>
<!-- Overlay text on picture-in-picture (PIP) to indicate that longpress HOME key to control PIP [CHAR LIMIT=52] -->
<string name="pip_hold_home">Hold <b>HOME</b> to control PIP</string>
@@ -35,7 +35,11 @@
<string name="pip_onboarding_description">Press and hold the HOME button to control PIP</string>
<!-- Button to close picture-in-picture (PIP) onboarding screen. -->
<string name="pip_onboarding_button">Got it</string>
+ <!-- Dismiss icon description -->
+ <string name="recents_tv_dismiss">Dismiss</string>
<!-- Font for Recents -->
<!-- DO NOT TRANSLATE -->
<string name="font_roboto_regular" translatable="false">sans-serif</string>
+ <!-- DO NOT TRANSLATE -->
+ <string name="font_roboto_light" translatable="false">sans-serif-light</string>
</resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b0c1e951f7db..21ad21695d22 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -305,7 +305,7 @@
<style name="TextAppearance.NotificationGuts">
<item name="android:textSize">14sp</item>
- <item name="android:fontFamily">sans-serif-medium</item>
+ <item name="android:fontFamily">roboto-regular</item>
<item name="android:textColor">@android:color/black</item>
</style>
diff --git a/packages/SystemUI/res/values/values_tv.xml b/packages/SystemUI/res/values/values_tv.xml
index 6a72e542482b..bd72c5115566 100644
--- a/packages/SystemUI/res/values/values_tv.xml
+++ b/packages/SystemUI/res/values/values_tv.xml
@@ -15,5 +15,5 @@ limitations under the License.
-->
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<item format="float" type="integer" name="unselected_scale">1.0</item>
- <item format="float" type="integer" name="selected_scale">1.1</item>
+ <item format="float" type="integer" name="selected_scale">1.259</item>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/Prefs.java b/packages/SystemUI/src/com/android/systemui/Prefs.java
index 9f2745b9ac24..28ed84f37642 100644
--- a/packages/SystemUI/src/com/android/systemui/Prefs.java
+++ b/packages/SystemUI/src/com/android/systemui/Prefs.java
@@ -30,8 +30,6 @@ public final class Prefs {
@Retention(RetentionPolicy.SOURCE)
@StringDef({
- Key.OVERVIEW_SEARCH_APP_WIDGET_ID,
- Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE,
Key.OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME,
Key.DEBUG_MODE_ENABLED,
Key.HOTSPOT_TILE_LAST_USED,
@@ -51,8 +49,6 @@ public final class Prefs {
Key.QS_NIGHT_ADDED,
})
public @interface Key {
- String OVERVIEW_SEARCH_APP_WIDGET_ID = "searchAppWidgetId";
- String OVERVIEW_SEARCH_APP_WIDGET_PACKAGE = "searchAppWidgetPackage";
String OVERVIEW_LAST_STACK_TASK_ACTIVE_TIME = "OverviewLastStackTaskActiveTime";
String DEBUG_MODE_ENABLED = "debugModeEnabled";
String HOTSPOT_TILE_LAST_USED = "HotspotTileLastUsed";
diff --git a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
index 81ba23f27f23..a08b2c1198d8 100644
--- a/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/SwipeHelper.java
@@ -34,6 +34,8 @@ import android.view.accessibility.AccessibilityEvent;
import com.android.systemui.classifier.FalsingManager;
import com.android.systemui.statusbar.FlingAnimationUtils;
+import java.util.HashMap;
+
public class SwipeHelper implements Gefingerpoken {
static final String TAG = "com.android.systemui.SwipeHelper";
private static final boolean DEBUG = false;
@@ -70,6 +72,7 @@ public class SwipeHelper implements Gefingerpoken {
private float mInitialTouchPos;
private float mPerpendicularInitialTouchPos;
private boolean mDragging;
+ private boolean mSnappingChild;
private View mCurrView;
private boolean mCanCurrViewBeDimissed;
private float mDensityScale;
@@ -85,6 +88,8 @@ public class SwipeHelper implements Gefingerpoken {
private boolean mTouchAboveFalsingThreshold;
private boolean mDisableHwLayers;
+ private HashMap<View, Animator> mDismissPendingMap = new HashMap<>();
+
public SwipeHelper(int swipeDirection, Callback callback, Context context) {
mCallback = callback;
mHandler = new Handler();
@@ -252,6 +257,7 @@ public class SwipeHelper implements Gefingerpoken {
case MotionEvent.ACTION_DOWN:
mTouchAboveFalsingThreshold = false;
mDragging = false;
+ mSnappingChild = false;
mLongPressSent = false;
mVelocityTracker.clear();
mCurrView = mCallback.getChildAtPosition(ev);
@@ -391,9 +397,18 @@ public class SwipeHelper implements Gefingerpoken {
anim.setStartDelay(delay);
}
anim.addListener(new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
public void onAnimationEnd(Animator animation) {
updateSwipeProgressFromOffset(animView, canBeDismissed);
- mCallback.onChildDismissed(animView);
+ mDismissPendingMap.remove(animView);
+ if (!mCancelled) {
+ mCallback.onChildDismissed(animView);
+ }
if (endAction != null) {
endAction.run();
}
@@ -402,7 +417,9 @@ public class SwipeHelper implements Gefingerpoken {
}
}
});
+
prepareDismissAnimation(animView, anim);
+ mDismissPendingMap.put(animView, anim);
anim.start();
}
@@ -429,11 +446,13 @@ public class SwipeHelper implements Gefingerpoken {
anim.setDuration(duration);
anim.addListener(new AnimatorListenerAdapter() {
public void onAnimationEnd(Animator animator) {
+ mSnappingChild = false;
updateSwipeProgressFromOffset(animView, canBeDismissed);
mCallback.onChildSnappedBack(animView, targetLeft);
}
});
prepareSnapBackAnimation(animView, anim);
+ mSnappingChild = true;
anim.start();
}
@@ -466,6 +485,33 @@ public class SwipeHelper implements Gefingerpoken {
updateSwipeProgressFromOffset(animView, canBeDismissed);
}
+ private void snapChildInstantly(final View view) {
+ final boolean canAnimViewBeDismissed = mCallback.canChildBeDismissed(view);
+ setTranslation(view, 0);
+ updateSwipeProgressFromOffset(view, canAnimViewBeDismissed);
+ }
+
+ public void snapChildIfNeeded(final View view, boolean animate) {
+ if ((mDragging && mCurrView == view) || mSnappingChild) {
+ return;
+ }
+ boolean needToSnap = false;
+ Animator dismissPendingAnim = mDismissPendingMap.get(view);
+ if (dismissPendingAnim != null) {
+ needToSnap = true;
+ dismissPendingAnim.cancel();
+ } else if (getTranslation(view) != 0) {
+ needToSnap = true;
+ }
+ if (needToSnap) {
+ if (animate) {
+ snapChild(view, 0 /* targetLeft */, 0.0f /* velocity */);
+ } else {
+ snapChildInstantly(view);
+ }
+ }
+ }
+
public boolean onTouchEvent(MotionEvent ev) {
if (mLongPressSent) {
return true;
@@ -532,7 +578,9 @@ public class SwipeHelper implements Gefingerpoken {
mCallback.onDragCancelled(mCurrView);
snapChild(mCurrView, 0 /* leftTarget */, velocity);
}
+ mCurrView = null;
}
+ mDragging = false;
break;
}
return true;
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 2e94bc7e4d52..0d75fdd1cc45 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -25,6 +25,8 @@ import com.android.internal.widget.LockPatternUtils;
import com.android.keyguard.ViewMediatorCallback;
import com.android.systemui.statusbar.ScrimView;
import com.android.systemui.statusbar.phone.KeyguardBouncer;
+import com.android.systemui.statusbar.phone.NotificationIconAreaController;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.phone.StatusBarWindowManager;
@@ -75,6 +77,11 @@ public class SystemUIFactory {
return new ScrimController(scrimBehind, scrimInFront, headsUpScrim);
}
+ public NotificationIconAreaController createNotificationIconAreaController(Context context,
+ PhoneStatusBar phoneStatusBar) {
+ return new NotificationIconAreaController(context, phoneStatusBar);
+ }
+
public <T> T createInstance(Class<T> classType) {
return null;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 070b39594d34..003379fe0bf8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -27,6 +27,7 @@ public class Constants {
public static final int DismissSourceKeyboard = 0;
public static final int DismissSourceSwipeGesture = 1;
public static final int DismissSourceHeaderButton = 2;
+ @Deprecated
public static final int DismissSourceHistorySwipeGesture = 3;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Recents.java b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
index 2b6ed445a810..287bb224dbee 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Recents.java
@@ -17,6 +17,7 @@
package com.android.systemui.recents;
import android.app.ActivityManager;
+import android.app.UiModeManager;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -53,6 +54,7 @@ import com.android.systemui.recents.events.component.ScreenPinningRequestEvent;
import com.android.systemui.recents.events.ui.RecentsDrawnEvent;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.tv.RecentsTvImpl;
import java.util.ArrayList;
@@ -178,11 +180,17 @@ public class Recents extends SystemUI
@Override
public void start() {
sDebugFlags = new RecentsDebugFlags(mContext);
- sSystemServicesProxy = new SystemServicesProxy(mContext);
+ sSystemServicesProxy = SystemServicesProxy.getInstance(mContext);
sTaskLoader = new RecentsTaskLoader(mContext);
sConfiguration = new RecentsConfiguration(mContext);
mHandler = new Handler();
- mImpl = new RecentsImpl(mContext);
+ UiModeManager uiModeManager = (UiModeManager) mContext.
+ getSystemService(Context.UI_MODE_SERVICE);
+ if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
+ mImpl = new RecentsTvImpl(mContext);
+ } else {
+ mImpl = new RecentsImpl(mContext);
+ }
// Check if there is a recents override package
if ("userdebug".equals(Build.TYPE) || "eng".equals(Build.TYPE)) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index aab45b5d02f6..3fb3106e367a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -18,10 +18,7 @@ package com.android.systemui.recents;
import android.app.Activity;
import android.app.ActivityOptions;
-import android.app.SearchManager;
import android.app.TaskStackBuilder;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -42,7 +39,6 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DebugFlagsChangedEvent;
@@ -50,12 +46,10 @@ import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimatio
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowLastAnimationFrameEvent;
import com.android.systemui.recents.events.activity.ExitRecentsWindowFirstAnimationFrameEvent;
-import com.android.systemui.recents.events.activity.HideHistoryEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchTaskFailedEvent;
import com.android.systemui.recents.events.activity.LaunchTaskSucceededEvent;
-import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
import com.android.systemui.recents.events.activity.ToggleRecentsEvent;
import com.android.systemui.recents.events.component.RecentsVisibilityChangedEvent;
@@ -89,9 +83,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
private final static String TAG = "RecentsActivity";
private final static boolean DEBUG = false;
- private final static String KEY_SAVED_STATE_HISTORY_VISIBLE =
- "saved_instance_state_history_visible";
-
public final static int EVENT_BUS_PRIORITY = Recents.EVENT_BUS_PRIORITY + 1;
private RecentsPackageMonitor mPackageMonitor;
@@ -104,11 +95,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
private RecentsView mRecentsView;
private SystemBarScrimViews mScrimViews;
- // Search AppWidget
- private AppWidgetProviderInfo mSearchWidgetInfo;
- private RecentsAppWidgetHost mAppWidgetHost;
- private RecentsAppWidgetHostView mSearchWidgetHostView;
-
// Runnables to finish the Recents activity
private Intent mHomeIntent;
@@ -138,17 +124,10 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
@Override
public void run() {
try {
- RecentsActivityLaunchState launchState =
- Recents.getConfiguration().getLaunchState();
ActivityOptions opts = mOpts;
if (opts == null) {
opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_enter :
- R.anim.recents_to_launcher_enter,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_exit :
- R.anim.recents_to_launcher_exit);
+ R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
}
startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
} catch (Exception e) {
@@ -167,27 +146,11 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
if (action.equals(Intent.ACTION_SCREEN_OFF)) {
// When the screen turns off, dismiss Recents to Home
dismissRecentsToHomeIfVisible(false);
- } else if (action.equals(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED)) {
- // When the search activity changes, update the search widget view
- SystemServicesProxy ssp = Recents.getSystemServices();
- mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(context, mAppWidgetHost);
- refreshSearchWidgetView();
}
}
};
/**
- * Dismisses the history view back into the stack view.
- */
- boolean dismissHistory() {
- if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
- EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
- return true;
- }
- return false;
- }
-
- /**
* Dismisses recents if we are already visible and the intent is to toggle the recents view.
*/
boolean dismissRecentsToFocusedTask(int logCategory) {
@@ -285,10 +248,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
// Register this activity with the event bus
EventBus.getDefault().register(this, EVENT_BUS_PRIORITY);
- // Initialize the widget host (the host id is static and does not change)
- if (RecentsDebugFlags.Static.EnableSearchBar) {
- mAppWidgetHost = new RecentsAppWidgetHost(this, RecentsAppWidgetHost.HOST_ID);
- }
+ // Initialize the package monitor
mPackageMonitor = new RecentsPackageMonitor();
mPackageMonitor.register(this);
@@ -317,17 +277,9 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- // Bind the search app widget when we first start up
- if (RecentsDebugFlags.Static.EnableSearchBar) {
- mSearchWidgetInfo = ssp.getOrBindSearchAppWidget(this, mAppWidgetHost);
- }
-
// Register the broadcast receiver to handle messages when the screen is turned off
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_SCREEN_OFF);
- if (RecentsDebugFlags.Static.EnableSearchBar) {
- filter.addAction(SearchManager.INTENT_GLOBAL_SEARCH_ACTIVITY_CHANGED);
- }
registerReceiver(mSystemBroadcastReceiver, filter);
}
@@ -372,7 +324,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
loader.loadTasks(this, loadPlan, loadOpts);
TaskStack stack = loadPlan.getTaskStack();
- mRecentsView.onResume(mIsVisible, stack);
+ mRecentsView.onResume(mIsVisible, false /* multiWindowChange */, stack);
// Animate the SystemUI scrims into view
Task launchTarget = stack.getLaunchTarget();
@@ -439,18 +391,13 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- EventBus.getDefault().send(new ConfigurationChangedEvent());
+ EventBus.getDefault().post(new ConfigurationChangedEvent());
}
@Override
protected void onStop() {
super.onStop();
- // Only hide the history if Recents is completely hidden
- if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
- EventBus.getDefault().send(new HideHistoryEvent(false /* animate */));
- }
-
// Notify that recents is now hidden
mIsVisible = false;
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
@@ -479,11 +426,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
// Unregister any broadcast receivers for the task loader
mPackageMonitor.unregister();
- // Stop listening for widget package changes if there was one bound
- if (RecentsDebugFlags.Static.EnableSearchBar) {
- mAppWidgetHost.stopListening();
- }
-
EventBus.getDefault().unregister(this);
}
@@ -500,23 +442,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
}
@Override
- protected void onSaveInstanceState(Bundle outState) {
- super.onSaveInstanceState(outState);
- if (RecentsDebugFlags.Static.EnableHistory) {
- outState.putBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE, mRecentsView.isHistoryVisible());
- }
- }
-
- @Override
- protected void onRestoreInstanceState(Bundle savedInstanceState) {
- super.onRestoreInstanceState(savedInstanceState);
- if (RecentsDebugFlags.Static.EnableHistory &&
- savedInstanceState.getBoolean(KEY_SAVED_STATE_HISTORY_VISIBLE, false)) {
- EventBus.getDefault().send(new ShowHistoryEvent());
- }
- }
-
- @Override
public void onTrimMemory(int level) {
RecentsTaskLoader loader = Recents.getTaskLoader();
if (loader != null) {
@@ -541,7 +466,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
loadOpts.numVisibleTaskThumbnails = launchState.launchedNumVisibleThumbnails;
loader.loadTasks(this, loadPlan, loadOpts);
- mRecentsView.onResume(mIsVisible, loadPlan.getTaskStack());
+ mRecentsView.onResume(mIsVisible, true /* multiWindowChange */, loadPlan.getTaskStack());
EventBus.getDefault().send(new MultiWindowStateChangedEvent(inMultiWindow));
}
@@ -611,39 +536,35 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
/**** EventBus events ****/
public final void onBusEvent(ToggleRecentsEvent event) {
- if (!RecentsDebugFlags.Static.EnableHistory || !dismissHistory()) {
- RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
- if (launchState.launchedFromHome) {
- dismissRecentsToHome(true /* animateTaskViews */);
- } else {
- dismissRecentsToLaunchTargetTaskOrHome();
- }
+ RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
+ if (launchState.launchedFromHome) {
+ dismissRecentsToHome(true /* animateTaskViews */);
+ } else {
+ dismissRecentsToLaunchTargetTaskOrHome();
}
}
public final void onBusEvent(IterateRecentsEvent event) {
- if (!RecentsDebugFlags.Static.EnableHistory || !dismissHistory()) {
- final RecentsDebugFlags debugFlags = Recents.getDebugFlags();
-
- // Start dozing after the recents button is clicked
- int timerIndicatorDuration = 0;
- if (debugFlags.isFastToggleRecentsEnabled()) {
- timerIndicatorDuration = getResources().getInteger(
- R.integer.recents_subsequent_auto_advance_duration);
-
- mIterateTrigger.setDozeDuration(timerIndicatorDuration);
- if (!mIterateTrigger.isDozing()) {
- mIterateTrigger.startDozing();
- } else {
- mIterateTrigger.poke();
- }
- }
+ final RecentsDebugFlags debugFlags = Recents.getDebugFlags();
- // Focus the next task
- EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
+ // Start dozing after the recents button is clicked
+ int timerIndicatorDuration = 0;
+ if (debugFlags.isFastToggleRecentsEnabled()) {
+ timerIndicatorDuration = getResources().getInteger(
+ R.integer.recents_subsequent_auto_advance_duration);
- MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
+ mIterateTrigger.setDozeDuration(timerIndicatorDuration);
+ if (!mIterateTrigger.isDozing()) {
+ mIterateTrigger.startDozing();
+ } else {
+ mIterateTrigger.poke();
+ }
}
+
+ // Focus the next task
+ EventBus.getDefault().send(new FocusNextTaskViewEvent(timerIndicatorDuration));
+
+ MetricsLogger.action(this, MetricsEvent.ACTION_OVERVIEW_PAGE);
}
public final void onBusEvent(UserInteractionEvent event) {
@@ -658,17 +579,7 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
dismissRecentsToFocusedTaskOrHome();
}
} else if (event.triggeredFromHomeKey) {
- // Otherwise, dismiss Recents to Home
- if (RecentsDebugFlags.Static.EnableHistory && mRecentsView.isHistoryVisible()) {
- // If the history view is visible, then just cross-fade home
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsActivity.this,
- R.anim.recents_to_launcher_enter,
- R.anim.recents_to_launcher_exit);
- dismissRecentsToHome(false /* animate */, opts);
-
- } else {
- dismissRecentsToHome(true /* animateTaskViews */);
- }
+ dismissRecentsToHome(true /* animateTaskViews */);
// Cancel any pending dozes
EventBus.getDefault().send(mUserInteractionEvent);
@@ -677,23 +588,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
}
}
- public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
- // Try and start the enter animation (or restart it on configuration changed)
- if (RecentsDebugFlags.Static.EnableSearchBar) {
- if (mSearchWidgetInfo != null) {
- event.addPostAnimationCallback(new Runnable() {
- @Override
- public void run() {
- // Start listening for widget package changes if there is one bound
- if (mAppWidgetHost != null) {
- mAppWidgetHost.startListening();
- }
- }
- });
- }
- }
- }
-
public final void onBusEvent(EnterRecentsWindowLastAnimationFrameEvent event) {
EventBus.getDefault().send(new UpdateFreeformTaskViewVisibilityEvent(true));
mRecentsView.getViewTreeObserver().addOnPreDrawListener(this);
@@ -719,10 +613,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
}
}
- public final void onBusEvent(AppWidgetProviderChangedEvent event) {
- refreshSearchWidgetView();
- }
-
public final void onBusEvent(ShowApplicationInfoEvent event) {
// Create a new task stack with the application info details activity
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
@@ -785,24 +675,6 @@ public class RecentsActivity extends Activity implements ViewTreeObserver.OnPreD
mIgnoreAltTabRelease = true;
}
- private void refreshSearchWidgetView() {
- if (mSearchWidgetInfo != null) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- int searchWidgetId = ssp.getSearchAppWidgetId(this);
- mSearchWidgetHostView = (RecentsAppWidgetHostView) mAppWidgetHost.createView(
- this, searchWidgetId, mSearchWidgetInfo);
- Bundle opts = new Bundle();
- opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
- AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
- mSearchWidgetHostView.updateAppWidgetOptions(opts);
- // Set the padding to 0 for this search widget
- mSearchWidgetHostView.setPadding(0, 0, 0, 0);
- mRecentsView.setSearchBar(mSearchWidgetHostView);
- } else {
- mRecentsView.setSearchBar(null);
- }
- }
-
@Override
public boolean onPreDraw() {
mRecentsView.getViewTreeObserver().removeOnPreDrawListener(this);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
index ec4820a34964..ab3b79ebd22c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivityLaunchState.java
@@ -31,7 +31,6 @@ public class RecentsActivityLaunchState {
public boolean launchedFromApp;
public boolean launchedFromAppDocked;
public boolean launchedFromHome;
- public boolean launchedFromSearchHome;
public boolean launchedReuseTaskStackViews;
public boolean launchedHasConfigurationChanged;
public boolean launchedViaDragGesture;
@@ -42,7 +41,6 @@ public class RecentsActivityLaunchState {
public void reset() {
launchedFromHome = false;
- launchedFromSearchHome = false;
launchedFromApp = false;
launchedFromAppDocked = false;
launchedToTaskId = -1;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
deleted file mode 100644
index 318c69fe3a4b..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHost.java
+++ /dev/null
@@ -1,69 +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.
- */
-
-package com.android.systemui.recents;
-
-import android.appwidget.AppWidgetHost;
-import android.appwidget.AppWidgetHostView;
-import android.appwidget.AppWidgetProviderInfo;
-import android.content.Context;
-
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.AppWidgetProviderChangedEvent;
-
-/** Our special app widget host for the Search widget */
-public class RecentsAppWidgetHost extends AppWidgetHost {
-
- public static final int HOST_ID = 1024;
-
- boolean mIsListening;
-
- public RecentsAppWidgetHost(Context context, int hostId) {
- super(context, hostId);
- }
-
- public void startListening() {
- if (!mIsListening) {
- mIsListening = true;
- super.startListening();
- }
- }
-
- @Override
- public void stopListening() {
- if (mIsListening) {
- mIsListening = false;
- super.stopListening();
- }
- }
-
- @Override
- protected AppWidgetHostView onCreateView(Context context, int appWidgetId,
- AppWidgetProviderInfo appWidget) {
- return new RecentsAppWidgetHostView(context);
- }
-
- /**
- * Note: this is only called for packages that have updated, not removed.
- */
- @Override
- protected void onProviderChanged(int appWidgetId, AppWidgetProviderInfo appWidgetInfo) {
- super.onProviderChanged(appWidgetId, appWidgetInfo);
- if (mIsListening) {
- EventBus.getDefault().send(new AppWidgetProviderChangedEvent());
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHostView.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHostView.java
deleted file mode 100644
index 672d6024c89f..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsAppWidgetHostView.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents;
-
-import android.appwidget.AppWidgetHostView;
-import android.content.Context;
-import android.view.View;
-import android.widget.RemoteViews;
-
-public class RecentsAppWidgetHostView extends AppWidgetHostView {
-
- private Context mContext;
- private int mPreviousOrientation;
-
- public RecentsAppWidgetHostView(Context context) {
- super(context);
- mContext = context;
- }
-
- @Override
- public void updateAppWidget(RemoteViews remoteViews) {
- // Store the orientation in which the widget was inflated
- updateLastInflationOrientation();
- super.updateAppWidget(remoteViews);
- }
-
- @Override
- protected View getErrorView() {
- // Just return an empty view as the error view when failing to inflate the Recents search
- // bar widget (this is mainly to catch the case where we try and inflate the widget view
- // while the search provider is updating)
- return new View(mContext);
- }
-
- /**
- * Updates the last orientation that this widget was inflated.
- */
- private void updateLastInflationOrientation() {
- mPreviousOrientation = mContext.getResources().getConfiguration().orientation;
- }
-
- /**
- * @return whether the search widget was updated while Recents was in a different orientation
- * in the background.
- */
- public boolean isReinflateRequired() {
- // Re-inflate is required if the orientation has changed since last inflated.
- int orientation = mContext.getResources().getConfiguration().orientation;
- if (mPreviousOrientation != orientation) {
- return true;
- }
- return false;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index eec0411f3590..2afb09a18f7a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -32,13 +32,6 @@ public class RecentsConfiguration {
private static final int LARGE_SCREEN_MIN_DP = 600;
private static final int XLARGE_SCREEN_MIN_DP = 720;
- // Variables that are used for global calculations
- private static final float STACK_SIDE_PADDING_PHONES_PCT = 0.03333f;
- private static final float STACK_SIZE_PADDING_TABLETS_PCT = 0.075f;
- private static final float STACK_SIZE_PADDING_LARGE_TABLETS_PCT = 0.15f;
- private static final int SEARCH_BAR_SPACE_HEIGHT_PHONES_DPS = 64;
- private static final int SEARCH_BAR_SPACE_HEIGHT_TABLETS_DPS = 72;
-
/** Levels of svelte in increasing severity/austerity. */
// No svelting.
public static final int SVELTE_NONE = 0;
@@ -57,9 +50,7 @@ public class RecentsConfiguration {
// TODO: Values determined by the current context, needs to be refactored into something that is
// agnostic of the activity context, but still calculable from the Recents component for
// the transition into recents
- boolean hasTransposedSearchBar;
- boolean hasTransposedNavBar;
- public float taskStackWidthPaddingPct;
+ public boolean hasTransposedNavBar;
// Since the positions in Recents has to be calculated globally (before the RecentsActivity
// starts), we need to calculate some resource values ourselves, instead of relying on framework
@@ -71,7 +62,6 @@ public class RecentsConfiguration {
/** Misc **/
public boolean fakeShadows;
public int svelteLevel;
- public int searchBarSpaceHeightPx;
public RecentsConfiguration(Context context) {
// Load only resources that can not change after the first load either through developer
@@ -82,20 +72,10 @@ public class RecentsConfiguration {
fakeShadows = res.getBoolean(R.bool.config_recents_fake_shadows);
svelteLevel = res.getInteger(R.integer.recents_svelte_level);
- float density = context.getResources().getDisplayMetrics().density;
+ float screenDensity = context.getResources().getDisplayMetrics().density;
smallestWidth = ssp.getDeviceSmallestWidth();
- isLargeScreen = smallestWidth >= (int) (density * LARGE_SCREEN_MIN_DP);
- isXLargeScreen = smallestWidth >= (int) (density * XLARGE_SCREEN_MIN_DP);
- searchBarSpaceHeightPx = isLargeScreen ?
- (int) (density * SEARCH_BAR_SPACE_HEIGHT_TABLETS_DPS) :
- (int) (density * SEARCH_BAR_SPACE_HEIGHT_PHONES_DPS);
- if (isLargeScreen) {
- taskStackWidthPaddingPct = STACK_SIZE_PADDING_TABLETS_PCT;
- } else if (isXLargeScreen) {
- taskStackWidthPaddingPct = STACK_SIZE_PADDING_LARGE_TABLETS_PCT;
- } else {
- taskStackWidthPaddingPct = STACK_SIDE_PADDING_PHONES_PCT;
- }
+ isLargeScreen = smallestWidth >= (int) (screenDensity * LARGE_SCREEN_MIN_DP);
+ isXLargeScreen = smallestWidth >= (int) (screenDensity * XLARGE_SCREEN_MIN_DP);
}
/**
@@ -103,7 +83,6 @@ public class RecentsConfiguration {
*/
void update(Rect systemInsets) {
hasTransposedNavBar = systemInsets.right > 0;
- hasTransposedSearchBar = systemInsets.right > 0;
}
/**
@@ -121,40 +100,4 @@ public class RecentsConfiguration {
public void updateOnConfigurationChange() {
mLaunchState.updateOnConfigurationChange();
}
-
- /**
- * Returns the task stack bounds in the current orientation. These bounds do not account for
- * the system insets.
- */
- public void getTaskStackBounds(Rect windowBounds, int topInset,
- int rightInset, Rect searchBarBounds, Rect taskStackBounds) {
- if (hasTransposedNavBar) {
- // In landscape phones, the search bar appears on the left, but we overlay it on top
- taskStackBounds.set(windowBounds.left, windowBounds.top + topInset,
- windowBounds.right - rightInset, windowBounds.bottom);
- } else {
- // In portrait, the search bar appears on the top (which already has the inset)
- int top = searchBarBounds.isEmpty() ? topInset : 0;
- taskStackBounds.set(windowBounds.left, windowBounds.top + searchBarBounds.bottom + top,
- windowBounds.right - rightInset, windowBounds.bottom);
- }
- }
-
- /**
- * Returns the search bar bounds in the current orientation. These bounds do not account for
- * the system insets.
- */
- public void getSearchBarBounds(Rect windowBounds, int topInset, Rect searchBarSpaceBounds) {
- // Return empty rects if search is not enabled
- int searchBarSize = searchBarSpaceHeightPx;
- if (hasTransposedSearchBar) {
- // In landscape phones, the search bar appears on the left
- searchBarSpaceBounds.set(windowBounds.left, windowBounds.top + topInset,
- windowBounds.left + searchBarSize, windowBounds.bottom);
- } else {
- // In portrait, the search bar appears on the top
- searchBarSpaceBounds.set(windowBounds.left, windowBounds.top + topInset,
- windowBounds.right, windowBounds.top + topInset + searchBarSize);
- }
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index 40bf6d3d2447..f67f099c23a5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -31,14 +31,12 @@ public class RecentsDebugFlags implements TunerService.Tunable {
public static class Static {
// Enables debug drawing for the transition thumbnail
public static final boolean EnableTransitionThumbnailDebugMode = false;
- // This enables the search bar integration
- public static final boolean EnableSearchBar = false;
// This disables the bitmap and icon caches
public static final boolean DisableBackgroundCache = false;
// Enables the task affiliations
public static final boolean EnableAffiliatedTaskGroups = true;
- // Enables the history
- public static final boolean EnableHistory = false;
+ // TODO: To be repurposed
+ public static final boolean EnableStackActionButton = false;
// Overrides the Tuner flags and enables the timeout
private static final boolean EnableFastToggleTimeout = false;
// Overrides the Tuner flags and enables the paging via the Recents button
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 9be24def0da4..58216b08463f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -20,18 +20,15 @@ import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import android.app.ActivityManager;
import android.app.ActivityOptions;
-import android.app.ITaskStackListener;
-import android.app.UiModeManager;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.SystemClock;
import android.os.UserHandle;
@@ -43,7 +40,6 @@ import android.view.View;
import android.view.ViewConfiguration;
import com.android.internal.logging.MetricsLogger;
-import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.SystemUIApplication;
import com.android.systemui.recents.events.EventBus;
@@ -61,12 +57,12 @@ import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ForegroundThread;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.recents.model.RecentsTaskLoadPlan;
import com.android.systemui.recents.model.RecentsTaskLoader;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskGrouping;
import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.tv.views.TaskCardView;
import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import com.android.systemui.recents.views.TaskStackView;
import com.android.systemui.recents.views.TaskStackViewScroller;
@@ -96,43 +92,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
public final static String RECENTS_PACKAGE = "com.android.systemui";
public final static String RECENTS_ACTIVITY = "com.android.systemui.recents.RecentsActivity";
- public final static String RECENTS_TV_ACTIVITY = "com.android.systemui.recents.tv.RecentsTvActivity";
-
- //Used to store tv or non-tv activty for use in creating intents.
- private final String mRecentsIntentActivityName;
/**
- * An implementation of ITaskStackListener, that allows us to listen for changes to the system
+ * An implementation of TaskStackListener, that allows us to listen for changes to the system
* task stacks and update recents accordingly.
*/
- class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable {
- Handler mHandler;
-
- public TaskStackListenerImpl(Handler handler) {
- mHandler = handler;
- }
-
+ class TaskStackListenerImpl extends TaskStackListener {
@Override
public void onTaskStackChanged() {
- // Debounce any task stack changes
- mHandler.removeCallbacks(this);
- mHandler.post(this);
- }
-
- @Override
- public void onActivityPinned() {
- }
-
- @Override
- public void onPinnedActivityRestartAttempt() {
- }
-
- @Override
- public void onPinnedStackAnimationEnded() {
- }
-
- /** Preloads the next task */
- public void run() {
+ // Preloads the next task
RecentsConfiguration config = Recents.getConfiguration();
if (config.svelteLevel == RecentsConfiguration.SVELTE_NONE) {
RecentsTaskLoader loader = Recents.getTaskLoader();
@@ -158,19 +126,16 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
}
- private static RecentsTaskLoadPlan sInstanceLoadPlan;
+ protected static RecentsTaskLoadPlan sInstanceLoadPlan;
- Context mContext;
- Handler mHandler;
+ protected Context mContext;
+ protected Handler mHandler;
TaskStackListenerImpl mTaskStackListener;
- RecentsAppWidgetHost mAppWidgetHost;
- boolean mCanReuseTaskStackViews = true;
+ protected boolean mCanReuseTaskStackViews = true;
boolean mDraggingInRecents;
boolean mLaunchedWhileDocking;
- private boolean mIsRunningOnTv;
// Task launching
- Rect mSearchBarBounds = new Rect();
Rect mTaskStackBounds = new Rect();
Rect mLastTaskViewBounds = new Rect();
TaskViewTransform mTmpTransform = new TaskViewTransform();
@@ -182,11 +147,11 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Header (for transition)
TaskViewHeader mHeaderBar;
final Object mHeaderBarLock = new Object();
- TaskStackView mDummyStackView;
+ protected TaskStackView mDummyStackView;
// Variables to keep track of if we need to start recents after binding
- boolean mTriggeredFromAltTab;
- long mLastToggleTime;
+ protected boolean mTriggeredFromAltTab;
+ protected long mLastToggleTime;
DozeTrigger mFastAltTabTrigger = new DozeTrigger(FAST_ALT_TAB_DELAY_MS, new Runnable() {
@Override
public void run() {
@@ -197,25 +162,24 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
});
- Bitmap mThumbnailTransitionBitmapCache;
+ protected Bitmap mThumbnailTransitionBitmapCache;
Task mThumbnailTransitionBitmapCacheKey;
public RecentsImpl(Context context) {
mContext = context;
mHandler = new Handler();
- mAppWidgetHost = new RecentsAppWidgetHost(mContext, RecentsAppWidgetHost.HOST_ID);
// Initialize the static foreground thread
ForegroundThread.get();
// Register the task stack listener
- mTaskStackListener = new TaskStackListenerImpl(mHandler);
+ mTaskStackListener = new TaskStackListenerImpl();
SystemServicesProxy ssp = Recents.getSystemServices();
ssp.registerTaskStackListener(mTaskStackListener);
// Initialize the static configuration resources
reloadHeaderBarLayout();
- updateHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
+ updateHeaderBarLayout(null /* stack */);
// When we start, preload the data associated with the previous recent tasks.
// We can use a new plan since the caches will be the same.
@@ -227,25 +191,15 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
launchOpts.numVisibleTaskThumbnails = loader.getThumbnailCacheSize();
launchOpts.onlyLoadForCache = true;
loader.loadTasks(mContext, plan, launchOpts);
-
- //Manager used to determine if we are running on tv or not
- UiModeManager uiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
- if (uiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_TELEVISION) {
- mRecentsIntentActivityName = RECENTS_TV_ACTIVITY;
- mIsRunningOnTv = true;
- } else {
- mRecentsIntentActivityName = RECENTS_ACTIVITY;
- mIsRunningOnTv = false;
- }
}
public void onBootCompleted() {
- updateHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
+ updateHeaderBarLayout(null /* stack */);
}
public void onConfigurationChanged() {
reloadHeaderBarLayout();
- updateHeaderBarLayout(true /* tryAndBindSearchWidget */, null /* stack */);
+ updateHeaderBarLayout(null /* stack */);
// Don't reuse task stack views if the configuration changes
mCanReuseTaskStackViews = false;
Recents.getConfiguration().updateOnConfigurationChange();
@@ -604,7 +558,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
mNavBarWidth = res.getDimensionPixelSize(
com.android.internal.R.dimen.navigation_bar_width);
mTaskBarHeight = res.getDimensionPixelSize(
- R.dimen.recents_task_bar_height);
+ R.dimen.recents_task_view_header_height);
mDummyStackView = new TaskStackView(mContext);
mHeaderBar = (TaskViewHeader) inflater.inflate(R.layout.recents_task_view_header,
null, false);
@@ -614,12 +568,9 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
* Prepares the header bar layout for the next transition, if the task view bounds has changed
* since the last call, it will attempt to re-measure and layout the header bar to the new size.
*
- * @param tryAndBindSearchWidget if set, will attempt to fetch and bind the search widget if one
- * is not already bound (can be expensive)
* @param stack the stack to initialize the stack layout with
*/
- private void updateHeaderBarLayout(boolean tryAndBindSearchWidget, TaskStack stack) {
- RecentsConfiguration config = Recents.getConfiguration();
+ private void updateHeaderBarLayout(TaskStack stack) {
SystemServicesProxy ssp = Recents.getSystemServices();
Rect systemInsets = new Rect();
ssp.getStableInsets(systemInsets);
@@ -628,28 +579,20 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
windowRect.offsetTo(0, 0);
// Update the configuration for the current state
- config.update(systemInsets);
-
- if (RecentsDebugFlags.Static.EnableSearchBar && tryAndBindSearchWidget) {
- // Try and pre-emptively bind the search widget on startup to ensure that we
- // have the right thumbnail bounds to animate to.
- // Note: We have to reload the widget id before we get the task stack bounds below
- if (ssp.getOrBindSearchAppWidget(mContext, mAppWidgetHost) != null) {
- config.getSearchBarBounds(windowRect, mStatusBarHeight, mSearchBarBounds);
- }
- }
- config.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
- mSearchBarBounds, mTaskStackBounds);
+ Recents.getConfiguration().update(systemInsets);
- // Rebind the header bar and draw it for the transition
TaskStackLayoutAlgorithm stackLayout = mDummyStackView.getStackAlgorithm();
+ stackLayout.getTaskStackBounds(windowRect, systemInsets.top, systemInsets.right,
+ mTaskStackBounds);
+
+ // Rebind the header bar and draw it for the transition
Rect taskStackBounds = new Rect(mTaskStackBounds);
stackLayout.setSystemInsets(systemInsets);
if (stack != null) {
- stackLayout.initialize(taskStackBounds,
+ stackLayout.initialize(windowRect, taskStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(stack));
mDummyStackView.setTasks(stack, false /* notifyStackChanges */,
- false /* relayoutTaskStack */);
+ false /* relayoutTaskStack */, false /* multiWindowChange */);
}
Rect taskViewBounds = stackLayout.getUntransformedTaskViewBounds();
if (!taskViewBounds.equals(mLastTaskViewBounds)) {
@@ -706,7 +649,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
preloadIcon(topTask);
// Update the header bar if necessary
- updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
+ updateHeaderBarLayout(stack);
// Update the destination rect
final Task toTask = new Task();
@@ -729,7 +672,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
/**
* Creates the activity options for a unknown state->recents transition.
*/
- private ActivityOptions getUnknownTransitionActivityOptions() {
+ protected ActivityOptions getUnknownTransitionActivityOptions() {
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_unknown_enter,
R.anim.recents_from_unknown_exit,
@@ -739,13 +682,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
/**
* Creates the activity options for a home->recents transition.
*/
- private ActivityOptions getHomeTransitionActivityOptions(boolean fromSearchHome) {
- if (fromSearchHome) {
- return ActivityOptions.makeCustomAnimation(mContext,
- R.anim.recents_from_search_launcher_enter,
- R.anim.recents_from_search_launcher_exit,
- mHandler, null);
- }
+ protected ActivityOptions getHomeTransitionActivityOptions() {
return ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_launcher_enter,
R.anim.recents_from_launcher_exit,
@@ -797,22 +734,6 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
}
}
- /**
- * Creates the activity options for an app->recents transition on TV.
- */
- private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
- ActivityManager.RunningTaskInfo topTask) {
- Bitmap thumbnail = mThumbnailTransitionBitmapCache;
- Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
- if (thumbnail != null) {
- return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
- null, (int) rect.left, (int) rect.top,
- (int) rect.width(), (int) rect.height(), mHandler, null);
- }
- // If both the screenshot and thumbnail fails, then just fall back to the default transition
- return getUnknownTransitionActivityOptions();
- }
-
private Bitmap getThumbnailBitmap(ActivityManager.RunningTaskInfo topTask, Task toTask,
TaskViewTransform toTransform) {
Bitmap thumbnail;
@@ -873,6 +794,12 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
} else {
Canvas c = new Canvas(thumbnail);
c.scale(toTransform.scale, toTransform.scale);
+ // 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();
+ if (icon != null) {
+ icon.setCallback(null);
+ }
mHeaderBar.rebindToTask(toTask, false /* touchExplorationEnabled */,
disabledInSafeMode);
mHeaderBar.setDimAlpha(toTransform.dimAlpha);
@@ -888,15 +815,10 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
/**
* Shows the recents activity
*/
- private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
+ protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
boolean isTopTaskHome, boolean animate) {
RecentsTaskLoader loader = Recents.getTaskLoader();
- // If we are on TV, divert to a different helper method
- if (mIsRunningOnTv) {
- setUpAndStartTvRecents(topTask, isTopTaskHome, animate);
- return;
- }
// In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
// should always preload the tasks now. If we are dragging in recents, reload them as
// the stacks might have changed.
@@ -910,7 +832,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
TaskStack stack = sInstanceLoadPlan.getTaskStack();
// Update the header bar if necessary
- updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
+ updateHeaderBarLayout(stack);
// Prepare the dummy stack for the transition
TaskStackLayoutAlgorithm.VisibilityReport stackVr =
@@ -918,8 +840,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
if (!animate) {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
- startRecentsActivity(topTask, opts, false /* fromHome */,
- false /* fromSearchHome */, false /* fromThumbnail*/, stackVr);
+ startRecentsActivity(topTask, opts, false /* fromHome */, false /* fromThumbnail*/,
+ stackVr);
return;
}
@@ -930,92 +852,8 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
// Try starting with a thumbnail transition
ActivityOptions opts = getThumbnailTransitionActivityOptions(topTask, mDummyStackView);
if (opts != null) {
- startRecentsActivity(topTask, opts, false /* fromHome */,
- false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
- } else {
- // Fall through below to the non-thumbnail transition
- useThumbnailTransition = false;
- }
- }
-
- if (!useThumbnailTransition) {
- // If there is no thumbnail transition, but is launching from home into recents, then
- // use a quick home transition and do the animation from home
- if (hasRecentTasks) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- String homeActivityPackage = ssp.getHomeActivityPackageName();
- String searchWidgetPackage = null;
- if (RecentsDebugFlags.Static.EnableSearchBar) {
- searchWidgetPackage = Prefs.getString(mContext,
- Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null);
- } else {
- AppWidgetProviderInfo searchWidgetInfo = ssp.resolveSearchAppWidget();
- if (searchWidgetInfo != null) {
- searchWidgetPackage = searchWidgetInfo.provider.getPackageName();
- }
- }
-
- // Determine whether we are coming from a search owned home activity
- boolean fromSearchHome = (homeActivityPackage != null) &&
- homeActivityPackage.equals(searchWidgetPackage);
- ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome);
- startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome,
- false /* fromThumbnail */, stackVr);
- } else {
- // Otherwise we do the normal fade from an unknown source
- ActivityOptions opts = getUnknownTransitionActivityOptions();
- startRecentsActivity(topTask, opts, true /* fromHome */,
- false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
- }
- }
- mLastToggleTime = SystemClock.elapsedRealtime();
- }
-
- /**
- * Used to set up the animations of Tv Recents, then start the Recents Activity.
- * TODO: Add the Transitions for Home -> Recents TV
- * TODO: Shift Transition code to separate class under /tv directory and access
- * from here
- */
- private void setUpAndStartTvRecents(ActivityManager.RunningTaskInfo topTask,
- boolean isTopTaskHome, boolean animate) {
- RecentsTaskLoader loader = Recents.getTaskLoader();
-
- // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
- // should always preload the tasks now. If we are dragging in recents, reload them as
- // the stacks might have changed.
- if (mLaunchedWhileDocking || mTriggeredFromAltTab || sInstanceLoadPlan == null) {
- // Create a new load plan if preloadRecents() was never triggered
- sInstanceLoadPlan = loader.createLoadPlan(mContext);
- }
- if (mLaunchedWhileDocking || mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
- loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome);
- }
- TaskStack stack = sInstanceLoadPlan.getTaskStack();
-
- // Update the header bar if necessary
- updateHeaderBarLayout(false /* tryAndBindSearchWidget */, stack);
-
- // Prepare the dummy stack for the transition
- TaskStackLayoutAlgorithm.VisibilityReport stackVr =
- mDummyStackView.computeStackVisibilityReport();
-
- if (!animate) {
- ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
- startRecentsActivity(topTask, opts, false /* fromHome */,
- false /* fromSearchHome */, false /* fromThumbnail*/, stackVr);
- return;
- }
-
- boolean hasRecentTasks = stack.getTaskCount() > 0;
- boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
-
- if (useThumbnailTransition) {
- // Try starting with a thumbnail transition
- ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask);
- if (opts != null) {
- startRecentsActivity(topTask, opts, false /* fromHome */,
- false /* fromSearchHome */, true /* fromThumbnail */, stackVr);
+ startRecentsActivity(topTask, opts, false /* fromHome */, true /* fromThumbnail */,
+ stackVr);
} else {
// Fall through below to the non-thumbnail transition
useThumbnailTransition = false;
@@ -1024,33 +862,12 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
if (!useThumbnailTransition) {
// If there is no thumbnail transition, but is launching from home into recents, then
- // use a quick home transition and do the animation from home
- if (hasRecentTasks) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- String homeActivityPackage = ssp.getHomeActivityPackageName();
- String searchWidgetPackage = null;
- if (RecentsDebugFlags.Static.EnableSearchBar) {
- searchWidgetPackage = Prefs.getString(mContext,
- Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null);
- } else {
- AppWidgetProviderInfo searchWidgetInfo = ssp.resolveSearchAppWidget();
- if (searchWidgetInfo != null) {
- searchWidgetPackage = searchWidgetInfo.provider.getPackageName();
- }
- }
-
- // Determine whether we are coming from a search owned home activity
- boolean fromSearchHome = (homeActivityPackage != null) &&
- homeActivityPackage.equals(searchWidgetPackage);
- ActivityOptions opts = getHomeTransitionActivityOptions(fromSearchHome);
- startRecentsActivity(topTask, opts, true /* fromHome */, fromSearchHome,
- false /* fromThumbnail */, stackVr);
- } else {
- // Otherwise we do the normal fade from an unknown source
- ActivityOptions opts = getUnknownTransitionActivityOptions();
- startRecentsActivity(topTask, opts, true /* fromHome */,
- false /* fromSearchHome */, false /* fromThumbnail */, stackVr);
- }
+ // use a quick home transition
+ ActivityOptions opts = hasRecentTasks
+ ? getHomeTransitionActivityOptions()
+ : getUnknownTransitionActivityOptions();
+ startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */,
+ stackVr);
}
mLastToggleTime = SystemClock.elapsedRealtime();
}
@@ -1059,13 +876,12 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
* Starts the recents activity.
*/
private void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
- ActivityOptions opts, boolean fromHome, boolean fromSearchHome,
- boolean fromThumbnail, TaskStackLayoutAlgorithm.VisibilityReport vr) {
+ ActivityOptions opts, boolean fromHome, boolean fromThumbnail,
+ TaskStackLayoutAlgorithm.VisibilityReport vr) {
// Update the configuration based on the launch options
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
- launchState.launchedFromHome = fromSearchHome || fromHome;
- launchState.launchedFromSearchHome = fromSearchHome;
+ launchState.launchedFromHome = fromHome;
launchState.launchedFromApp = fromThumbnail || mLaunchedWhileDocking;
launchState.launchedFromAppDocked = mLaunchedWhileDocking;
launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
@@ -1078,7 +894,7 @@ public class RecentsImpl implements ActivityOptions.OnAnimationFinishedListener
launchState.launchedWhileDocking = mLaunchedWhileDocking;
Intent intent = new Intent();
- intent.setClassName(RECENTS_PACKAGE, mRecentsIntentActivityName);
+ intent.setClassName(RECENTS_PACKAGE, RECENTS_ACTIVITY);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
| Intent.FLAG_ACTIVITY_TASK_ON_HOME);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppWidgetProviderChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppWidgetProviderChangedEvent.java
deleted file mode 100644
index 52cfe18a9e26..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/AppWidgetProviderChangedEvent.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.RecentsAppWidgetHost;
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent by the {@link RecentsAppWidgetHost} whenever the search provider widget changes, and
- * subscribers can update accordingly.
- */
-public class AppWidgetProviderChangedEvent extends EventBus.Event {
- // Simple event
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
deleted file mode 100644
index bacf3bdbf976..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideHistoryEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.events.activity;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent when the history view will be closed.
- */
-public class HideHistoryEvent extends EventBus.Event {
-
- public final boolean animate;
-
- public HideHistoryEvent(boolean animate) {
- this.animate = animate;
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
index 469f336ebff1..e02fb147e926 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/HideStackActionButtonEvent.java
@@ -19,10 +19,8 @@ package com.android.systemui.recents.events.activity;
import com.android.systemui.recents.events.EventBus;
/**
- * This is sent when the history view button is clicked.
+ * This is sent when the stack action button should be hidden.
*/
-public class ShowHistoryEvent extends EventBus.Event {
-
+public class HideStackActionButtonEvent extends EventBus.Event {
// Simple event
-
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java
index ae803ea7d104..d81f89c172b9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowHistoryButtonEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ShowStackActionButtonEvent.java
@@ -19,14 +19,14 @@ package com.android.systemui.recents.events.activity;
import com.android.systemui.recents.events.EventBus;
/**
- * This is sent when the history view button should be shown.
+ * This is sent when the stack action view button should be shown.
*/
-public class ShowHistoryButtonEvent extends EventBus.Event {
+public class ShowStackActionButtonEvent extends EventBus.Event {
- // Whether or not to translate the history button when showing it
+ // Whether or not to translate the stack action button when showing it
public final boolean translate;
- public ShowHistoryButtonEvent(boolean translate) {
+ public ShowStackActionButtonEvent(boolean translate) {
this.translate = translate;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
deleted file mode 100644
index 16385c9ab358..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryAdapter.java
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.history;
-
-import android.app.ActivityOptions;
-import android.content.Context;
-import android.support.v7.widget.RecyclerView;
-import android.text.format.DateFormat;
-import android.util.SparseIntArray;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
-import com.android.systemui.recents.events.activity.HideHistoryEvent;
-import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
-import com.android.systemui.recents.misc.SystemServicesProxy;
-import com.android.systemui.recents.model.RecentsTaskLoader;
-import com.android.systemui.recents.model.Task;
-import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.views.AnimationProps;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.List;
-import java.util.Locale;
-import java.util.Objects;
-
-
-/**
- * An adapter for the list of recent tasks in the history view.
- */
-public class RecentsHistoryAdapter extends RecyclerView.Adapter<RecentsHistoryAdapter.ViewHolder> {
-
- private static final String TAG = "RecentsHistoryView";
- private static final boolean DEBUG = false;
-
- static final int DATE_ROW_VIEW_TYPE = 0;
- static final int TASK_ROW_VIEW_TYPE = 1;
-
- /**
- * View holder implementation. The {@param TaskCallbacks} are only called for TaskRow view
- * holders.
- */
- public static class ViewHolder extends RecyclerView.ViewHolder implements Task.TaskCallbacks {
- public final View content;
-
- private Task mTask;
-
- public ViewHolder(View content) {
- super(content);
- this.content = content;
- }
-
- /**
- * Binds this view holder to the given task.
- */
- public void bindToTask(Task newTask) {
- unbindFromTask();
- mTask = newTask;
- mTask.addCallback(this);
- }
-
- /**
- * Unbinds this view holder from the
- */
- public void unbindFromTask() {
- if (mTask != null) {
- mTask.removeCallback(this);
- mTask = null;
- }
- }
-
- @Override
- public void onTaskDataLoaded(Task task) {
- // This callback is only made for TaskRow view holders
- ImageView iv = (ImageView) content.findViewById(R.id.icon);
- iv.setImageDrawable(task.icon);
- iv.animate()
- .alpha(1f)
- .setDuration(100)
- .start();
- }
-
- @Override
- public void onTaskDataUnloaded() {
- // This callback is only made for TaskRow view holders
- ImageView iv = (ImageView) content.findViewById(R.id.icon);
- iv.setImageBitmap(null);
- iv.animate().cancel();
- }
-
- @Override
- public void onTaskStackIdChanged() {
- // Do nothing, this callback is only made for TaskRow view holders
- }
- }
-
- /**
- * A single row of content.
- */
- interface Row {
- int getViewType();
- }
-
- /**
- * A date row.
- */
- static class DateRow implements Row {
-
- public final String date;
-
- public DateRow(String date) {
- this.date = date;
- }
-
- @Override
- public int getViewType() {
- return RecentsHistoryAdapter.DATE_ROW_VIEW_TYPE;
- }
- }
-
- /**
- * A task row.
- */
- static class TaskRow implements Row, View.OnClickListener {
-
- public final Task task;
- public final int dateKey;
-
- public TaskRow(Task task, int dateKey) {
- this.task = task;
- this.dateKey = dateKey;
- }
-
- @Override
- public void onClick(View v) {
- SystemServicesProxy ssp = Recents.getSystemServices();
- ssp.startActivityFromRecents(v.getContext(), task.key.id, task.title,
- ActivityOptions.makeBasic());
-
- MetricsLogger.action(v.getContext(), MetricsEvent.ACTION_OVERVIEW_SELECT,
- task.key.getComponent().toString());
- }
-
- @Override
- public int getViewType() {
- return RecentsHistoryAdapter.TASK_ROW_VIEW_TYPE;
- }
- }
-
- private Context mContext;
- private LayoutInflater mLayoutInflater;
- private final List<Row> mRows = new ArrayList<>();
- private final SparseIntArray mTaskRowCount = new SparseIntArray();
- private TaskStack mStack;
-
- public RecentsHistoryAdapter(Context context) {
- mLayoutInflater = LayoutInflater.from(context);
- }
-
- /**
- * Updates this adapter with the given tasks.
- */
- public void updateTasks(Context context, TaskStack stack) {
- mContext = context;
- mStack = stack;
-
- final Locale l = context.getResources().getConfiguration().locale;
- final String dateFormatStr = DateFormat.getBestDateTimePattern(l, "EEEEMMMMd");
- final List<Task> tasksMostRecent = new ArrayList<>(stack.getHistoricalTasks());
- Collections.reverse(tasksMostRecent);
- int prevDateKey = -1;
- int taskCount = tasksMostRecent.size();
- mRows.clear();
- mTaskRowCount.clear();
- Calendar cal = Calendar.getInstance(l);
- for (int i = 0; i < taskCount; i++) {
- Task task = tasksMostRecent.get(i);
- if (task.isFreeformTask()) {
- continue;
- }
-
- cal.setTimeInMillis(task.key.lastActiveTime);
- int dateKey = Objects.hash(cal.get(Calendar.YEAR), cal.get(Calendar.DAY_OF_YEAR));
- if (dateKey != prevDateKey) {
- prevDateKey = dateKey;
- mRows.add(new DateRow(DateFormat.format(dateFormatStr, cal).toString()));
- }
- mRows.add(new TaskRow(task, dateKey));
- mTaskRowCount.put(dateKey, mTaskRowCount.get(dateKey, 0) + 1);
- }
- notifyDataSetChanged();
- }
-
- /**
- * Removes historical tasks belonging to the specified package and user. We do not need to
- * remove the task from the TaskStack since the TaskStackView will also receive this event.
- */
- public void removeTasks(String packageName, int userId) {
- for (int i = mRows.size() - 1; i >= 0; i--) {
- Row row = mRows.get(i);
- if (row.getViewType() == TASK_ROW_VIEW_TYPE) {
- TaskRow taskRow = (TaskRow) row;
- Task task = taskRow.task;
- String taskPackage = task.key.getComponent().getPackageName();
- if (task.key.userId == userId && taskPackage.equals(packageName)) {
- i = removeTaskRow(i);
- }
- }
- }
- if (mRows.isEmpty()) {
- dismissHistory();
- }
- }
-
- /**
- * Removes all historical tasks.
- */
- public void removeAllTasks() {
- for (int i = mRows.size() - 1; i >= 0; i--) {
- Row row = mRows.get(i);
- if (row.getViewType() == TASK_ROW_VIEW_TYPE) {
- TaskRow taskRow = (TaskRow) row;
- Task task = taskRow.task;
- mStack.removeTask(task, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
- EventBus.getDefault().send(new DeleteTaskDataEvent(task));
- i = removeTaskRow(i);
- }
- }
- dismissHistory();
- }
-
- /**
- * Returns the row at the given {@param position}.
- */
- public Row getRow(int position) {
- return mRows.get(position);
- }
-
- @Override
- public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
- switch (viewType) {
- case DATE_ROW_VIEW_TYPE:
- return new ViewHolder(mLayoutInflater.inflate(R.layout.recents_history_date, parent,
- false));
- case TASK_ROW_VIEW_TYPE:
- return new ViewHolder(mLayoutInflater.inflate(R.layout.recents_history_task, parent,
- false));
- default:
- return new ViewHolder(null);
- }
- }
-
- @Override
- public void onBindViewHolder(ViewHolder holder, int position) {
- RecentsTaskLoader loader = Recents.getTaskLoader();
-
- Row row = mRows.get(position);
- int viewType = row.getViewType();
- switch (viewType) {
- case DATE_ROW_VIEW_TYPE: {
- TextView tv = (TextView) holder.content;
- tv.setText(((DateRow) row).date);
- break;
- }
- case TASK_ROW_VIEW_TYPE: {
- TaskRow taskRow = (TaskRow) row;
- TextView tv = (TextView) holder.content.findViewById(R.id.description);
- tv.setText(taskRow.task.title);
- ImageView iv = (ImageView) holder.content.findViewById(R.id.icon);
- iv.setAlpha(0f);
- holder.content.setOnClickListener(taskRow);
-
- holder.bindToTask(taskRow.task);
- loader.loadTaskData(taskRow.task, false /* fetchAndInvalidateThumbnails */);
- break;
- }
- }
- }
-
- @Override
- public void onViewRecycled(ViewHolder holder) {
- RecentsTaskLoader loader = Recents.getTaskLoader();
- int position = holder.getAdapterPosition();
- if (position != RecyclerView.NO_POSITION) {
- Row row = mRows.get(position);
- int viewType = row.getViewType();
- if (viewType == TASK_ROW_VIEW_TYPE) {
- TaskRow taskRow = (TaskRow) row;
- loader.unloadTaskData(taskRow.task);
- holder.unbindFromTask();
- }
- }
- }
-
- @Override
- public boolean onFailedToRecycleView(ViewHolder holder) {
- // Always recycle views, even if it is animating
- onViewRecycled(holder);
- return true;
- }
-
- public void onTaskRemoved(Task task, int position) {
- // Since this is removed from the history, we need to update the stack as well to ensure
- // that the model is correct. Since the stack is hidden, we can update it immediately.
- mStack.removeTask(task, AnimationProps.IMMEDIATE, false /* fromDockGesture */);
- removeTaskRow(position);
- if (mRows.isEmpty()) {
- dismissHistory();
- }
- }
-
- @Override
- public int getItemCount() {
- return mRows.size();
- }
-
- @Override
- public int getItemViewType(int position) {
- return mRows.get(position).getViewType();
- }
-
- /**
- * Removes a task row, also removing the associated {@link DateRow} if there are no more tasks
- * in that date group.
- *
- * @param position an adapter position of a task row such that 0 < position < num rows.
- * @return the index of the last removed row
- */
- private int removeTaskRow(int position) {
- // Remove the task at that row
- TaskRow taskRow = (TaskRow) mRows.remove(position);
- int numTasks = mTaskRowCount.get(taskRow.dateKey) - 1;
- mTaskRowCount.put(taskRow.dateKey, numTasks);
- notifyItemRemoved(position);
-
- if (numTasks == 0) {
- // If that was the last task row in the group, then remove the date as well
- mRows.remove(position - 1);
- mTaskRowCount.removeAt(mTaskRowCount.indexOfKey(taskRow.dateKey));
- notifyItemRemoved(position - 1);
- return position - 1;
- } else {
- return position;
- }
- }
-
- /**
- * Dismisses history back to the stack view.
- */
- private void dismissHistory() {
- EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
- EventBus.getDefault().send(new HideHistoryButtonEvent());
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryItemTouchCallbacks.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryItemTouchCallbacks.java
deleted file mode 100644
index 3d1ea8eedfbe..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryItemTouchCallbacks.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.history;
-
-import android.content.Context;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.helper.ItemTouchHelper;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.recents.Constants;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
-
-
-/**
- * An item touch handler for items in the history view.
- */
-public class RecentsHistoryItemTouchCallbacks extends ItemTouchHelper.SimpleCallback {
-
- private Context mContext;
- private RecentsHistoryAdapter mAdapter;
-
- public RecentsHistoryItemTouchCallbacks(Context context, RecentsHistoryAdapter adapter) {
- super(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT);
- mContext = context;
- mAdapter = adapter;
- }
-
- @Override
- public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
- RecyclerView.ViewHolder target) {
- return false;
- }
-
- @Override
- public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
- int viewType = mAdapter.getItemViewType(viewHolder.getAdapterPosition());
- switch (viewType) {
- case RecentsHistoryAdapter.DATE_ROW_VIEW_TYPE:
- // Disallow swiping
- return 0;
- default:
- return super.getSwipeDirs(recyclerView, viewHolder);
- }
- }
-
- @Override
- public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
- int position = viewHolder.getAdapterPosition();
- if (position != RecyclerView.NO_POSITION) {
- RecentsHistoryAdapter.Row row = mAdapter.getRow(position);
- RecentsHistoryAdapter.TaskRow taskRow = (RecentsHistoryAdapter.TaskRow) row;
-
- // Remove the task from the system
- EventBus.getDefault().send(new DeleteTaskDataEvent(taskRow.task));
- mAdapter.onTaskRemoved(taskRow.task, position);
-
- // Keep track of deletions by swiping within history
- MetricsLogger.histogram(mContext, "overview_task_dismissed_source",
- Constants.Metrics.DismissSourceHistorySwipeGesture);
- MetricsLogger.action(mContext, MetricsEvent.OVERVIEW_DISMISS,
- taskRow.task.key.getComponent().toString());
- }
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java b/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
deleted file mode 100644
index 3c4adb23e77a..000000000000
--- a/packages/SystemUI/src/com/android/systemui/recents/history/RecentsHistoryView.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.recents.history;
-
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Rect;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.support.v7.widget.helper.ItemTouchHelper;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.WindowInsets;
-import android.widget.LinearLayout;
-
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.MetricsProto.MetricsEvent;
-import com.android.systemui.Interpolators;
-import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsActivity;
-import com.android.systemui.recents.RecentsConfiguration;
-import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.ClearHistoryEvent;
-import com.android.systemui.recents.events.activity.PackagesChangedEvent;
-import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
-import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
-import com.android.systemui.recents.model.TaskStack;
-import com.android.systemui.recents.views.AnimateableViewBounds;
-
-/**
- * A list of the recent tasks that are not in the stack.
- */
-public class RecentsHistoryView extends LinearLayout
- implements ValueAnimator.AnimatorUpdateListener {
-
- private static final float TRANSLATION_Y_PCT = 0.25f;
- private static final float BG_SCRIM_ALPHA = 0.625f;
-
- private RecyclerView mRecyclerView;
- private RecentsHistoryAdapter mAdapter;
- private RecentsHistoryItemTouchCallbacks mItemTouchHandler;
- private AnimateableViewBounds mViewBounds;
- private boolean mIsVisible;
- private Rect mSystemInsets = new Rect();
- private int mHeaderHeight;
-
- private int mHistoryTransitionDuration;
-
- public RecentsHistoryView(Context context) {
- super(context);
- }
-
- public RecentsHistoryView(Context context, AttributeSet attrs) {
- this(context, attrs, 0);
- }
-
- public RecentsHistoryView(Context context, AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
- }
-
- public RecentsHistoryView(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- Resources res = context.getResources();
- mAdapter = new RecentsHistoryAdapter(context);
- mItemTouchHandler = new RecentsHistoryItemTouchCallbacks(context, mAdapter);
- mHistoryTransitionDuration = res.getInteger(R.integer.recents_history_transition_duration);
- mViewBounds = new AnimateableViewBounds(this, 0);
- setOutlineProvider(mViewBounds);
- }
-
- /**
- * Updates this history view with the recent tasks, and then shows it.
- */
- public void show(TaskStack stack, int stackHeight, View clearAllButton) {
- setVisibility(View.VISIBLE);
- setAlpha(0f);
- setTranslationY(-stackHeight * TRANSLATION_Y_PCT);
- animate()
- .alpha(1f)
- .translationY(0f)
- .setDuration(mHistoryTransitionDuration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .setUpdateListener(this)
- .start();
- clearAllButton.setVisibility(View.VISIBLE);
- clearAllButton.setAlpha(0f);
- clearAllButton.animate()
- .alpha(1f)
- .setDuration(mHistoryTransitionDuration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .withLayer()
- .start();
- mAdapter.updateTasks(getContext(), stack);
- mIsVisible = true;
- EventBus.getDefault().send(new UpdateBackgroundScrimEvent(BG_SCRIM_ALPHA));
-
- MetricsLogger.visible(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
- }
-
- /**
- * Hides this history view.
- */
- public void hide(boolean animate, int stackHeight, final View clearAllButton) {
- if (animate) {
- animate()
- .alpha(0f)
- .translationY(-stackHeight * TRANSLATION_Y_PCT)
- .setDuration(mHistoryTransitionDuration)
- .setInterpolator(Interpolators.FAST_OUT_LINEAR_IN)
- .setUpdateListener(this)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- setVisibility(View.INVISIBLE);
- }
- })
- .start();
- clearAllButton.animate()
- .alpha(0f)
- .translationY(0f)
- .setDuration(mHistoryTransitionDuration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- clearAllButton.setVisibility(View.INVISIBLE);
- }
- })
- .withLayer()
- .start();
- } else {
- setAlpha(0f);
- setVisibility(View.INVISIBLE);
- clearAllButton.setAlpha(0f);
- clearAllButton.setVisibility(View.INVISIBLE);
- }
- mIsVisible = false;
- EventBus.getDefault().send(new ResetBackgroundScrimEvent());
-
- MetricsLogger.hidden(mRecyclerView.getContext(), MetricsEvent.OVERVIEW_HISTORY);
- }
-
- /**
- * Updates the system insets of this history view to the provided values.
- */
- public void setSystemInsets(Rect systemInsets) {
- mSystemInsets.set(systemInsets);
- requestLayout();
- }
-
- /**
- * Updates the header height to account for the history button bar.
- */
- public void setHeaderHeight(int height) {
- mHeaderHeight = height;
- requestLayout();
- }
-
- /**
- * Returns whether this view is visible.
- */
- public boolean isVisible() {
- return mIsVisible;
- }
-
- @Override
- protected void onFinishInflate() {
- super.onFinishInflate();
- mRecyclerView = (RecyclerView) findViewById(R.id.list);
- mRecyclerView.setAdapter(mAdapter);
- mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
- mRecyclerView.getItemAnimator().setRemoveDuration(100);
- ItemTouchHelper touchHelper = new ItemTouchHelper(mItemTouchHandler);
- touchHelper.attachToRecyclerView(mRecyclerView);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- RecentsConfiguration config = Recents.getConfiguration();
- int width = MeasureSpec.getSize(widthMeasureSpec);
- int height = MeasureSpec.getSize(heightMeasureSpec);
-
- // Pad the view to align the history with the stack layout
- Rect taskStackBounds = new Rect();
- config.getTaskStackBounds(new Rect(0, 0, width, height), mSystemInsets.top,
- mSystemInsets.right, new Rect() /* searchBarSpaceBounds */, taskStackBounds);
- int stackWidthPadding = (int) (config.taskStackWidthPaddingPct * taskStackBounds.width());
- int stackHeightPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_stack_top_padding);
- mRecyclerView.setPadding(stackWidthPadding + mSystemInsets.left,
- stackHeightPadding + mSystemInsets.top + mHeaderHeight,
- stackWidthPadding + mSystemInsets.right, mSystemInsets.bottom);
-
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- }
-
- @Override
- protected void onAttachedToWindow() {
- EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
- super.onAttachedToWindow();
- }
-
- @Override
- protected void onDetachedFromWindow() {
- super.onDetachedFromWindow();
- EventBus.getDefault().unregister(this);
- }
-
- @Override
- public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- setSystemInsets(insets.getSystemWindowInsets());
- return insets;
- }
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- // Clip the top of the view by the header bar height
- int top = Math.max(0, (int) -getTranslationY()) + mSystemInsets.top + mHeaderHeight;
- mViewBounds.setClipTop(top);
- }
-
- @Override
- public boolean hasOverlappingRendering() {
- return false;
- }
-
- /**** EventBus Events ****/
-
- public final void onBusEvent(PackagesChangedEvent event) {
- mAdapter.removeTasks(event.packageName, event.userId);
- }
-
- public final void onBusEvent(ClearHistoryEvent event) {
- mAdapter.removeAllTasks();
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
index 532e79661c6a..6b3eab8cc212 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/SystemServicesProxy.java
@@ -16,15 +16,18 @@
package com.android.systemui.recents.misc;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.HOME_STACK_ID;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
+
import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.AppGlobals;
import android.app.IActivityManager;
import android.app.ITaskStackListener;
-import android.appwidget.AppWidgetHost;
-import android.appwidget.AppWidgetManager;
-import android.appwidget.AppWidgetProviderInfo;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.Context;
@@ -34,6 +37,7 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
@@ -47,8 +51,9 @@ import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.hardware.display.DisplayManager;
-import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.os.SystemProperties;
@@ -58,9 +63,9 @@ import android.provider.Settings;
import android.util.ArraySet;
import android.util.Log;
import android.util.MutableBoolean;
-import android.util.Pair;
import android.view.Display;
import android.view.IDockedStackListener;
+import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.WindowManager.KeyboardShortcutsReceiver;
@@ -69,10 +74,10 @@ import android.view.accessibility.AccessibilityManager;
import com.android.internal.app.AssistUtils;
import com.android.internal.os.BackgroundThread;
-import com.android.systemui.Prefs;
import com.android.systemui.R;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.RecentsImpl;
+import com.android.systemui.recents.tv.RecentsTvImpl;
import java.io.IOException;
import java.util.ArrayList;
@@ -80,12 +85,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Random;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.HOME_STACK_ID;
-import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
-import static android.provider.Settings.Global.DEVELOPMENT_ENABLE_FREEFORM_WINDOWS_SUPPORT;
-
/**
* Acts as a shim around the real system services that we need to access data from, and provides
* a point of injection when testing UI.
@@ -94,16 +93,23 @@ public class SystemServicesProxy {
final static String TAG = "SystemServicesProxy";
final static BitmapFactory.Options sBitmapOptions;
-
static {
sBitmapOptions = new BitmapFactory.Options();
sBitmapOptions.inMutable = true;
}
+ final static List<String> sRecentsBlacklist;
+ static {
+ sRecentsBlacklist = new ArrayList<>();
+ sRecentsBlacklist.add("com.android.systemui.tv.pip.PipOnboardingActivity");
+ sRecentsBlacklist.add("com.android.systemui.tv.pip.PipMenuActivity");
+ }
+
+ private static SystemServicesProxy sSystemServicesProxy;
+
AccessibilityManager mAccm;
ActivityManager mAm;
IActivityManager mIam;
- AppWidgetManager mAwm;
PackageManager mPm;
IPackageManager mIpm;
AssistUtils mAssistUtils;
@@ -122,12 +128,61 @@ public class SystemServicesProxy {
Paint mBgProtectionPaint;
Canvas mBgProtectionCanvas;
+ private final Handler mHandler = new H();
+
+ /**
+ * An abstract class to track task stack changes.
+ * Classes should implement this instead of {@link android.app.ITaskStackListener}
+ * to reduce IPC calls from system services. These callbacks will be called on the main thread.
+ */
+ public abstract static class TaskStackListener {
+ public void onTaskStackChanged() { }
+ public void onActivityPinned() { }
+ public void onPinnedActivityRestartAttempt() { }
+ public void onPinnedStackAnimationEnded() { }
+ }
+
+ /**
+ * Implementation of {@link android.app.ITaskStackListener} to listen task stack changes from
+ * ActivityManagerNative.
+ * This simply passes callbacks to listeners through {@link H}.
+ * */
+ private ITaskStackListener.Stub mTaskStackListener = new ITaskStackListener.Stub() {
+ @Override
+ public void onTaskStackChanged() throws RemoteException {
+ mHandler.removeMessages(H.ON_TASK_STACK_CHANGED);
+ mHandler.sendEmptyMessage(H.ON_TASK_STACK_CHANGED);
+ }
+
+ @Override
+ public void onActivityPinned() throws RemoteException {
+ mHandler.removeMessages(H.ON_ACTIVITY_PINNED);
+ mHandler.sendEmptyMessage(H.ON_ACTIVITY_PINNED);
+ }
+
+ @Override
+ public void onPinnedActivityRestartAttempt() throws RemoteException{
+ mHandler.removeMessages(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
+ mHandler.sendEmptyMessage(H.ON_PINNED_ACTIVITY_RESTART_ATTEMPT);
+ }
+
+ @Override
+ public void onPinnedStackAnimationEnded() throws RemoteException {
+ mHandler.removeMessages(H.ON_PINNED_STACK_ANIMATION_ENDED);
+ mHandler.sendEmptyMessage(H.ON_PINNED_STACK_ANIMATION_ENDED);
+ }
+ };
+
+ /**
+ * List of {@link TaskStackListener} registered from {@link registerTaskStackListener}.
+ */
+ private List<TaskStackListener> mTaskStackListeners = new ArrayList<>();
+
/** Private constructor */
- public SystemServicesProxy(Context context) {
+ private SystemServicesProxy(Context context) {
mAccm = AccessibilityManager.getInstance(context);
mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
mIam = ActivityManagerNative.getDefault();
- mAwm = AppWidgetManager.getInstance(context);
mPm = context.getPackageManager();
mIpm = AppGlobals.getPackageManager();
mAssistUtils = new AssistUtils(context);
@@ -164,6 +219,20 @@ public class SystemServicesProxy {
}
}
+ /**
+ * Returns the single instance of the {@link SystemServicesProxy}.
+ * This should only be called on the main thread.
+ */
+ public static SystemServicesProxy getInstance(Context context) {
+ if (!Looper.getMainLooper().isCurrentThread()) {
+ throw new RuntimeException("Must be called on the UI thread");
+ }
+ if (sSystemServicesProxy == null) {
+ sSystemServicesProxy = new SystemServicesProxy(context);
+ }
+ return sSystemServicesProxy;
+ }
+
/** Returns a list of the recents tasks */
public List<ActivityManager.RecentTaskInfo> getRecentTasks(int numLatestTasks, int userId,
boolean isTopTaskHome, ArraySet<Integer> quietProfileIds) {
@@ -227,12 +296,13 @@ public class SystemServicesProxy {
// Check the first non-recents task, include this task even if it is marked as excluded
// from recents if we are currently in the app. In other words, only remove excluded
- // tasks if it is not the first active task.
+ // tasks if it is not the first active task, and not in the blacklist.
boolean isExcluded = (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
== Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS;
+ boolean isBlackListed = sRecentsBlacklist.contains(t.realActivity.getClassName());
// Filter out recent tasks from managed profiles which are in quiet mode.
isExcluded |= quietProfileIds.contains(t.userId);
- if (isExcluded && (isTopTaskHome || !isFirstValidTask)) {
+ if (isBlackListed || (isExcluded && (isTopTaskHome || !isFirstValidTask))) {
iter.remove();
continue;
}
@@ -280,7 +350,7 @@ public class SystemServicesProxy {
// Check if the front most activity is recents
if ((topActivity.getPackageName().equals(RecentsImpl.RECENTS_PACKAGE) &&
(topActivity.getClassName().equals(RecentsImpl.RECENTS_ACTIVITY) ||
- topActivity.getClassName().equals(RecentsImpl.RECENTS_TV_ACTIVITY)))) {
+ topActivity.getClassName().equals(RecentsTvImpl.RECENTS_TV_ACTIVITY)))) {
if (isHomeTopMost != null) {
isHomeTopMost.value = false;
}
@@ -778,89 +848,6 @@ public class SystemServicesProxy {
}
/**
- * Returns the current search widget id.
- */
- public int getSearchAppWidgetId(Context context) {
- return Prefs.getInt(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID, -1);
- }
-
- /**
- * Returns the current search widget info, binding a new one if necessary.
- */
- public AppWidgetProviderInfo getOrBindSearchAppWidget(Context context, AppWidgetHost host) {
- int searchWidgetId = Prefs.getInt(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID, -1);
- AppWidgetProviderInfo searchWidgetInfo = mAwm.getAppWidgetInfo(searchWidgetId);
- AppWidgetProviderInfo resolvedSearchWidgetInfo = resolveSearchAppWidget();
-
- // Return the search widget info if it hasn't changed
- if (searchWidgetInfo != null && resolvedSearchWidgetInfo != null &&
- searchWidgetInfo.provider.equals(resolvedSearchWidgetInfo.provider)) {
- if (Prefs.getString(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE, null) == null) {
- Prefs.putString(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE,
- searchWidgetInfo.provider.getPackageName());
- }
- return searchWidgetInfo;
- }
-
- // Delete the old widget
- if (searchWidgetId != -1) {
- host.deleteAppWidgetId(searchWidgetId);
- }
-
- // And rebind a new search widget
- if (resolvedSearchWidgetInfo != null) {
- Pair<Integer, AppWidgetProviderInfo> widgetInfo = bindSearchAppWidget(host,
- resolvedSearchWidgetInfo);
- if (widgetInfo != null) {
- Prefs.putInt(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID, widgetInfo.first);
- Prefs.putString(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE,
- widgetInfo.second.provider.getPackageName());
- return widgetInfo.second;
- }
- }
-
- // If we fall through here, then there is no resolved search widget, so clear the state
- Prefs.remove(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_ID);
- Prefs.remove(context, Prefs.Key.OVERVIEW_SEARCH_APP_WIDGET_PACKAGE);
- return null;
- }
-
- /**
- * Returns the first Recents widget from the same package as the global assist activity.
- */
- public AppWidgetProviderInfo resolveSearchAppWidget() {
- if (mAssistComponent == null) return null;
- List<AppWidgetProviderInfo> widgets = mAwm.getInstalledProviders(
- AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
- for (AppWidgetProviderInfo info : widgets) {
- if (info.provider.getPackageName().equals(mAssistComponent.getPackageName())) {
- return info;
- }
- }
- return null;
- }
-
- /**
- * Resolves and binds the search app widget that is to appear in the recents.
- */
- private Pair<Integer, AppWidgetProviderInfo> bindSearchAppWidget(AppWidgetHost host,
- AppWidgetProviderInfo resolvedSearchWidgetInfo) {
- if (mAwm == null) return null;
- if (mAssistComponent == null) return null;
-
- // Allocate a new widget id and try and bind the app widget (if that fails, then just skip)
- int searchWidgetId = host.allocateAppWidgetId();
- Bundle opts = new Bundle();
- opts.putInt(AppWidgetManager.OPTION_APPWIDGET_HOST_CATEGORY,
- AppWidgetProviderInfo.WIDGET_CATEGORY_SEARCHBOX);
- if (!mAwm.bindAppWidgetIdIfAllowed(searchWidgetId, resolvedSearchWidgetInfo.provider, opts)) {
- host.deleteAppWidgetId(searchWidgetId);
- return null;
- }
- return new Pair<>(searchWidgetId, resolvedSearchWidgetInfo);
- }
-
- /**
* Returns whether touch exploration is currently enabled.
*/
public boolean isTouchExplorationEnabled() {
@@ -909,28 +896,40 @@ public class SystemServicesProxy {
* Returns the smallest width/height.
*/
public int getDeviceSmallestWidth() {
- if (mWm == null) return 0;
+ if (mDisplay == null) return 0;
Point smallestSizeRange = new Point();
Point largestSizeRange = new Point();
- mWm.getDefaultDisplay().getCurrentSizeRange(smallestSizeRange, largestSizeRange);
+ mDisplay.getCurrentSizeRange(smallestSizeRange, largestSizeRange);
return smallestSizeRange.x;
}
/**
- * Returns the display rect.
+ * Returns the current display rect in the current display orientation.
*/
public Rect getDisplayRect() {
Rect displayRect = new Rect();
- if (mWm == null) return displayRect;
+ if (mDisplay == null) return displayRect;
Point p = new Point();
- mWm.getDefaultDisplay().getRealSize(p);
+ mDisplay.getRealSize(p);
displayRect.set(0, 0, p.x, p.y);
return displayRect;
}
/**
+ * Returns the current display orientation.
+ */
+ public int getDisplayOrientation() {
+ // Because of multi-window, the configuration orientation does not necessarily reflect the
+ // orientation of the display, instead we just use the display's real-size.
+ Rect displayRect = getDisplayRect();
+ return displayRect.width() > displayRect.height()
+ ? Configuration.ORIENTATION_LANDSCAPE
+ : Configuration.ORIENTATION_PORTRAIT;
+ }
+
+ /**
* Returns the window rect for the RecentsActivity, based on the dimensions of the home stack.
*/
public Rect getWindowRect() {
@@ -975,14 +974,21 @@ public class SystemServicesProxy {
}
}
- /** Registers a task stack listener with the system. */
- public void registerTaskStackListener(ITaskStackListener listener) {
+ /**
+ * Registers a task stack listener with the system.
+ * This should be called on the main thread.
+ */
+ public void registerTaskStackListener(TaskStackListener listener) {
if (mIam == null) return;
- try {
- mIam.registerTaskStackListener(listener);
- } catch (Exception e) {
- e.printStackTrace();
+ mTaskStackListeners.add(listener);
+ if (mTaskStackListeners.size() == 1) {
+ // Register mTaskStackListener to IActivityManager only once if needed.
+ try {
+ mIam.registerTaskStackListener(mTaskStackListener);
+ } catch (Exception e) {
+ Log.w(TAG, "Failed to call registerTaskStackListener", e);
+ }
}
}
@@ -1032,4 +1038,41 @@ public class SystemServicesProxy {
e.printStackTrace();
}
}
+
+ private final class H extends Handler {
+ private static final int ON_TASK_STACK_CHANGED = 1;
+ private static final int ON_ACTIVITY_PINNED = 2;
+ private static final int ON_PINNED_ACTIVITY_RESTART_ATTEMPT = 3;
+ private static final int ON_PINNED_STACK_ANIMATION_ENDED = 4;
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case ON_TASK_STACK_CHANGED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onTaskStackChanged();
+ }
+ break;
+ }
+ case ON_ACTIVITY_PINNED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onActivityPinned();
+ }
+ break;
+ }
+ case ON_PINNED_ACTIVITY_RESTART_ATTEMPT: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onPinnedActivityRestartAttempt();
+ }
+ break;
+ }
+ case ON_PINNED_STACK_ANIMATION_ENDED: {
+ for (int i = mTaskStackListeners.size() - 1; i >= 0; i--) {
+ mTaskStackListeners.get(i).onPinnedStackAnimationEnded();
+ }
+ break;
+ }
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index 72b1cab5af22..e28612a3cff6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -19,6 +19,7 @@ package com.android.systemui.recents.misc;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.annotation.FloatRange;
+import android.content.res.Resources;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.RectF;
@@ -26,6 +27,7 @@ import android.graphics.drawable.Drawable;
import android.util.ArraySet;
import android.util.IntProperty;
import android.util.Property;
+import android.util.TypedValue;
import android.view.View;
import android.view.ViewParent;
@@ -67,6 +69,8 @@ public class Utilities {
public static final RectFEvaluator RECTF_EVALUATOR = new RectFEvaluator();
+ public static final Rect EMPTY_RECT = new Rect();
+
/**
* @return the first parent walking up the view hierarchy that has the given class type.
*
@@ -232,4 +236,11 @@ public class Utilities {
transforms.subList(taskCount, taskTransformCount).clear();
}
}
+
+ /**
+ * Used for debugging, converts DP to PX.
+ */
+ public static float dpToPx(Resources res, float dp) {
+ return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
index 6ae07fc89a5a..c86347144523 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/RecentsTaskLoadPlan.java
@@ -39,7 +39,6 @@ import com.android.systemui.recents.misc.SystemServicesProxy;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Formatter;
import java.util.List;
@@ -196,7 +195,7 @@ public class RecentsTaskLoadPlan {
// Add the task to the stack
Task task = new Task(taskKey, t.affiliatedTaskId, t.affiliatedTaskColor, icon,
thumbnail, title, contentDescription, dismissDescription, activityColor,
- backgroundColor, !isStackTask, isLaunchTarget, isSystemApp, t.isDockable,
+ backgroundColor, isLaunchTarget, isStackTask, isSystemApp, t.isDockable,
t.bounds, t.taskDescription);
allTasks.add(task);
@@ -273,7 +272,7 @@ public class RecentsTaskLoadPlan {
}
/**
- * Returns whether this task is considered a task to be shown in the history.
+ * Returns whether this task is too old to be shown.
*/
private boolean isHistoricalTask(ActivityManager.RecentTaskInfo t) {
return t.lastActiveTime < (System.currentTimeMillis() - SESSION_BEGIN_TIME);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index b5a5949d0c48..3e858a860a88 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -161,7 +161,7 @@ public class Task {
@ViewDebug.ExportedProperty(category="recents")
public boolean isLaunchTarget;
@ViewDebug.ExportedProperty(category="recents")
- public boolean isHistorical;
+ public boolean isStackTask;
@ViewDebug.ExportedProperty(category="recents")
public boolean isSystemApp;
@ViewDebug.ExportedProperty(category="recents")
@@ -176,7 +176,7 @@ public class Task {
public Task(TaskKey key, int affiliationTaskId, int affiliationColor, Drawable icon,
Bitmap thumbnail, String title, String contentDescription,
String dismissDescription, int colorPrimary, int colorBackground,
- boolean isHistorical, boolean isLaunchTarget, boolean isSystemApp,
+ boolean isLaunchTarget, boolean isStackTask, boolean isSystemApp,
boolean isDockable, Rect bounds, ActivityManager.TaskDescription taskDescription) {
boolean isInAffiliationGroup = (affiliationTaskId != key.id);
boolean hasAffiliationGroupColor = isInAffiliationGroup && (affiliationColor != 0);
@@ -195,7 +195,7 @@ public class Task {
this.bounds = bounds;
this.taskDescription = taskDescription;
this.isLaunchTarget = isLaunchTarget;
- this.isHistorical = isHistorical;
+ this.isStackTask = isStackTask;
this.isSystemApp = isSystemApp;
this.isDockable = isDockable;
}
@@ -218,7 +218,7 @@ public class Task {
this.useLightOnPrimaryColor = o.useLightOnPrimaryColor;
this.bounds = o.bounds;
this.isLaunchTarget = o.isLaunchTarget;
- this.isHistorical = o.isHistorical;
+ this.isStackTask = o.isStackTask;
this.isSystemApp = o.isSystemApp;
this.isDockable = o.isDockable;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 193bfffffd9f..930e2d02b1c5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -16,6 +16,16 @@
package com.android.systemui.recents.model;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
+import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.view.WindowManager.DOCKED_BOTTOM;
+import static android.view.WindowManager.DOCKED_INVALID;
+import static android.view.WindowManager.DOCKED_LEFT;
+import static android.view.WindowManager.DOCKED_RIGHT;
+import static android.view.WindowManager.DOCKED_TOP;
+
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
@@ -37,13 +47,13 @@ import android.view.animation.Interpolator;
import com.android.internal.policy.DockedDividerUtils;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.misc.NamedCounter;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
-import com.android.systemui.recents.views.DropTarget;
import com.android.systemui.recents.views.AnimationProps;
+import com.android.systemui.recents.views.DropTarget;
+import com.android.systemui.recents.views.TaskStackLayoutAlgorithm;
import java.util.ArrayList;
import java.util.Collections;
@@ -51,16 +61,6 @@ import java.util.Comparator;
import java.util.List;
import java.util.Random;
-import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_BOTTOM_OR_RIGHT;
-import static android.app.ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.view.WindowManager.DOCKED_BOTTOM;
-import static android.view.WindowManager.DOCKED_INVALID;
-import static android.view.WindowManager.DOCKED_LEFT;
-import static android.view.WindowManager.DOCKED_RIGHT;
-import static android.view.WindowManager.DOCKED_TOP;
-
/**
* An interface for a task filter to query whether a particular task should show in a stack.
@@ -220,11 +220,6 @@ public class TaskStack {
*/
void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture);
-
- /**
- * Notifies when a task has been removed from the history.
- */
- void onHistoryTaskRemoved(TaskStack stack, Task removedTask, AnimationProps animation);
}
/**
@@ -375,29 +370,24 @@ public class TaskStack {
* {@param height}.
*/
public Rect getDockedTaskStackBounds(int width, int height, int dividerSize, Rect insets,
- Resources res) {
- RecentsConfiguration config = Recents.getConfiguration();
-
+ TaskStackLayoutAlgorithm layoutAlgorithm, Resources res, Rect windowRectOut) {
// Calculate the inverse docked task bounds
boolean isHorizontalDivision =
res.getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
int position = DockedDividerUtils.calculateMiddlePosition(isHorizontalDivision,
insets, width, height, dividerSize);
- Rect newWindowBounds = new Rect();
DockedDividerUtils.calculateBoundsForPosition(position,
- DockedDividerUtils.invertDockSide(dockSide), newWindowBounds, width, height,
+ DockedDividerUtils.invertDockSide(dockSide), windowRectOut, width, height,
dividerSize);
// Calculate the task stack bounds from the new window bounds
- Rect searchBarSpaceBounds = new Rect();
Rect taskStackBounds = new Rect();
// If the task stack bounds is specifically under the dock area, then ignore the top
// inset
int top = dockArea.bottom < 1f
? 0
: insets.top;
- config.getTaskStackBounds(newWindowBounds, top, insets.right,
- searchBarSpaceBounds, taskStackBounds);
+ layoutAlgorithm.getTaskStackBounds(windowRectOut, top, insets.right, taskStackBounds);
return taskStackBounds;
}
}
@@ -429,7 +419,6 @@ public class TaskStack {
ArrayList<Task> mRawTaskList = new ArrayList<>();
FilteredTaskList mStackTaskList = new FilteredTaskList();
- FilteredTaskList mHistoryTaskList = new FilteredTaskList();
TaskStackCallbacks mCb;
ArrayList<TaskGrouping> mGroups = new ArrayList<>();
@@ -448,21 +437,7 @@ public class TaskStack {
t = parentTask;
}
}
- return !t.isHistorical;
- }
- });
- mHistoryTaskList.setFilter(new TaskFilter() {
- @Override
- public boolean acceptTask(SparseArray<Task> taskIdMap, Task t, int index) {
- if (t.isAffiliatedTask()) {
- // If this task is affiliated with another parent in the stack, then the
- // historical state of this task depends on the state of the parent task
- Task parentTask = taskIdMap.get(t.affiliationTaskId);
- if (parentTask != null) {
- t = parentTask;
- }
- }
- return t.isHistorical;
+ return t.isStackTask;
}
});
}
@@ -523,12 +498,6 @@ public class TaskStack {
mCb.onStackTaskRemoved(this, t, wasFrontMostTask, newFrontMostTask, animation,
fromDockGesture);
}
- } else if (mHistoryTaskList.contains(t)) {
- removeTaskImpl(mHistoryTaskList, t);
- if (mCb != null) {
- // Notify that a task has been removed
- mCb.onHistoryTaskRemoved(this, t, animation);
- }
}
mRawTaskList.remove(t);
}
@@ -586,21 +555,7 @@ public class TaskStack {
// Sort all the tasks to ensure they are ordered correctly
Collections.sort(allTasks, FREEFORM_LAST_ACTIVE_TIME_COMPARATOR);
- // Filter out the historical tasks from this new list
- ArrayList<Task> stackTasks = new ArrayList<>();
- ArrayList<Task> historyTasks = new ArrayList<>();
- int newTaskCount = allTasks.size();
- for (int i = 0; i < newTaskCount; i++) {
- Task task = allTasks.get(i);
- if (task.isHistorical) {
- historyTasks.add(task);
- } else {
- stackTasks.add(task);
- }
- }
-
- mStackTaskList.set(stackTasks);
- mHistoryTaskList.set(historyTasks);
+ mStackTaskList.set(allTasks);
mRawTaskList = allTasks;
// Only callback for the newly added tasks after this stack has been updated
@@ -650,14 +605,6 @@ public class TaskStack {
}
/**
- * Returns the set of tasks that are inactive. These tasks will be presented in a separate
- * history view.
- */
- public ArrayList<Task> getHistoricalTasks() {
- return mHistoryTaskList.getTasks();
- }
-
- /**
* Returns the set of "freeform" tasks in the stack.
*/
public ArrayList<Task> getFreeformTasks() {
@@ -679,7 +626,6 @@ public class TaskStack {
public ArrayList<Task> computeAllTasksList() {
ArrayList<Task> tasks = new ArrayList<>();
tasks.addAll(mStackTaskList.getTasks());
- tasks.addAll(mHistoryTaskList.getTasks());
Collections.sort(tasks, LAST_ACTIVE_TIME_COMPARATOR);
return tasks;
}
@@ -927,10 +873,6 @@ public class TaskStack {
for (Task t : mStackTaskList.getTasks()) {
str += " " + t.toString() + "\n";
}
- str += "Historical Tasks(" + mHistoryTaskList.size() + "):\n";
- for (Task t : mHistoryTaskList.getTasks()) {
- str += " " + t.toString() + "\n";
- }
return str;
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
index dae522f2c072..d8e82d9e86ec 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvActivity.java
@@ -85,9 +85,13 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
private PipManager mPipManager;
private PipManager.Listener mPipListener = new PipManager.Listener() {
@Override
+ public void onPipEntered() {
+ updatePipUI();
+ }
+
+ @Override
public void onPipActivityClosed() {
- mPipView.setVisibility(View.GONE);
- mPipShadeView.setVisibility(View.GONE);
+ updatePipUI();
}
@Override
@@ -102,6 +106,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
@Override
public void onMediaControllerChanged() { }
};
+ private boolean mHasPip;
/**
* A common Runnable to finish Recents by launching Home with an animation depending on the
@@ -121,15 +126,8 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
@Override
public void run() {
try {
- RecentsActivityLaunchState launchState =
- Recents.getConfiguration().getLaunchState();
ActivityOptions opts = ActivityOptions.makeCustomAnimation(RecentsTvActivity.this,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_enter :
- R.anim.recents_to_launcher_enter,
- launchState.launchedFromSearchHome ?
- R.anim.recents_to_search_launcher_exit :
- R.anim.recents_to_launcher_exit);
+ R.anim.recents_to_launcher_enter, R.anim.recents_to_launcher_exit);
startActivityAsUser(mLaunchIntent, opts.toBundle(), UserHandle.CURRENT);
} catch (Exception e) {
Log.e(TAG, getString(R.string.recents_launch_error_message, "Home"), e);
@@ -266,6 +264,10 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
homeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK |
Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
mFinishLaunchHomeRunnable = new FinishRecentsRunnable(homeIntent);
+
+ mHasPip = false;
+ updatePipUI();
+ mPipManager.addListener(mPipListener);
}
@Override
@@ -296,34 +298,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
SystemServicesProxy ssp = Recents.getSystemServices();
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, true));
- if (mPipManager.isPipShown()) {
- // Place mPipView at the PIP bounds for fine tuned focus handling.
- Rect pipBounds = mPipManager.getPipBounds();
- LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
- lp.width = pipBounds.width();
- lp.height = pipBounds.height();
- lp.leftMargin = pipBounds.left;
- lp.topMargin = pipBounds.top;
- mPipView.setLayoutParams(lp);
-
- mPipView.setVisibility(View.VISIBLE);
- mPipView.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- mPipManager.resizePinnedStack(PipManager.STATE_PIP_MENU);
- }
- });
- mPipView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
- @Override
- public void onFocusChange(View v, boolean hasFocus) {
- mPipManager.onPipViewFocusChangedInRecents(hasFocus);
- mPipShadeView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
- }
- });
- mPipManager.addListener(mPipListener);
- } else {
- mPipView.setVisibility(View.GONE);
- }
mPipManager.onRecentsStarted();
// Give focus to the recents row whenever its visible to an user.
mRecentsView.requestFocus();
@@ -340,7 +314,6 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
super.onStop();
mPipManager.onRecentsStopped();
- mPipManager.removeListener(mPipListener);
mIgnoreAltTabRelease = false;
// Notify that recents is now hidden
EventBus.getDefault().send(new RecentsVisibilityChangedEvent(this, false));
@@ -357,6 +330,7 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
protected void onDestroy() {
super.onDestroy();
+ mPipManager.removeListener(mPipListener);
// In the case that the activity finished on startup, just skip the unregistration below
if (mFinishedOnStartup) {
return;
@@ -480,4 +454,40 @@ public class RecentsTvActivity extends Activity implements OnPreDrawListener {
});
return true;
}
+
+ private void updatePipUI() {
+ if (mHasPip == mPipManager.isPipShown()) {
+ return;
+ }
+ mHasPip = mPipManager.isPipShown();
+ if (mHasPip) {
+ // Place mPipView at the PIP bounds for fine tuned focus handling.
+ Rect pipBounds = mPipManager.getPipBounds();
+ LayoutParams lp = (LayoutParams) mPipView.getLayoutParams();
+ lp.width = pipBounds.width();
+ lp.height = pipBounds.height();
+ lp.leftMargin = pipBounds.left;
+ lp.topMargin = pipBounds.top;
+ mPipView.setLayoutParams(lp);
+
+ mPipView.setVisibility(View.VISIBLE);
+ mPipView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ mPipManager.resizePinnedStack(PipManager.STATE_PIP_MENU);
+ }
+ });
+ mPipView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
+ @Override
+ public void onFocusChange(View v, boolean hasFocus) {
+ mPipManager.onPipViewFocusChangedInRecents(hasFocus);
+ mPipShadeView.setVisibility(hasFocus ? View.VISIBLE : View.INVISIBLE);
+ }
+ });
+ mPipShadeView.setVisibility(View.GONE);
+ } else {
+ mPipView.setVisibility(View.GONE);
+ mPipShadeView.setVisibility(View.GONE);
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
new file mode 100644
index 000000000000..aa273250e8b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/RecentsTvImpl.java
@@ -0,0 +1,137 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.recents.tv;
+
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import com.android.systemui.recents.*;
+import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.events.activity.RecentsActivityStartingEvent;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.model.RecentsTaskLoader;
+import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+public class RecentsTvImpl extends RecentsImpl{
+ public final static String RECENTS_TV_ACTIVITY =
+ "com.android.systemui.recents.tv.RecentsTvActivity";
+
+ public RecentsTvImpl(Context context) {
+ super(context);
+ }
+
+ @Override
+ protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
+ boolean isTopTaskHome, boolean animate) {
+ RecentsTaskLoader loader = Recents.getTaskLoader();
+
+ // In the case where alt-tab is triggered, we never get a preloadRecents() call, so we
+ // should always preload the tasks now. If we are dragging in recents, reload them as
+ // the stacks might have changed.
+ if (mTriggeredFromAltTab || sInstanceLoadPlan == null) {
+ // Create a new load plan if preloadRecents() was never triggered
+ sInstanceLoadPlan = loader.createLoadPlan(mContext);
+ }
+ if (mTriggeredFromAltTab || !sInstanceLoadPlan.hasTasks()) {
+ loader.preloadTasks(sInstanceLoadPlan, topTask.id, isTopTaskHome);
+ }
+ TaskStack stack = sInstanceLoadPlan.getTaskStack();
+
+ if (!animate) {
+ ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext, -1, -1);
+ startRecentsActivity(topTask, opts, false /* fromHome */, false /* fromThumbnail*/);
+ return;
+ }
+
+ boolean hasRecentTasks = stack.getTaskCount() > 0;
+ boolean useThumbnailTransition = (topTask != null) && !isTopTaskHome && hasRecentTasks;
+
+ if (useThumbnailTransition) {
+ // Try starting with a thumbnail transition
+ ActivityOptions opts = getThumbnailTransitionActivityOptionsForTV(topTask);
+ if (opts != null) {
+ startRecentsActivity(topTask, opts, false /* fromHome */, true /* fromThumbnail */);
+ } else {
+ // Fall through below to the non-thumbnail transition
+ useThumbnailTransition = false;
+ }
+ }
+
+ if (!useThumbnailTransition) {
+ // If there is no thumbnail transition, but is launching from home into recents, then
+ // use a quick home transition and do the animation from home
+ if (hasRecentTasks) {
+ ActivityOptions opts = getHomeTransitionActivityOptions();
+ startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
+ } else {
+ // Otherwise we do the normal fade from an unknown source
+ ActivityOptions opts = getUnknownTransitionActivityOptions();
+ startRecentsActivity(topTask, opts, true /* fromHome */, false /* fromThumbnail */);
+ }
+ }
+ mLastToggleTime = SystemClock.elapsedRealtime();
+ }
+
+ protected void startRecentsActivity(ActivityManager.RunningTaskInfo topTask,
+ ActivityOptions opts, boolean fromHome, boolean fromThumbnail) {
+ // Update the configuration based on the launch options
+ RecentsConfiguration config = Recents.getConfiguration();
+ RecentsActivityLaunchState launchState = config.getLaunchState();
+ launchState.launchedFromHome = fromHome;
+ launchState.launchedFromApp = fromThumbnail;
+ launchState.launchedToTaskId = (topTask != null) ? topTask.id : -1;
+ launchState.launchedWithAltTab = mTriggeredFromAltTab;
+ launchState.launchedReuseTaskStackViews = mCanReuseTaskStackViews;
+ launchState.launchedHasConfigurationChanged = false;
+
+ Intent intent = new Intent();
+ intent.setClassName(RECENTS_PACKAGE, RECENTS_TV_ACTIVITY);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
+ | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
+ | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
+
+ if (opts != null) {
+ mContext.startActivityAsUser(intent, opts.toBundle(), UserHandle.CURRENT);
+ } else {
+ mContext.startActivityAsUser(intent, UserHandle.CURRENT);
+ }
+ mCanReuseTaskStackViews = true;
+ EventBus.getDefault().send(new RecentsActivityStartingEvent());
+ }
+
+ /**
+ * Creates the activity options for an app->recents transition on TV.
+ */
+ private ActivityOptions getThumbnailTransitionActivityOptionsForTV(
+ ActivityManager.RunningTaskInfo topTask) {
+ Bitmap thumbnail = mThumbnailTransitionBitmapCache;
+ Rect rect = TaskCardView.getStartingCardThumbnailRect(mContext);
+ if (thumbnail != null) {
+ return ActivityOptions.makeThumbnailAspectScaleDownAnimation(mDummyStackView,
+ null, (int) rect.left, (int) rect.top,
+ (int) rect.width(), (int) rect.height(), mHandler, null);
+ }
+ // If both the screenshot and thumbnail fails, then just fall back to the default transition
+ return getUnknownTransitionActivityOptions();
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
new file mode 100644
index 000000000000..8996d0b2e8c2
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/DismissAnimationsHolder.java
@@ -0,0 +1,80 @@
+/*
+ * 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.
+ */
+package com.android.systemui.recents.tv.animations;
+
+
+import android.animation.Animator;
+import android.content.res.Resources;
+import android.support.v4.view.animation.FastOutSlowInInterpolator;
+import android.view.View;
+import android.widget.LinearLayout;
+import com.android.systemui.recents.tv.views.TaskCardView;
+
+import com.android.systemui.R;
+
+public class DismissAnimationsHolder {
+ private LinearLayout mDismissArea;
+ private LinearLayout mTaskCardView;
+ private FastOutSlowInInterpolator mFastOutSlowIn;
+ private int mCardYDelta;
+ private long mShortDuration;
+ private long mLongDuration;
+
+ public DismissAnimationsHolder(TaskCardView taskCardView) {
+ mTaskCardView = (LinearLayout) taskCardView.findViewById(R.id.recents_tv_card);
+ mDismissArea = (LinearLayout) taskCardView.findViewById(R.id.card_dismiss);
+ mFastOutSlowIn = new FastOutSlowInInterpolator();
+
+ Resources res = taskCardView.getResources();
+ mCardYDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_shift_down);
+ mShortDuration = res.getInteger(R.integer.dismiss_short_duration);
+ mLongDuration = res.getInteger(R.integer.dismiss_long_duration);
+ }
+
+ public void startEnterAnimation() {
+ mDismissArea.animate().setDuration(mShortDuration);
+ mDismissArea.animate().setInterpolator(mFastOutSlowIn);
+ mDismissArea.animate().alpha(1.0f);
+
+ mTaskCardView.animate().setDuration(mShortDuration);
+ mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
+ mTaskCardView.animate().translationYBy(mCardYDelta);
+ mTaskCardView.animate().alpha(0.5f);
+ }
+
+ public void startExitAnimation() {
+ mDismissArea.animate().setDuration(mShortDuration);
+ mDismissArea.animate().setInterpolator(mFastOutSlowIn);
+ mDismissArea.animate().alpha(0.0f);
+
+ mTaskCardView.animate().setDuration(mShortDuration);
+ mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
+ mTaskCardView.animate().translationYBy(-mCardYDelta);
+ mTaskCardView.animate().alpha(1.0f);
+ }
+
+ public void startDismissAnimation(Animator.AnimatorListener listener) {
+ mDismissArea.animate().setDuration(mShortDuration);
+ mDismissArea.animate().setInterpolator(mFastOutSlowIn);
+ mDismissArea.animate().alpha(0.0f);
+
+ mTaskCardView.animate().setDuration(mLongDuration);
+ mTaskCardView.animate().setInterpolator(mFastOutSlowIn);
+ mTaskCardView.animate().translationYBy(mCardYDelta);
+ mTaskCardView.animate().alpha(0.0f);
+ mTaskCardView.animate().setListener(listener);
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
index 365b29d67676..888561c2172b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/animations/ViewFocusAnimator.java
@@ -33,6 +33,8 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
private final float mSelectedScaleDelta;
private final float mUnselectedZ;
private final float mSelectedZDelta;
+ private final float mUnselectedSpacing;
+ private final float mSelectedSpacingDelta;
private final int mAnimDuration;
private final Interpolator mFocusInterpolator;
@@ -57,6 +59,9 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
mUnselectedZ = res.getDimensionPixelOffset(R.dimen.recents_tv_unselected_item_z);
mSelectedZDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_selected_item_z_delta);
+ mUnselectedSpacing = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_card_spacing);
+ mSelectedSpacingDelta = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_focused_card_delta);
+
mAnimDuration = res.getInteger(R.integer.item_scale_anim_duration);
mFocusInterpolator = new AccelerateDecelerateInterpolator();
@@ -85,10 +90,14 @@ public class ViewFocusAnimator implements View.OnFocusChangeListener {
float scale = mUnselectedScale + (level * mSelectedScaleDelta);
float z = mUnselectedZ + (level * mSelectedZDelta);
+ float spacing = mUnselectedSpacing + (level * mSelectedSpacingDelta);
mTargetView.setScaleX(scale);
mTargetView.setScaleY(scale);
mTargetView.setZ(z);
+
+ mTargetView.setPadding((int) spacing, mTargetView.getPaddingTop(),
+ (int) spacing, mTargetView.getPaddingBottom());
}
public float getFocusProgress() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
index bf6229cc0307..3d5176f2554e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/RecentsTvView.java
@@ -104,28 +104,6 @@ public class RecentsTvView extends FrameLayout {
requestLayout();
}
- public Task getNextTaskOrTopTask(Task taskToSearch) {
- Task returnTask = null;
- boolean found = false;
- if (mTaskStackHorizontalView != null) {
- TaskStack stack = mTaskStackHorizontalView.getStack();
- ArrayList<Task> taskList = stack.getStackTasks();
- // Iterate the stack views and try and find the focused task
- for (int j = taskList.size() - 1; j >= 0; --j) {
- Task task = taskList.get(j);
- // Return the next task in the line.
- if (found)
- return task;
- // Remember the first possible task as the top task.
- if (returnTask == null)
- returnTask = task;
- if (task == taskToSearch)
- found = true;
- }
- }
- return returnTask;
- }
-
public boolean launchFocusedTask() {
if (mTaskStackHorizontalView != null) {
Task task = mTaskStackHorizontalView.getFocusedTask();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 5775b60ab308..3343aec8891b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.recents.tv.views;
+import android.animation.Animator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Point;
@@ -22,12 +23,14 @@ import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Display;
+import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.recents.tv.animations.DismissAnimationsHolder;
import com.android.systemui.recents.tv.animations.ViewFocusAnimator;
import com.android.systemui.recents.model.Task;
@@ -37,8 +40,10 @@ public class TaskCardView extends LinearLayout {
private TextView mTitleTextView;
private ImageView mBadgeView;
private Task mTask;
+ private boolean mDismissState;
private ViewFocusAnimator mViewFocusAnimator;
+ private DismissAnimationsHolder mDismissAnimationsHolder;
public TaskCardView(Context context) {
this(context, null);
@@ -51,6 +56,7 @@ public class TaskCardView extends LinearLayout {
public TaskCardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mViewFocusAnimator = new ViewFocusAnimator(this);
+ mDismissState = false;
}
@Override
@@ -58,6 +64,7 @@ public class TaskCardView extends LinearLayout {
mThumbnailView = (ImageView) findViewById(R.id.card_view_thumbnail);
mTitleTextView = (TextView) findViewById(R.id.card_title_text);
mBadgeView = (ImageView) findViewById(R.id.card_extra_badge);
+ mDismissAnimationsHolder = new DismissAnimationsHolder(this);
}
public void init(Task task) {
@@ -98,13 +105,23 @@ public class TaskCardView extends LinearLayout {
int width = res.getDimensionPixelOffset(R.dimen.recents_tv_card_width);
int widthDelta = (int) (width * scale - width);
- int height = (int) (res.getDimensionPixelOffset(
- R.dimen.recents_tv_screenshot_height) * scale);
- int padding = res.getDimensionPixelOffset(R.dimen.recents_tv_grid_row_padding);
+ int height = res.getDimensionPixelOffset(R.dimen.recents_tv_screenshot_height);
+ int heightDelta = (int) (height * scale - height);
+ int topMargin = res.getDimensionPixelOffset(R.dimen.recents_tv_gird_row_top_margin);
- int headerHeight = (int) ((res.getDimensionPixelOffset(
- R.dimen.recents_tv_card_extra_badge_size) +
- res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom)) * scale);
+ int headerHeight = res.getDimensionPixelOffset(R.dimen.recents_tv_card_extra_badge_size) +
+ res.getDimensionPixelOffset(R.dimen.recents_tv_icon_padding_bottom);
+ int headerHeightDelta = (int) (headerHeight * scale - headerHeight);
+
+ int dismissAreaHeight =
+ res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_top_margin) +
+ res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_bottom_margin) +
+ res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_icon_size) +
+ res.getDimensionPixelOffset(R.dimen.recents_tv_dismiss_text_size);
+
+ int dismissAreaHeightDelta = (int) (dismissAreaHeight * scale - dismissAreaHeight);
+
+ int totalHeightDelta = heightDelta + headerHeightDelta + dismissAreaHeightDelta;
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
@@ -113,9 +130,72 @@ public class TaskCardView extends LinearLayout {
int screenWidth = size.x;
int screenHeight = size.y;
- return new Rect(screenWidth - width - padding - widthDelta / 2,
- screenHeight / 2 - height / 2 + headerHeight / 2,
- screenWidth - padding + widthDelta / 2,
- screenHeight / 2 + height / 2 + headerHeight / 2);
+ return new Rect(screenWidth / 2 - width / 2 - widthDelta / 2,
+ topMargin - totalHeightDelta / 2 + (int) (headerHeight * scale),
+ screenWidth / 2 + width / 2 + widthDelta / 2,
+ topMargin - totalHeightDelta / 2 + (int) (headerHeight * scale) +
+ (int) (height * scale));
+ }
+
+ @Override
+ public boolean onKeyDown(int keyCode, KeyEvent event) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_DPAD_DOWN : {
+ if (!isInDismissState()) {
+ setDismissState(true);
+ return true;
+ }
+ break;
+ }
+ case KeyEvent.KEYCODE_DPAD_UP : {
+ if (isInDismissState()) {
+ setDismissState(false);
+ return true;
+ }
+ break;
+ }
+
+ //Eat right and left key presses when we are in dismiss state
+ case KeyEvent.KEYCODE_DPAD_LEFT : {
+ if (isInDismissState()) {
+ return true;
+ }
+ break;
+ }
+ case KeyEvent.KEYCODE_DPAD_RIGHT : {
+ if (isInDismissState()) {
+ return true;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ return super.onKeyDown(keyCode, event);
+ }
+
+ private void setDismissState(boolean dismissState) {
+ if (mDismissState != dismissState) {
+ mDismissState = dismissState;
+ if (dismissState) {
+ mDismissAnimationsHolder.startEnterAnimation();
+ } else {
+ mDismissAnimationsHolder.startExitAnimation();
+ }
+ }
+ }
+
+ public boolean isInDismissState() {
+ return mDismissState;
+ }
+
+ public void startDismissTaskAnimation(Animator.AnimatorListener listener) {
+ mDismissAnimationsHolder.startDismissAnimation(listener);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ setDismissState(false);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index cf8c9bb38b7c..22ade9f43fe5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -41,7 +41,6 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
private ArrayList<TaskCardView> mTaskViews = new ArrayList<>();
private Task mFocusedTask;
-
public TaskStackHorizontalGridView(Context context) {
this(context, null);
}
@@ -53,7 +52,7 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
@Override
protected void onAttachedToWindow() {
EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
- setItemMargin((int) getResources().getDimension(R.dimen.recents_tv_gird_card_spacing));
+ setWindowAlignment(WINDOW_ALIGN_NO_EDGE);
setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
super.onAttachedToWindow();
}
@@ -109,6 +108,13 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
}
/**
+ * @return - The focused task card view.
+ */
+ public TaskCardView getFocusedTaskCardView() {
+ return ((TaskCardView)findFocus());
+ }
+
+ /**
* @param task
* @return Child view for given task
*/
@@ -150,9 +156,4 @@ public class TaskStackHorizontalGridView extends HorizontalGridView implements T
}
}
}
-
- @Override
- public void onHistoryTaskRemoved(TaskStack stack, Task removedTask, AnimationProps animation) {
- //No history task on tv
- }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
index fba424ee2ee3..378871934f70 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalViewAdapter.java
@@ -15,6 +15,7 @@
*/
package com.android.systemui.recents.tv.views;
+import android.animation.Animator;
import android.app.Activity;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
@@ -25,6 +26,7 @@ import android.view.ViewGroup;
import com.android.systemui.R;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.LaunchTvTaskEvent;
+import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.model.Task;
import java.util.ArrayList;
@@ -39,7 +41,7 @@ public class TaskStackHorizontalViewAdapter extends
private static final String TAG = "TaskStackViewAdapter";
private List<Task> mTaskList;
- static class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
+ public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
private TaskCardView mTaskCardView;
private Task mTask;
public ViewHolder(View v) {
@@ -58,9 +60,14 @@ public class TaskStackHorizontalViewAdapter extends
@Override
public void onClick(View v) {
try {
- EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
- null, INVALID_STACK_ID));
- ((Activity)(v.getContext())).finish();
+ if (mTaskCardView.isInDismissState()) {
+ mTaskCardView.startDismissTaskAnimation(
+ getRemoveAtListener(getAdapterPosition(), mTaskCardView));
+ } else {
+ EventBus.getDefault().send(new LaunchTvTaskEvent(mTaskCardView, mTask,
+ null, INVALID_STACK_ID));
+ ((Activity) (v.getContext())).finish();
+ }
} catch (Exception e) {
Log.e(TAG, v.getContext()
.getString(R.string.recents_launch_error_message, mTask.title), e);
@@ -97,4 +104,31 @@ public class TaskStackHorizontalViewAdapter extends
public int getItemCount() {
return mTaskList.size();
}
+
+ private Animator.AnimatorListener getRemoveAtListener(final int position,
+ final TaskCardView taskCardView) {
+ return new Animator.AnimatorListener() {
+
+ @Override
+ public void onAnimationStart(Animator animation) { }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ removeAt(position);
+ EventBus.getDefault().send(new DeleteTaskDataEvent(taskCardView.getTask()));
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) { }
+
+ @Override
+ public void onAnimationRepeat(Animator animation) { }
+ };
+
+ }
+
+ private void removeAt(int position) {
+ mTaskList.remove(position);
+ notifyItemRemoved(position);
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
index 72b914c6874e..035c058c7e8d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FreeformWorkspaceLayoutAlgorithm.java
@@ -46,7 +46,7 @@ public class FreeformWorkspaceLayoutAlgorithm {
public void reloadOnConfigurationChange(Context context) {
// This is applied to the edges of each task
mTaskPadding = context.getResources().getDimensionPixelSize(
- R.dimen.recents_freeform_workspace_task_padding) / 2;
+ R.dimen.recents_freeform_layout_task_padding) / 2;
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index a91bbd4b6d45..29da476db955 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -16,6 +16,11 @@
package com.android.systemui.recents.views;
+import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
+import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
import android.annotation.Nullable;
import android.app.ActivityManager.StackId;
import android.app.ActivityOptions;
@@ -49,11 +54,6 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
import java.util.List;
-import static android.app.ActivityManager.StackId.DOCKED_STACK_ID;
-import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
/**
* A helper class to create transitions to/from Recents
*/
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index db97e8f95b55..70c4c8176792 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -48,19 +48,14 @@ import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
-import com.android.systemui.recents.RecentsAppWidgetHostView;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.events.activity.ClearHistoryEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
-import com.android.systemui.recents.events.activity.HideHistoryEvent;
+import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
-import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
-import com.android.systemui.recents.events.activity.ShowHistoryEvent;
-import com.android.systemui.recents.events.activity.ToggleHistoryEvent;
+import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
@@ -68,7 +63,6 @@ import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
-import com.android.systemui.recents.history.RecentsHistoryView;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
@@ -94,11 +88,8 @@ public class RecentsView extends FrameLayout {
private TaskStack mStack;
private TaskStackView mTaskStackView;
- private RecentsAppWidgetHostView mSearchBar;
- private TextView mHistoryButton;
- private TextView mHistoryClearAllButton;
+ private TextView mStackActionButton;
private TextView mEmptyView;
- private RecentsHistoryView mHistoryView;
private boolean mAwaitingFirstLayout = true;
private boolean mLastTaskLaunchedWasFreeform;
@@ -141,18 +132,18 @@ public class RecentsView extends FrameLayout {
final float cornerRadius = context.getResources().getDimensionPixelSize(
R.dimen.recents_task_view_rounded_corners_radius);
LayoutInflater inflater = LayoutInflater.from(context);
- if (RecentsDebugFlags.Static.EnableHistory) {
- mHistoryButton = (TextView) inflater.inflate(R.layout.recents_history_button, this,
+ if (RecentsDebugFlags.Static.EnableStackActionButton) {
+ mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button, this,
false);
- mHistoryButton.setOnClickListener(new View.OnClickListener() {
+ mStackActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- EventBus.getDefault().send(new ToggleHistoryEvent());
+ // TODO: To be implemented
}
});
- addView(mHistoryButton);
- mHistoryButton.setClipToOutline(true);
- mHistoryButton.setOutlineProvider(new ViewOutlineProvider() {
+ addView(mStackActionButton);
+ mStackActionButton.setClipToOutline(true);
+ mStackActionButton.setOutlineProvider(new ViewOutlineProvider() {
@Override
public void getOutline(View view, Outline outline) {
outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), cornerRadius);
@@ -166,14 +157,17 @@ public class RecentsView extends FrameLayout {
}
/** Set/get the bsp root node */
- public void onResume(boolean isResumingFromVisible, TaskStack stack) {
+ public void onResume(boolean isResumingFromVisible, boolean multiWindowChange,
+ TaskStack stack) {
RecentsConfiguration config = Recents.getConfiguration();
RecentsActivityLaunchState launchState = config.getLaunchState();
- if (mTaskStackView == null || !launchState.launchedReuseTaskStackViews) {
+ if (!multiWindowChange &&
+ (mTaskStackView == null || !launchState.launchedReuseTaskStackViews)) {
isResumingFromVisible = false;
removeView(mTaskStackView);
mTaskStackView = new TaskStackView(getContext());
+ mTaskStackView.setSystemInsets(mSystemInsets);
mStack = mTaskStackView.getStack();
addView(mTaskStackView);
}
@@ -185,7 +179,7 @@ public class RecentsView extends FrameLayout {
// Update the stack
mTaskStackView.onResume(isResumingFromVisible);
mTaskStackView.setTasks(stack, isResumingFromVisible /* notifyStackChanges */,
- true /* relayoutTaskStack */);
+ true /* relayoutTaskStack */, multiWindowChange);
if (isResumingFromVisible) {
// If we are already visible, then restore the background scrim
@@ -217,43 +211,6 @@ public class RecentsView extends FrameLayout {
return mLastTaskLaunchedWasFreeform;
}
- /**
- * Returns whether the history is visible or not.
- */
- public boolean isHistoryVisible() {
- return mHistoryView != null && mHistoryView.isVisible();
- }
-
- /**
- * Returns the currently set task stack.
- */
- public TaskStack getTaskStack() {
- return mStack;
- }
-
- /** Gets the next task in the stack - or if the last - the top task */
- public Task getNextTaskOrTopTask(Task taskToSearch) {
- Task returnTask = null;
- boolean found = false;
- if (mTaskStackView != null) {
- TaskStack stack = mTaskStackView.getStack();
- ArrayList<Task> taskList = stack.getStackTasks();
- // Iterate the stack views and try and find the focused task
- for (int j = taskList.size() - 1; j >= 0; --j) {
- Task task = taskList.get(j);
- // Return the next task in the line.
- if (found)
- return task;
- // Remember the first possible task as the top task.
- if (returnTask == null)
- returnTask = task;
- if (task == taskToSearch)
- found = true;
- }
- }
- return returnTask;
- }
-
/** Launches the focused task from the first stack if possible */
public boolean launchFocusedTask(int logEvent) {
if (mTaskStackView != null) {
@@ -306,37 +263,16 @@ public class RecentsView extends FrameLayout {
return false;
}
- /** Adds the search bar */
- public void setSearchBar(RecentsAppWidgetHostView searchBar) {
- // Remove the previous search bar if one exists
- if (mSearchBar != null && indexOfChild(mSearchBar) > -1) {
- removeView(mSearchBar);
- }
- // Add the new search bar
- if (searchBar != null) {
- mSearchBar = searchBar;
- addView(mSearchBar);
- }
- }
-
- /** Returns whether there is currently a search bar */
- public boolean hasValidSearchBar() {
- return mSearchBar != null && !mSearchBar.isReinflateRequired();
- }
-
/**
* Hides the task stack and shows the empty view.
*/
public void showEmptyView(int msgResId) {
- if (RecentsDebugFlags.Static.EnableSearchBar && (mSearchBar != null)) {
- mSearchBar.setVisibility(View.INVISIBLE);
- }
mTaskStackView.setVisibility(View.INVISIBLE);
mEmptyView.setText(msgResId);
mEmptyView.setVisibility(View.VISIBLE);
mEmptyView.bringToFront();
- if (RecentsDebugFlags.Static.EnableHistory) {
- mHistoryButton.bringToFront();
+ if (RecentsDebugFlags.Static.EnableStackActionButton) {
+ mStackActionButton.bringToFront();
}
}
@@ -346,15 +282,9 @@ public class RecentsView extends FrameLayout {
public void hideEmptyView() {
mEmptyView.setVisibility(View.INVISIBLE);
mTaskStackView.setVisibility(View.VISIBLE);
- if (RecentsDebugFlags.Static.EnableSearchBar && (mSearchBar != null)) {
- mSearchBar.setVisibility(View.VISIBLE);
- }
mTaskStackView.bringToFront();
- if (mSearchBar != null) {
- mSearchBar.bringToFront();
- }
- if (RecentsDebugFlags.Static.EnableHistory) {
- mHistoryButton.bringToFront();
+ if (RecentsDebugFlags.Static.EnableStackActionButton) {
+ mStackActionButton.bringToFront();
}
}
@@ -377,25 +307,10 @@ public class RecentsView extends FrameLayout {
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- RecentsConfiguration config = Recents.getConfiguration();
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
- // Get the search bar bounds and measure the search bar layout
- Rect searchBarSpaceBounds = new Rect();
- if (mSearchBar != null) {
- config.getSearchBarBounds(new Rect(0, 0, width, height), mSystemInsets.top,
- searchBarSpaceBounds);
- mSearchBar.measure(
- MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), MeasureSpec.EXACTLY));
- }
-
- Rect taskStackBounds = new Rect();
- config.getTaskStackBounds(new Rect(0, 0, width, height), mSystemInsets.top,
- mSystemInsets.right, searchBarSpaceBounds, taskStackBounds);
- if (mTaskStackView != null && mTaskStackView.getVisibility() != GONE) {
- mTaskStackView.setTaskStackBounds(taskStackBounds, mSystemInsets);
+ if (mTaskStackView.getVisibility() != GONE) {
mTaskStackView.measure(widthMeasureSpec, heightMeasureSpec);
}
@@ -405,23 +320,12 @@ public class RecentsView extends FrameLayout {
MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST));
}
- if (RecentsDebugFlags.Static.EnableHistory) {
- // Measure the history view
- if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
- measureChild(mHistoryView, MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
- MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
- }
-
- // Measure the history button within the constraints of the space above the stack
- Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
- measureChild(mHistoryButton,
- MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(historyButtonRect.height(), MeasureSpec.AT_MOST));
- if (mHistoryClearAllButton != null && mHistoryClearAllButton.getVisibility() != GONE) {
- measureChild(mHistoryClearAllButton,
- MeasureSpec.makeMeasureSpec(historyButtonRect.width(), MeasureSpec.AT_MOST),
- MeasureSpec.makeMeasureSpec(historyButtonRect.height(), MeasureSpec.AT_MOST));
- }
+ if (RecentsDebugFlags.Static.EnableStackActionButton) {
+ // Measure the stack action button within the constraints of the space above the stack
+ Rect actionButtonRect = mTaskStackView.mLayoutAlgorithm.mStackActionButtonRect;
+ measureChild(mStackActionButton,
+ MeasureSpec.makeMeasureSpec(actionButtonRect.width(), MeasureSpec.AT_MOST),
+ MeasureSpec.makeMeasureSpec(actionButtonRect.height(), MeasureSpec.AT_MOST));
}
setMeasuredDimension(width, height);
@@ -432,19 +336,7 @@ public class RecentsView extends FrameLayout {
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- RecentsConfiguration config = Recents.getConfiguration();
-
- // Get the search bar bounds so that we lay it out
- Rect measuredRect = new Rect(0, 0, getMeasuredWidth(), getMeasuredHeight());
- Rect searchBarSpaceBounds = new Rect();
- if (mSearchBar != null) {
- config.getSearchBarBounds(measuredRect,
- mSystemInsets.top, searchBarSpaceBounds);
- mSearchBar.layout(searchBarSpaceBounds.left, searchBarSpaceBounds.top,
- searchBarSpaceBounds.right, searchBarSpaceBounds.bottom);
- }
-
- if (mTaskStackView != null && mTaskStackView.getVisibility() != GONE) {
+ if (mTaskStackView.getVisibility() != GONE) {
mTaskStackView.layout(left, top, left + getMeasuredWidth(), top + getMeasuredHeight());
}
@@ -459,39 +351,19 @@ public class RecentsView extends FrameLayout {
mEmptyView.layout(childLeft, childTop, childLeft + childWidth, childTop + childHeight);
}
- if (RecentsDebugFlags.Static.EnableHistory) {
- // Layout the history view
- if (mHistoryView != null && mHistoryView.getVisibility() != GONE) {
- mHistoryView.layout(left, top, right, bottom);
- }
-
- // Layout the history button such that its drawable is start-aligned with the stack,
- // vertically centered in the available space above the stack
- Rect historyButtonRect = mTaskStackView.mLayoutAlgorithm.mHistoryButtonRect;
- int historyLeft = isLayoutRtl()
- ? historyButtonRect.right + mHistoryButton.getPaddingStart()
- - mHistoryButton.getMeasuredWidth()
- : historyButtonRect.left - mHistoryButton.getPaddingStart();
- int historyTop = historyButtonRect.top +
- (historyButtonRect.height() - mHistoryButton.getMeasuredHeight()) / 2;
- mHistoryButton.layout(historyLeft, historyTop,
- historyLeft + mHistoryButton.getMeasuredWidth(),
- historyTop + mHistoryButton.getMeasuredHeight());
-
- // Layout the history clear all button such that it is end-aligned with the stack,
- // vertically centered in the available space above the stack
- if (mHistoryClearAllButton != null && mHistoryClearAllButton.getVisibility() != GONE) {
- int clearAllLeft = isLayoutRtl()
- ? historyButtonRect.left - mHistoryClearAllButton.getPaddingStart()
- : historyButtonRect.right + mHistoryClearAllButton.getPaddingStart()
- - mHistoryClearAllButton.getMeasuredWidth();
- int clearAllTop = historyButtonRect.top +
- (historyButtonRect.height() - mHistoryClearAllButton.getMeasuredHeight()) /
- 2;
- mHistoryClearAllButton.layout(clearAllLeft, clearAllTop,
- clearAllLeft + mHistoryClearAllButton.getMeasuredWidth(),
- clearAllTop + mHistoryClearAllButton.getMeasuredHeight());
- }
+ if (RecentsDebugFlags.Static.EnableStackActionButton) {
+ // Layout the stack action button such that its drawable is start-aligned with the
+ // stack, vertically centered in the available space above the stack
+ Rect actionButtonRect = mTaskStackView.mLayoutAlgorithm.mStackActionButtonRect;
+ int buttonLeft = isLayoutRtl()
+ ? actionButtonRect.right + mStackActionButton.getPaddingStart()
+ - mStackActionButton.getMeasuredWidth()
+ : actionButtonRect.left - mStackActionButton.getPaddingStart();
+ int buttonTop = actionButtonRect.top +
+ (actionButtonRect.height() - mStackActionButton.getMeasuredHeight()) / 2;
+ mStackActionButton.layout(buttonLeft, buttonTop,
+ buttonLeft + mStackActionButton.getMeasuredWidth(),
+ buttonTop + mStackActionButton.getMeasuredHeight());
}
if (mAwaitingFirstLayout) {
@@ -511,6 +383,7 @@ public class RecentsView extends FrameLayout {
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mSystemInsets.set(insets.getSystemWindowInsets());
+ mTaskStackView.setSystemInsets(mSystemInsets);
requestLayout();
return insets;
}
@@ -560,9 +433,9 @@ public class RecentsView extends FrameLayout {
public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
- if (RecentsDebugFlags.Static.EnableHistory) {
- // Hide the history button
- hideHistoryButton(taskViewExitToHomeDuration, false /* translate */);
+ if (RecentsDebugFlags.Static.EnableStackActionButton) {
+ // Hide the stack action button
+ hideStackActionButton(taskViewExitToHomeDuration, false /* translate */);
}
animateBackgroundScrim(0f, taskViewExitToHomeDuration);
}
@@ -687,144 +560,47 @@ public class RecentsView extends FrameLayout {
animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
}
- public final void onBusEvent(ToggleHistoryEvent event) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
- return;
- }
-
- if (mHistoryView != null && mHistoryView.isVisible()) {
- EventBus.getDefault().send(new HideHistoryEvent(true /* animate */));
- } else {
- EventBus.getDefault().send(new ShowHistoryEvent());
- }
- }
-
- public final void onBusEvent(ShowHistoryEvent event) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
- return;
- }
-
- if (mHistoryView == null) {
- LayoutInflater inflater = LayoutInflater.from(getContext());
- mHistoryView = (RecentsHistoryView) inflater.inflate(R.layout.recents_history, this,
- false);
- addView(mHistoryView);
-
- final float cornerRadius = getResources().getDimensionPixelSize(
- R.dimen.recents_task_view_rounded_corners_radius);
- mHistoryClearAllButton = (TextView) inflater.inflate(
- R.layout.recents_history_clear_all_button, this, false);
- mHistoryClearAllButton.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- EventBus.getDefault().send(new ClearHistoryEvent());
- }
- });
- mHistoryClearAllButton.setClipToOutline(true);
- mHistoryClearAllButton.setOutlineProvider(new ViewOutlineProvider() {
- @Override
- public void getOutline(View view, Outline outline) {
- outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), cornerRadius);
- }
- });
- addView(mHistoryClearAllButton);
-
- // Since this history view is inflated by a view stub after the insets have already
- // been applied, we have to set them ourselves initial from the insets that were last
- // provided.
- mHistoryView.setSystemInsets(mSystemInsets);
- mHistoryView.setHeaderHeight(mHistoryButton.getMeasuredHeight());
- mHistoryButton.bringToFront();
- mHistoryClearAllButton.bringToFront();
- }
-
- // Animate the empty view in parallel with the history view (the task view animations are
- // handled in TaskStackView)
- Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
- if (mEmptyView.getVisibility() == View.VISIBLE) {
- int historyTransitionDuration = getResources().getInteger(
- R.integer.recents_history_transition_duration);
- mEmptyView.animate()
- .alpha(0f)
- .translationY(stackRect.height() / 2)
- .setDuration(historyTransitionDuration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .withEndAction(new Runnable() {
- @Override
- public void run() {
- mEmptyView.setVisibility(View.INVISIBLE);
- }
- })
- .start();
- }
-
- mHistoryView.show(mStack, stackRect.height(), mHistoryClearAllButton);
- }
-
- public final void onBusEvent(HideHistoryEvent event) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
- return;
- }
-
- // Animate the empty view in parallel with the history view (the task view animations are
- // handled in TaskStackView)
- Rect stackRect = mTaskStackView.mLayoutAlgorithm.mStackRect;
- if (mStack.getTaskCount() == 0) {
- int historyTransitionDuration = getResources().getInteger(
- R.integer.recents_history_transition_duration);
- mEmptyView.setVisibility(View.VISIBLE);
- mEmptyView.animate()
- .alpha(1f)
- .translationY(0)
- .setDuration(historyTransitionDuration)
- .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
- .start();
- }
-
- mHistoryView.hide(event.animate, stackRect.height(), mHistoryClearAllButton);
- }
-
- public final void onBusEvent(ShowHistoryButtonEvent event) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
+ public final void onBusEvent(ShowStackActionButtonEvent event) {
+ if (!RecentsDebugFlags.Static.EnableStackActionButton) {
return;
}
- showHistoryButton(150, event.translate);
+ showStackActionButton(150, event.translate);
}
- public final void onBusEvent(HideHistoryButtonEvent event) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
+ public final void onBusEvent(HideStackActionButtonEvent event) {
+ if (!RecentsDebugFlags.Static.EnableStackActionButton) {
return;
}
- hideHistoryButton(100, true /* translate */);
+ hideStackActionButton(100, true /* translate */);
}
/**
- * Shows the history button.
+ * Shows the stack action button.
*/
- private void showHistoryButton(final int duration, final boolean translate) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
+ private void showStackActionButton(final int duration, final boolean translate) {
+ if (!RecentsDebugFlags.Static.EnableStackActionButton) {
return;
}
final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- if (mHistoryButton.getVisibility() == View.INVISIBLE) {
- mHistoryButton.setVisibility(View.VISIBLE);
- mHistoryButton.setAlpha(0f);
+ if (mStackActionButton.getVisibility() == View.INVISIBLE) {
+ mStackActionButton.setVisibility(View.VISIBLE);
+ mStackActionButton.setAlpha(0f);
if (translate) {
- mHistoryButton.setTranslationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+ mStackActionButton.setTranslationY(-mStackActionButton.getMeasuredHeight() * 0.25f);
} else {
- mHistoryButton.setTranslationY(0f);
+ mStackActionButton.setTranslationY(0f);
}
postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
@Override
public void run() {
if (translate) {
- mHistoryButton.animate()
+ mStackActionButton.animate()
.translationY(0f);
}
- mHistoryButton.animate()
+ mStackActionButton.animate()
.alpha(1f)
.setDuration(duration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
@@ -837,40 +613,40 @@ public class RecentsView extends FrameLayout {
}
/**
- * Hides the history button.
+ * Hides the stack action button.
*/
- private void hideHistoryButton(int duration, boolean translate) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
+ private void hideStackActionButton(int duration, boolean translate) {
+ if (!RecentsDebugFlags.Static.EnableStackActionButton) {
return;
}
final ReferenceCountedTrigger postAnimationTrigger = new ReferenceCountedTrigger();
- hideHistoryButton(duration, translate, postAnimationTrigger);
+ hideStackActionButton(duration, translate, postAnimationTrigger);
postAnimationTrigger.flushLastDecrementRunnables();
}
/**
- * Hides the history button.
+ * Hides the stack action button.
*/
- private void hideHistoryButton(int duration, boolean translate,
- final ReferenceCountedTrigger postAnimationTrigger) {
- if (!RecentsDebugFlags.Static.EnableHistory) {
+ private void hideStackActionButton(int duration, boolean translate,
+ final ReferenceCountedTrigger postAnimationTrigger) {
+ if (!RecentsDebugFlags.Static.EnableStackActionButton) {
return;
}
- if (mHistoryButton.getVisibility() == View.VISIBLE) {
+ if (mStackActionButton.getVisibility() == View.VISIBLE) {
if (translate) {
- mHistoryButton.animate()
- .translationY(-mHistoryButton.getMeasuredHeight() * 0.25f);
+ mStackActionButton.animate()
+ .translationY(-mStackActionButton.getMeasuredHeight() * 0.25f);
}
- mHistoryButton.animate()
+ mStackActionButton.animate()
.alpha(0f)
.setDuration(duration)
.setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
.withEndAction(new Runnable() {
@Override
public void run() {
- mHistoryButton.setVisibility(View.INVISIBLE);
+ mStackActionButton.setVisibility(View.INVISIBLE);
postAnimationTrigger.decrement();
}
})
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 19b219a49b2c..6bdaaf96829e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -16,11 +16,9 @@
package com.android.systemui.recents.views;
-import android.animation.AnimatorListenerAdapter;
import android.app.Activity;
import android.content.Context;
import android.view.View;
-import android.view.ViewPropertyAnimator;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index b36d5d195138..4155dd2a0532 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -65,6 +65,12 @@ public class TaskStackAnimationHelper {
*/
void onStartLaunchTargetLaunchAnimation(int duration, boolean screenPinningRequested,
ReferenceCountedTrigger postAnimationTrigger);
+
+ /**
+ * Callback to start the animation for the front {@link TaskView} if there is no launch
+ * target.
+ */
+ void onStartFrontTaskEnterAnimation(boolean screenPinningEnabled);
}
private static final int FRAME_OFFSET_MS = 16;
@@ -126,9 +132,9 @@ public class TaskStackAnimationHelper {
int offscreenYOffset = stackLayout.mStackRect.height();
int taskViewAffiliateGroupEnterOffset = res.getDimensionPixelSize(
- R.dimen.recents_task_view_affiliate_group_enter_offset);
+ R.dimen.recents_task_stack_animation_affiliate_enter_offset);
int launchedWhileDockingOffset = res.getDimensionPixelSize(
- R.dimen.recents_task_view_launched_while_docking_offset);
+ R.dimen.recents_task_stack_animation_launched_while_docking_offset);
// Prepare each of the task views for their enter animation from front to back
List<TaskView> taskViews = mStackView.getTaskViews();
@@ -164,6 +170,7 @@ public class TaskStackAnimationHelper {
// Move the task view off screen (below) so we can animate it in
RectF bounds = new RectF(mTmpTransform.rect);
bounds.offset(0, offscreenYOffset);
+ tv.setAlpha(0f);
tv.setLeftTopRightBottom((int) bounds.left, (int) bounds.top, (int) bounds.right,
(int) bounds.bottom);
} else if (launchState.launchedWhileDocking) {
@@ -232,7 +239,7 @@ public class TaskStackAnimationHelper {
@Override
public void onAnimationEnd(Animator animation) {
postAnimationTrigger.decrement();
- tv.setClipViewInStack(false);
+ tv.setClipViewInStack(true);
}
});
postAnimationTrigger.increment();
@@ -254,6 +261,9 @@ public class TaskStackAnimationHelper {
.setListener(postAnimationTrigger.decrementOnAnimationEnd());
postAnimationTrigger.increment();
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
+ if (i == taskViewCount - 1) {
+ tv.onStartFrontTaskEnterAnimation(mStackView.mScreenPinningEnabled);
+ }
} else if (launchState.launchedWhileDocking) {
// Animate the tasks up
AnimationProps taskAnimation = new AnimationProps()
@@ -312,6 +322,7 @@ public class TaskStackAnimationHelper {
stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
null);
+ mTmpTransform.alpha = 0f;
mTmpTransform.rect.offset(0, offscreenYOffset);
mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
}
@@ -330,7 +341,7 @@ public class TaskStackAnimationHelper {
int taskViewExitToAppDuration = res.getInteger(
R.integer.recents_task_exit_to_app_duration);
int taskViewAffiliateGroupEnterOffset = res.getDimensionPixelSize(
- R.dimen.recents_task_view_affiliate_group_enter_offset);
+ R.dimen.recents_task_stack_animation_affiliate_enter_offset);
Task launchingTask = launchingTaskView.getTask();
List<TaskView> taskViews = mStackView.getTaskViews();
@@ -399,62 +410,6 @@ public class TaskStackAnimationHelper {
}
/**
- * Starts the animation to hide the {@link TaskView}s when the history is shown.
- */
- public void startShowHistoryAnimation(ReferenceCountedTrigger postAnimationTrigger) {
- Resources res = mStackView.getResources();
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mStackView.getScroller();
-
- int offscreenY = stackLayout.mStackRect.bottom;
- int historyTransitionDuration = res.getInteger(
- R.integer.recents_history_transition_duration);
- int startDelayIncr = 16;
-
- List<TaskView> taskViews = mStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
- Task task = tv.getTask();
- AnimationProps taskAnimation = new AnimationProps(startDelayIncr * i,
- historyTransitionDuration, Interpolators.FAST_OUT_SLOW_IN,
- postAnimationTrigger.decrementOnAnimationEnd());
- postAnimationTrigger.increment();
-
- stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
- null);
- mTmpTransform.alpha = 0f;
- mTmpTransform.rect.offsetTo(mTmpTransform.rect.left, offscreenY);
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
- }
-
- /**
- * Starts the animation to show the {@link TaskView}s when the history is hidden.
- */
- public void startHideHistoryAnimation() {
- Resources res = mStackView.getResources();
- TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
- TaskStackViewScroller stackScroller = mStackView.getScroller();
-
- int historyTransitionDuration = res.getInteger(
- R.integer.recents_history_transition_duration);
- int startDelayIncr = 16;
-
- List<TaskView> taskViews = mStackView.getTaskViews();
- int taskViewCount = taskViews.size();
- for (int i = taskViewCount - 1; i >= 0; i--) {
- TaskView tv = taskViews.get(i);
- AnimationProps taskAnimation = new AnimationProps(startDelayIncr * i,
- historyTransitionDuration, Interpolators.FAST_OUT_SLOW_IN);
- stackLayout.getStackTransform(tv.getTask(), stackScroller.getStackScroll(),
- mTmpTransform, null);
- mTmpTransform.alpha = 1f;
- mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
- }
- }
-
- /**
* Starts the animation to focus the next {@link TaskView} when paging through recents.
*
* @return whether or not this will trigger a scroll in the stack
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 6df5884328b3..93c5fc9d56ab 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -16,7 +16,9 @@
package com.android.systemui.recents.views;
+import android.annotation.IntDef;
import android.content.Context;
+import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Path;
import android.graphics.Rect;
@@ -36,6 +38,8 @@ import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
@@ -97,8 +101,10 @@ class Range {
}
/**
- * The layout logic for a TaskStackView. This layout can have two states focused and unfocused,
- * and in the focused state, there is a task that is displayed more prominently in the stack.
+ * The layout logic for a TaskStackView. This layout needs to be able to calculate the stack layout
+ * without an activity-specific context only with the information passed in. This layout can have
+ * two states focused and unfocused, and in the focused state, there is a task that is displayed
+ * more prominently in the stack.
*/
public class TaskStackLayoutAlgorithm {
@@ -107,13 +113,28 @@ public class TaskStackLayoutAlgorithm {
public static final float OUTLINE_ALPHA_MIN_VALUE = 0f;
public static final float OUTLINE_ALPHA_MAX_VALUE = 2f;
- // The maximum dim on the tasks
+ // The medium/maximum dim on the tasks
+ private static final float MED_DIM = 0.15f;
private static final float MAX_DIM = 0.25f;
// The various focus states
public static final int STATE_FOCUSED = 1;
public static final int STATE_UNFOCUSED = 0;
+ // The side that an offset is anchored
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({FROM_TOP, FROM_BOTTOM})
+ public @interface AnchorSide {}
+ private static final int FROM_TOP = 0;
+ private static final int FROM_BOTTOM = 1;
+
+ // The extent that we care about when calculating fractions
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({WIDTH, HEIGHT})
+ public @interface Extent {}
+ private static final int WIDTH = 0;
+ private static final int HEIGHT = 1;
+
public interface TaskStackLayoutAlgorithmCallbacks {
void onFocusStateChanged(int prevFocusState, int curFocusState);
}
@@ -165,22 +186,24 @@ public class TaskStackLayoutAlgorithm {
* @param taskStackBounds the full rect that the freeform rect can take up
*/
public void computeRects(Rect freeformRectOut, Rect stackRectOut,
- Rect taskStackBounds, int widthPadding, int heightPadding, int stackBottomOffset) {
- int availableHeight = taskStackBounds.height() - stackBottomOffset;
+ Rect taskStackBounds, int topMargin, int freeformGap, int stackBottomOffset) {
+ // The freeform height is the visible height (not including system insets) - padding
+ // above freeform and below stack - gap between the freeform and stack
+ int availableHeight = taskStackBounds.height() - topMargin - stackBottomOffset;
int ffPaddedHeight = (int) (availableHeight * freeformHeightPct);
- int ffHeight = Math.max(0, ffPaddedHeight - (2 * heightPadding));
- freeformRectOut.set(taskStackBounds.left + widthPadding,
- taskStackBounds.top + heightPadding,
- taskStackBounds.right - widthPadding,
- taskStackBounds.top + heightPadding + ffHeight);
- stackRectOut.set(taskStackBounds.left + widthPadding,
+ int ffHeight = Math.max(0, ffPaddedHeight - freeformGap);
+ freeformRectOut.set(taskStackBounds.left,
+ taskStackBounds.top + topMargin,
+ taskStackBounds.right,
+ taskStackBounds.top + topMargin + ffHeight);
+ stackRectOut.set(taskStackBounds.left,
taskStackBounds.top,
- taskStackBounds.right - widthPadding,
+ taskStackBounds.right,
taskStackBounds.bottom);
if (ffPaddedHeight > 0) {
stackRectOut.top += ffPaddedHeight;
} else {
- stackRectOut.top += heightPadding;
+ stackRectOut.top += topMargin;
}
}
}
@@ -204,44 +227,53 @@ public class TaskStackLayoutAlgorithm {
// The task bounds (untransformed) for layout. This rect is anchored at mTaskRoot.
@ViewDebug.ExportedProperty(category="recents")
public Rect mTaskRect = new Rect();
- // The freeform workspace bounds, inset from the top by the search bar, and is a fixed height
+ // The freeform workspace bounds, inset by the top system insets and is a fixed height
@ViewDebug.ExportedProperty(category="recents")
public Rect mFreeformRect = new Rect();
- // The stack bounds, inset from the top by the search bar, and runs to
- // the bottom of the screen
+ // The stack bounds, inset from the top system insets, and runs to the bottom of the screen
@ViewDebug.ExportedProperty(category="recents")
public Rect mStackRect = new Rect();
// This is the current system insets
@ViewDebug.ExportedProperty(category="recents")
public Rect mSystemInsets = new Rect();
- // This is the bounds of the history button above the stack rect
+ // This is the bounds of the stack action above the stack rect
@ViewDebug.ExportedProperty(category="recents")
- public Rect mHistoryButtonRect = new Rect();
+ public Rect mStackActionButtonRect = new Rect();
// The visible ranges when the stack is focused and unfocused
private Range mUnfocusedRange;
private Range mFocusedRange;
- // The initial offset from the top and bottom of the stack
+ // The base top margin for the stack from the system insets
@ViewDebug.ExportedProperty(category="recents")
- private int mInitialTopPeekHeight;
+ private int mBaseTopMargin;
+ // The base side margin for the stack from the system insets
@ViewDebug.ExportedProperty(category="recents")
- private int mInitialBottomPeekHeight;
-
- // The offset from the top when scrolled to the top of the stack
+ private int mBaseSideMargin;
+ // The base bottom margin for the stack from the system insets
@ViewDebug.ExportedProperty(category="recents")
- private int mFocusedTopPeekHeight;
+ private int mBaseBottomMargin;
+ private int mMinMargin;
+
+ // The gap between the freeform and stack layouts
@ViewDebug.ExportedProperty(category="recents")
- private int mFocusedBottomTaskPeekHeight;
+ private int mFreeformStackGap;
- // The offset from the top of the stack to the top of the bounds when the stack is scrolled to
- // the end
+ // The initial offset that the focused task is from the top
+ @ViewDebug.ExportedProperty(category="recents")
+ private int mInitialTopOffset;
+ private int mBaseInitialTopOffset;
+ // The initial offset that the launch-from task is from the bottom
@ViewDebug.ExportedProperty(category="recents")
- private int mStackTopOffset;
+ private int mInitialBottomOffset;
+ private int mBaseInitialBottomOffset;
- // The height of the header bar
+ // The height between the top margin and the top of the focused task
+ @ViewDebug.ExportedProperty(category="recents")
+ private int mFocusedTopPeekHeight;
+ // The height between the bottom margin and the top of task in front of the focused task
@ViewDebug.ExportedProperty(category="recents")
- private int mHeaderBarHeight;
+ private int mFocusedBottomPeekHeight;
// The offset from the bottom of the stack to the bottom of the bounds when the stack is
// scrolled to the front
@@ -307,9 +339,23 @@ public class TaskStackLayoutAlgorithm {
TaskViewTransform mFrontOfStackTransform = new TaskViewTransform();
public TaskStackLayoutAlgorithm(Context context, TaskStackLayoutAlgorithmCallbacks cb) {
+ Resources res = context.getResources();
mContext = context;
mCb = cb;
mFreeformLayoutAlgorithm = new FreeformWorkspaceLayoutAlgorithm(context);
+ mMinMargin = res.getDimensionPixelSize(R.dimen.recents_layout_min_margin);
+ mBaseTopMargin = getDimensionForDevice(res,
+ R.dimen.recents_layout_top_margin_phone,
+ R.dimen.recents_layout_top_margin_tablet,
+ R.dimen.recents_layout_top_margin_tablet_xlarge);
+ mBaseSideMargin = getDimensionForDevice(res,
+ R.dimen.recents_layout_side_margin_phone,
+ R.dimen.recents_layout_side_margin_tablet,
+ R.dimen.recents_layout_side_margin_tablet_xlarge);
+ mBaseBottomMargin = res.getDimensionPixelSize(R.dimen.recents_layout_bottom_margin);
+ mFreeformStackGap =
+ res.getDimensionPixelSize(R.dimen.recents_freeform_layout_bottom_margin);
+
reloadOnConfigurationChange(context);
}
@@ -323,17 +369,25 @@ public class TaskStackLayoutAlgorithm {
mUnfocusedRange = new Range(res.getFloat(R.integer.recents_layout_unfocused_range_min),
res.getFloat(R.integer.recents_layout_unfocused_range_max));
mFocusState = getInitialFocusState();
- mInitialTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_initial_top_peek_size);
- mInitialBottomPeekHeight =
- res.getDimensionPixelSize(R.dimen.recents_initial_bottom_peek_size);
- mFocusedTopPeekHeight =
- res.getDimensionPixelSize(R.dimen.recents_layout_focused_top_peek_size);
- mFocusedBottomTaskPeekHeight =
- res.getDimensionPixelSize(R.dimen.recents_layout_focused_bottom_task_peek_size);
- mHeaderBarHeight = res.getDimensionPixelSize(R.dimen.recents_task_bar_height);
-
- mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_min);
- mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
+ mFocusedTopPeekHeight = res.getDimensionPixelSize(R.dimen.recents_layout_top_peek_size);
+ mFocusedBottomPeekHeight =
+ res.getDimensionPixelSize(R.dimen.recents_layout_bottom_peek_size);
+ mMinTranslationZ = res.getDimensionPixelSize(R.dimen.recents_layout_z_min);
+ mMaxTranslationZ = res.getDimensionPixelSize(R.dimen.recents_layout_z_max);
+ mBaseInitialTopOffset = getDimensionForDevice(res,
+ R.dimen.recents_layout_initial_top_offset_phone_port,
+ R.dimen.recents_layout_initial_top_offset_phone_land,
+ R.dimen.recents_layout_initial_top_offset_tablet,
+ R.dimen.recents_layout_initial_top_offset_tablet,
+ R.dimen.recents_layout_initial_top_offset_tablet,
+ R.dimen.recents_layout_initial_top_offset_tablet);
+ mBaseInitialBottomOffset = getDimensionForDevice(res,
+ R.dimen.recents_layout_initial_bottom_offset_phone_port,
+ R.dimen.recents_layout_initial_bottom_offset_phone_land,
+ R.dimen.recents_layout_initial_bottom_offset_tablet,
+ R.dimen.recents_layout_initial_bottom_offset_tablet,
+ R.dimen.recents_layout_initial_bottom_offset_tablet,
+ R.dimen.recents_layout_initial_bottom_offset_tablet);
mFreeformLayoutAlgorithm.reloadOnConfigurationChange(context);
}
@@ -372,52 +426,52 @@ public class TaskStackLayoutAlgorithm {
}
/**
- * Computes the stack and task rects. The given task stack bounds is the whole bounds not
- * including the search bar.
+ * Computes the stack and task rects. The given task stack bounds already has the top/right
+ * insets and left/right padding already applied.
*/
- public void initialize(Rect taskStackBounds, StackState state) {
- RecentsConfiguration config = Recents.getConfiguration();
- int widthPadding = (int) (config.taskStackWidthPaddingPct * taskStackBounds.width());
- int heightPadding = mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_stack_top_padding);
+ public void initialize(Rect windowRect, Rect taskStackBounds, StackState state) {
+ SystemServicesProxy ssp = Recents.getSystemServices();
Rect lastStackRect = new Rect(mStackRect);
+ Rect displayRect = ssp.getDisplayRect();
- // The freeform height is the visible height (not including system insets) - padding above
- // freeform and below stack - gap between the freeform and stack
+ int topMargin = getScaleForExtent(windowRect, displayRect, mBaseTopMargin, mMinMargin, HEIGHT);
+ int bottomMargin = getScaleForExtent(windowRect, displayRect, mBaseBottomMargin, mMinMargin,
+ HEIGHT);
+ mInitialTopOffset = getScaleForExtent(windowRect, displayRect, mBaseInitialTopOffset,
+ mMinMargin, HEIGHT);
+ mInitialBottomOffset = mBaseInitialBottomOffset;
+
+ // Compute the stack bounds
mState = state;
- mStackTopOffset = mFocusedTopPeekHeight + heightPadding;
- mStackBottomOffset = mSystemInsets.bottom + heightPadding;
- state.computeRects(mFreeformRect, mStackRect, taskStackBounds, widthPadding, heightPadding,
- mStackBottomOffset);
- // The history button will take the full un-padded header space above the stack
- mHistoryButtonRect.set(mStackRect.left, mStackRect.top - heightPadding,
+ mStackBottomOffset = mSystemInsets.bottom + bottomMargin;
+ state.computeRects(mFreeformRect, mStackRect, taskStackBounds, topMargin,
+ mFreeformStackGap, mStackBottomOffset);
+
+ // The stack action button will take the full un-padded header space above the stack
+ mStackActionButtonRect.set(mStackRect.left, mStackRect.top - topMargin,
mStackRect.right, mStackRect.top + mFocusedTopPeekHeight);
- // Anchor the task rect to the top-center of the non-freeform stack rect
- float aspect = (float) (taskStackBounds.width() - mSystemInsets.left - mSystemInsets.right)
- / (taskStackBounds.height() - mSystemInsets.bottom);
- int width = mStackRect.width();
- int minHeight = mStackRect.height() - mFocusedTopPeekHeight - mStackBottomOffset;
- int height = (int) Math.min(width / aspect, minHeight);
- mTaskRect.set(mStackRect.left, mStackRect.top,
- mStackRect.left + width, mStackRect.top + height);
+ // Anchor the task rect top aligned to the non-freeform stack rect
+ float aspect = (float) (windowRect.width() - (mSystemInsets.left + mSystemInsets.right)) /
+ (windowRect.height() - (mSystemInsets.top + mSystemInsets.bottom));
+ int minHeight = mStackRect.height() - mInitialTopOffset - mStackBottomOffset;
+ int height = (int) Math.min(mStackRect.width() / aspect, minHeight);
+ mTaskRect.set(mStackRect.left, mStackRect.top, mStackRect.right, mStackRect.top + height);
// Short circuit here if the stack rects haven't changed so we don't do all the work below
- if (lastStackRect.equals(mStackRect)) {
- return;
+ if (!lastStackRect.equals(mStackRect)) {
+ // Reinitialize the focused and unfocused curves
+ mUnfocusedCurve = constructUnfocusedCurve();
+ mUnfocusedCurveInterpolator = new FreePathInterpolator(mUnfocusedCurve);
+ mFocusedCurve = constructFocusedCurve();
+ mFocusedCurveInterpolator = new FreePathInterpolator(mFocusedCurve);
+ mUnfocusedDimCurve = constructUnfocusedDimCurve();
+ mUnfocusedDimCurveInterpolator = new FreePathInterpolator(mUnfocusedDimCurve);
+ mFocusedDimCurve = constructFocusedDimCurve();
+ mFocusedDimCurveInterpolator = new FreePathInterpolator(mFocusedDimCurve);
+
+ updateFrontBackTransforms();
}
-
- // Reinitialize the focused and unfocused curves
- mUnfocusedCurve = constructUnfocusedCurve();
- mUnfocusedCurveInterpolator = new FreePathInterpolator(mUnfocusedCurve);
- mFocusedCurve = constructFocusedCurve();
- mFocusedCurveInterpolator = new FreePathInterpolator(mFocusedCurve);
- mUnfocusedDimCurve = constructUnfocusedDimCurve();
- mUnfocusedDimCurveInterpolator = new FreePathInterpolator(mUnfocusedDimCurve);
- mFocusedDimCurve = constructFocusedDimCurve();
- mFocusedDimCurveInterpolator = new FreePathInterpolator(mFocusedDimCurve);
-
- updateFrontBackTransforms();
}
/**
@@ -435,7 +489,7 @@ public class TaskStackLayoutAlgorithm {
ArrayList<Task> tasks = stack.getStackTasks();
if (tasks.isEmpty()) {
mFrontMostTaskP = 0;
- mMinScrollP = mMaxScrollP = 0;
+ mMinScrollP = mMaxScrollP = mInitialScrollP = 0;
mNumStackTasks = mNumFreeformTasks = 0;
return;
}
@@ -492,8 +546,7 @@ public class TaskStackLayoutAlgorithm {
// Set the max scroll to be the point where the front most task is visible with the
// stack bottom offset
int maxBottomOffset = mStackBottomOffset + mTaskRect.height();
- float maxBottomOffsetPct = (float) maxBottomOffset / mStackRect.height();
- float maxBottomNormX = mUnfocusedCurveInterpolator.getX(maxBottomOffsetPct);
+ float maxBottomNormX = getNormalizedXFromUnfocusedY(maxBottomOffset, FROM_BOTTOM);
mUnfocusedRange.offset(0f);
mMinScrollP = 0;
mMaxScrollP = Math.max(mMinScrollP, (mNumStackTasks - 1) -
@@ -502,34 +555,19 @@ public class TaskStackLayoutAlgorithm {
launchState.launchedFromAppDocked;
if (scrollToFront) {
mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
+ mInitialNormX = null;
} else {
- mInitialScrollP = Utilities.clamp(launchTaskIndex - 1, mMinScrollP, mMaxScrollP);
+ float normX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
+ mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2)) -
+ Math.max(0, mUnfocusedRange.getAbsoluteX(normX)));
+
+ // Set the initial scroll to the predefined state (which differs from the stack)
+ mInitialNormX = new float[] {
+ getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset,
+ FROM_BOTTOM),
+ normX
+ };
}
-
- // Set the initial scroll to the predefined state (which differs from the stack)
- int initialPeekOffset = mStackRect.height() - mInitialTopPeekHeight;
- float initialPeekOffsetPct = (float) initialPeekOffset / mStackRect.height();
- float initialPeekOffsetNormX = mUnfocusedCurveInterpolator.getX(initialPeekOffsetPct);
- float initialFocusedOffset = mStackRect.height() - mInitialTopPeekHeight -
- (mHeaderBarHeight * 1f) + 1;
- float initialFocusedOffsetPct = initialFocusedOffset / mStackRect.height();
- float initialFocusedNormX = mUnfocusedCurveInterpolator.getX(initialFocusedOffsetPct);
- float initialBottomOffset = mStackBottomOffset +
- (ssp.hasDockedTask()
- ? mHeaderBarHeight
- : mInitialBottomPeekHeight);
- float initialBottomOffsetPct = initialBottomOffset / mStackRect.height();
- float initialBottomNormX = mUnfocusedCurveInterpolator.getX(initialBottomOffsetPct);
- /*
- // If we want to offset the top card slightly
- mInitialNormX = scrollToFront
- ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
- : new float[] { initialBottomNormX, initialFocusedNormX,
- initialPeekOffsetNormX, 0f };
- */
- mInitialNormX = scrollToFront
- ? new float[] { initialFocusedNormX, initialPeekOffsetNormX, 0f }
- : new float[] { initialBottomNormX, 0.5f, 0f };
}
}
@@ -669,7 +707,7 @@ public class TaskStackLayoutAlgorithm {
Range currentRange = getInitialFocusState() > 0f ? mFocusedRange : mUnfocusedRange;
currentRange.offset(mInitialScrollP);
int taskBarHeight = mContext.getResources().getDimensionPixelSize(
- R.dimen.recents_task_bar_height);
+ R.dimen.recents_task_view_header_height);
int numVisibleTasks = Math.max(mNumFreeformTasks, 1);
int numVisibleThumbnails = Math.max(mNumFreeformTasks, 1);
float prevScreenY = Integer.MAX_VALUE;
@@ -869,6 +907,25 @@ public class TaskStackLayoutAlgorithm {
}
/**
+ * Returns the original scroll progress to scroll to such that the top of the task is at the top
+ * of the stack.
+ */
+ float getStackScrollForTaskIgnoreOverrides(Task t) {
+ return (float) mTaskIndexMap.get(t.key.id, 0);
+ }
+
+ /**
+ * Returns the scroll progress to scroll to such that the top of the task at the initial top
+ * offset (which is at the task's brightest point).
+ */
+ float getStackScrollForTaskAtInitialOffset(Task t) {
+ float normX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
+ mUnfocusedRange.offset(0f);
+ return Utilities.clamp((float) mTaskIndexMap.get(t.key.id, 0) - Math.max(0,
+ mUnfocusedRange.getAbsoluteX(normX)), mMinScrollP, mMaxScrollP);
+ }
+
+ /**
* Maps a movement in screen y, relative to {@param downY}, to a movement in along the arc
* length of the curve. We know the curve is mostly flat, so we just map the length of the
* screen along the arc-length proportionally (1/arclength).
@@ -890,6 +947,76 @@ public class TaskStackLayoutAlgorithm {
}
/**
+ * Returns the task stack bounds in the current orientation. This rect takes into account the
+ * top and right system insets (but not the bottom inset) and left/right paddings, but _not_
+ * the top/bottom padding or insets.
+ */
+ public void getTaskStackBounds(Rect windowRect, int topInset, int rightInset,
+ Rect taskStackBounds) {
+ RecentsConfiguration config = Recents.getConfiguration();
+ if (config.hasTransposedNavBar) {
+ taskStackBounds.set(windowRect.left, windowRect.top + topInset,
+ windowRect.right - rightInset, windowRect.bottom);
+ } else {
+ taskStackBounds.set(windowRect.left, windowRect.top + topInset,
+ windowRect.right - rightInset, windowRect.bottom);
+ }
+
+ // Ensure that the new width is at most the smaller display edge size
+ Rect displayRect = Recents.getSystemServices().getDisplayRect();
+ int sideMargin = getScaleForExtent(windowRect, displayRect, mBaseSideMargin, mMinMargin,
+ WIDTH);
+ int targetStackWidth = Math.min(taskStackBounds.width() - 2 * sideMargin,
+ Math.min(displayRect.width(), displayRect.height()));
+ taskStackBounds.inset((taskStackBounds.width() - targetStackWidth) / 2, 0);
+ }
+
+ /**
+ * Retrieves resources that are constant regardless of the current configuration of the device.
+ */
+ public static int getDimensionForDevice(Resources res, int phoneResId,
+ int tabletResId, int xlargeTabletResId) {
+ return getDimensionForDevice(res, phoneResId, phoneResId, tabletResId, tabletResId,
+ xlargeTabletResId, xlargeTabletResId);
+ }
+
+ /**
+ * Retrieves resources that are constant regardless of the current configuration of the device.
+ */
+ public static int getDimensionForDevice(Resources res, int phonePortResId, int phoneLandResId,
+ int tabletPortResId, int tabletLandResId, int xlargeTabletPortResId,
+ int xlargeTabletLandResId) {
+ RecentsConfiguration config = Recents.getConfiguration();
+ boolean isLandscape = Recents.getSystemServices().getDisplayOrientation() ==
+ Configuration.ORIENTATION_LANDSCAPE;
+ if (config.isXLargeScreen) {
+ return res.getDimensionPixelSize(isLandscape
+ ? xlargeTabletLandResId
+ : xlargeTabletPortResId);
+ } else if (config.isLargeScreen) {
+ return res.getDimensionPixelSize(isLandscape
+ ? tabletLandResId
+ : tabletPortResId);
+ } else {
+ return res.getDimensionPixelSize(isLandscape
+ ? phoneLandResId
+ : phonePortResId);
+ }
+ }
+
+ /**
+ * Returns the normalized x on the unfocused curve given an absolute Y position (relative to the
+ * stack height).
+ */
+ private float getNormalizedXFromUnfocusedY(float y, @AnchorSide int fromSide) {
+ float offset = (fromSide == FROM_TOP)
+ ? mStackRect.height() - y
+ : y;
+ float offsetPct = offset / mStackRect.height();
+ return mUnfocusedCurveInterpolator.getX(offsetPct);
+ }
+
+ /**
* Creates a new path for the focused curve.
*/
private Path constructFocusedCurve() {
@@ -897,13 +1024,12 @@ public class TaskStackLayoutAlgorithm {
// linear pieces that goes from (0,1) through (0.5, peek height offset),
// (0.5, bottom task offsets), and (1,0).
float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
- float bottomPeekHeightPct = Math.max(
- mSystemInsets.bottom + mFocusedRange.relativeMax * mFocusedBottomTaskPeekHeight,
- mStackBottomOffset + mFocusedBottomTaskPeekHeight) / mStackRect.height();
+ float bottomPeekHeightPct = (float) (mStackBottomOffset + mFocusedBottomPeekHeight) /
+ mStackRect.height();
Path p = new Path();
p.moveTo(0f, 1f);
p.lineTo(0.5f, 1f - topPeekHeightPct);
- p.lineTo(0.5f + (0.5f / mFocusedRange.relativeMax), bottomPeekHeightPct);
+ p.lineTo(1f - (0.5f / mFocusedRange.relativeMax), bottomPeekHeightPct);
p.lineTo(1f, 0f);
return p;
}
@@ -919,16 +1045,16 @@ public class TaskStackLayoutAlgorithm {
// the control point of the second bezier such that between it and a first known point,
// there is a tangent at (0.5, peek height offset).
float cpoint1X = 0.4f;
- float cpoint1Y = 1f;
- float peekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
- float slope = ((1f - peekHeightPct) - cpoint1Y) / (0.5f - cpoint1X);
+ float cpoint1Y = 0.975f;
+ float topPeekHeightPct = (float) mFocusedTopPeekHeight / mStackRect.height();
+ float slope = ((1f - topPeekHeightPct) - cpoint1Y) / (0.5f - cpoint1X);
float b = 1f - slope * cpoint1X;
float cpoint2X = 0.65f;
float cpoint2Y = slope * cpoint2X + b;
Path p = new Path();
p.moveTo(0f, 1f);
- p.cubicTo(0f, 1f, cpoint1X, cpoint1Y, 0.5f, 1f - peekHeightPct);
- p.cubicTo(0.5f, 1f - peekHeightPct, cpoint2X, cpoint2Y, 1f, 0f);
+ p.cubicTo(0f, 1f, cpoint1X, cpoint1Y, 0.5f, 1f - topPeekHeightPct);
+ p.cubicTo(0.5f, 1f - topPeekHeightPct, cpoint2X, cpoint2Y, 1f, 0f);
return p;
}
@@ -950,15 +1076,30 @@ public class TaskStackLayoutAlgorithm {
* Creates a new path for the unfocused dim curve.
*/
private Path constructUnfocusedDimCurve() {
+ float focusX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
+ float cpoint2X = focusX + (1f - focusX) / 2;
Path p = new Path();
// The unfocused dim interpolator starts at max dim, reduces to zero at 0.5 (the focused
// task), then goes back to max dim towards the front of the stack
p.moveTo(0f, MAX_DIM);
- p.cubicTo(0.1f, MAX_DIM, 0.4f, 0.0f, 0.5f, 0f);
- p.cubicTo(0.6f, 0f, 0.9f, MAX_DIM / 2f, 1f, MAX_DIM / 2f);
+ p.cubicTo(focusX * 0.5f, MAX_DIM, focusX * 0.75f, MAX_DIM * 0.75f, focusX, 0f);
+ p.cubicTo(cpoint2X, 0f, cpoint2X, MED_DIM, 1f, MED_DIM);
return p;
}
+ /**
+ * Scales the given {@param value} to the scale of the {@param instance} rect relative to the
+ * {@param other} rect in the {@param extent} side.
+ */
+ private int getScaleForExtent(Rect instance, Rect other, int value, int minValue,
+ @Extent int extent) {
+ if (extent == WIDTH) {
+ return Math.max(minValue, (int) (((float) instance.width() / other.width()) * value));
+ } else if (extent == HEIGHT) {
+ return Math.max(minValue, (int) (((float) instance.height() / other.height()) * value));
+ }
+ return value;
+ }
/**
* Updates the current transforms that would put a TaskView at the front and back of the stack.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 0b20d21d806c..c9cc1e99977e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -59,8 +59,7 @@ import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
-import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
-import com.android.systemui.recents.events.activity.HideHistoryEvent;
+import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
import com.android.systemui.recents.events.activity.HideRecentsEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
@@ -68,8 +67,7 @@ import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
-import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
-import com.android.systemui.recents.events.activity.ShowHistoryEvent;
+import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
@@ -84,7 +82,6 @@ import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
import com.android.systemui.recents.misc.DozeTrigger;
-import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
@@ -106,15 +103,15 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
private final static String KEY_SAVED_STATE_LAYOUT_STACK_SCROLL =
"saved_instance_state_layout_stack_scroll";
- // The thresholds at which to show/hide the history button.
- private static final float SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
- private static final float HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
+ // The thresholds at which to show/hide the stack action button.
+ private static final float SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
+ private static final float HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD = 0.3f;
public static final int DEFAULT_SYNC_STACK_DURATION = 200;
private static final int DRAG_SCALE_DURATION = 175;
private static final float DRAG_SCALE_FACTOR = 1.05f;
- private static final int LAUNCH_NEXT_SCROLL_BASE_DURATION = 200;
+ private static final int LAUNCH_NEXT_SCROLL_BASE_DURATION = 216;
private static final int LAUNCH_NEXT_SCROLL_INCR_DURATION = 32;
private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>();
@@ -165,11 +162,18 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// The current stack bounds are dynamic and may change as the user drags and drops
@ViewDebug.ExportedProperty(category="recents")
private Rect mStackBounds = new Rect();
+ // The current window bounds at the point we were measured
+ @ViewDebug.ExportedProperty(category="recents")
+ private Rect mStableWindowRect = new Rect();
+ // The current window bounds are dynamic and may change as the user drags and drops
+ @ViewDebug.ExportedProperty(category="recents")
+ private Rect mWindowRect = new Rect();
private Rect mTmpRect = new Rect();
private ArrayMap<Task.TaskKey, TaskView> mTmpTaskViewMap = new ArrayMap<>();
private List<TaskView> mTmpTaskViews = new ArrayList<>();
private TaskViewTransform mTmpTransform = new TaskViewTransform();
+ private ArrayList<TaskViewTransform> mTmpTaskTransforms = new ArrayList<>();
private int[] mTmpIntPair = new int[2];
// A convenience update listener to request updating clipping of tasks
@@ -302,7 +306,8 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
/**
* Sets the stack tasks of this TaskStackView from the given TaskStack.
*/
- public void setTasks(TaskStack stack, boolean notifyStackChanges, boolean relayoutTaskStack) {
+ public void setTasks(TaskStack stack, boolean notifyStackChanges, boolean relayoutTaskStack,
+ boolean multiWindowChange) {
boolean isInitialized = mLayoutAlgorithm.isInitialized();
mStack.setTasks(getContext(), stack.computeAllTasksList(),
notifyStackChanges && isInitialized);
@@ -310,7 +315,9 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
// Only update the layout if we are notifying, otherwise, we will update it in the next
// measure/layout pass
updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
- updateToInitialState();
+ if (!multiWindowChange) {
+ updateToInitialState();
+ }
if (relayoutTaskStack) {
relayoutTaskViews(AnimationProps.IMMEDIATE);
@@ -622,15 +629,17 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/**
- * Relayout the the visible {@link TaskView}s to their current transforms as specified by the
- * {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
- * animations that are current running on those task views, and will ensure that the children
- * {@link TaskView}s will match the set of visible tasks in the stack.
- *
- * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>)
+ * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean)
*/
void relayoutTaskViews(AnimationProps animation) {
- relayoutTaskViews(animation, mIgnoreTasks);
+ relayoutTaskViews(animation, mIgnoreTasks, false /* ignoreTaskOverrides */);
+ }
+
+ /**
+ * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>, boolean)
+ */
+ void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet) {
+ relayoutTaskViews(animation, ignoreTasksSet, false /* ignoreTaskOverrides */);
}
/**
@@ -641,13 +650,14 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
*
* @param ignoreTasksSet the set of tasks to ignore in the relayout
*/
- void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet) {
+ void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet,
+ boolean ignoreTaskOverrides) {
// If we had a deferred animation, cancel that
mDeferredTaskViewLayoutAnimation = null;
// Synchronize the current set of TaskViews
bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet,
- false /* ignoreTaskOverrides */);
+ ignoreTaskOverrides /* ignoreTaskOverrides */);
// Animate them to their final transforms with the given animation
List<TaskView> taskViews = getTaskViews();
@@ -1059,8 +1069,10 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
event.setContentDescription(frontMostTask.getTask().title);
}
event.setItemCount(mStack.getTaskCount());
- event.setScrollY(mStackScroller.mScroller.getCurrY());
- event.setMaxScrollY(mStackScroller.progressToScrollRange(mLayoutAlgorithm.mMaxScrollP));
+
+ int stackHeight = mLayoutAlgorithm.mStackRect.height();
+ event.setScrollY((int) (mStackScroller.getStackScroll() * stackHeight));
+ event.setMaxScrollY((int) (mLayoutAlgorithm.mMaxScrollP * stackHeight));
}
@Override
@@ -1161,23 +1173,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/**
- * Updates the expected task stack bounds for this stack view.
+ * Updates the system insets.
*/
- public void setTaskStackBounds(Rect taskStackBounds, Rect systemInsets) {
- // We can get spurious measure passes with the old bounds when docking, and since we are
- // using the current stack bounds during drag and drop, don't overwrite them until we
- // actually get new bounds
- boolean requiresLayout = false;
- if (!taskStackBounds.equals(mStableStackBounds)) {
- mStableStackBounds.set(taskStackBounds);
- mStackBounds.set(taskStackBounds);
- requiresLayout = true;
- }
+ public void setSystemInsets(Rect systemInsets) {
if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) {
mLayoutAlgorithm.setSystemInsets(systemInsets);
- requiresLayout = true;
- }
- if (requiresLayout) {
requestLayout();
}
}
@@ -1192,8 +1192,20 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
+ // Update the stable stack bounds, but only update the current stack bounds if the stable
+ // bounds have changed. This is because we may get spurious measures while dragging where
+ // our current stack bounds reflect the target drop region.
+ mLayoutAlgorithm.getTaskStackBounds(new Rect(0, 0, width, height),
+ mLayoutAlgorithm.mSystemInsets.top, mLayoutAlgorithm.mSystemInsets.right, mTmpRect);
+ if (!mTmpRect.equals(mStableStackBounds)) {
+ mStableStackBounds.set(mTmpRect);
+ mStackBounds.set(mTmpRect);
+ mStableWindowRect.set(0, 0, width, height);
+ mWindowRect.set(0, 0, width, height);
+ }
+
// Compute the rects in the stack algorithm
- mLayoutAlgorithm.initialize(mStackBounds,
+ mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
@@ -1241,11 +1253,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
MeasureSpec.EXACTLY));
}
- /**
- * This is called with the size of the space not including the top or right insets, or the
- * search bar height in portrait (but including the search bar width in landscape, since we want
- * to draw under it.
- */
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
// Layout each of the TaskViews
@@ -1282,6 +1289,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mTmpRect.setEmpty();
}
Rect taskRect = mLayoutAlgorithm.mTaskRect;
+ tv.cancelTransformAnimation();
tv.layout(taskRect.left - mTmpRect.left, taskRect.top - mTmpRect.top,
taskRect.right + mTmpRect.right, taskRect.bottom + mTmpRect.bottom);
}
@@ -1306,12 +1314,11 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
false /* requestViewFocus */);
}
- // Update the history button visibility
- if (shouldShowHistoryButton() &&
- mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new ShowHistoryButtonEvent(false /* translate */));
+ // Update the stack action button visibility
+ if (mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
} else {
- EventBus.getDefault().send(new HideHistoryButtonEvent());
+ EventBus.getDefault().send(new HideStackActionButtonEvent());
}
}
@@ -1432,12 +1439,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
- @Override
- public void onHistoryTaskRemoved(TaskStack stack, Task removedTask,
- AnimationProps animation) {
- // To be implemented
- }
-
/**** ViewPoolConsumer Implementation ****/
@Override
@@ -1572,13 +1573,12 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
mLayoutAlgorithm.updateFocusStateOnScroll(curScroll, curScroll - prevScroll);
if (mEnterAnimationComplete) {
- if (shouldShowHistoryButton() &&
- prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
- curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new ShowHistoryButtonEvent(true /* translate */));
- } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
- curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
- EventBus.getDefault().send(new HideHistoryButtonEvent());
+ if (prevScroll > SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
+ curScroll <= SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new ShowStackActionButtonEvent(true /* translate */));
+ } else if (prevScroll < HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
+ curScroll >= HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) {
+ EventBus.getDefault().send(new HideStackActionButtonEvent());
}
}
}
@@ -1625,15 +1625,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
cancelAllTaskViewAnimations();
final Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
- if (getChildViewForTask(launchTask) == null) {
- List<TaskView> taskViews = getTaskViews();
- int lastTaskIndex = !taskViews.isEmpty()
- ? mStack.indexOfStackTask(taskViews.get(taskViews.size() - 1).getTask())
- : mStack.getTaskCount() - 1;
- int duration = LAUNCH_NEXT_SCROLL_BASE_DURATION +
- Math.abs(mStack.indexOfStackTask(launchTask) - lastTaskIndex)
- * LAUNCH_NEXT_SCROLL_INCR_DURATION;
- mStackScroller.animateScroll(mLayoutAlgorithm.getStackScrollForTask(launchTask),
+ float curScroll = mStackScroller.getStackScroll();
+ float targetScroll = mLayoutAlgorithm.getStackScrollForTaskAtInitialOffset(launchTask);
+ float absScrollDiff = Math.abs(targetScroll - curScroll);
+ if (getChildViewForTask(launchTask) == null || absScrollDiff > 0.35f) {
+ int duration = (int) (LAUNCH_NEXT_SCROLL_BASE_DURATION +
+ absScrollDiff * LAUNCH_NEXT_SCROLL_INCR_DURATION);
+ mStackScroller.animateScroll(targetScroll,
duration, new Runnable() {
@Override
public void run() {
@@ -1757,32 +1755,38 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public final void onBusEvent(DragDropTargetChangedEvent event) {
AnimationProps animation = new AnimationProps(250, Interpolators.FAST_OUT_SLOW_IN);
+ boolean ignoreTaskOverrides = false;
if (event.dropTarget instanceof TaskStack.DockState) {
// Calculate the new task stack bounds that matches the window size that Recents will
// have after the drop
final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(),
getMeasuredHeight(), mDividerSize, mLayoutAlgorithm.mSystemInsets,
- getResources()));
- mLayoutAlgorithm.initialize(mStackBounds,
+ mLayoutAlgorithm, getResources(), mWindowRect));
+ mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
+ ignoreTaskOverrides = true;
} else {
// Restore the pre-drag task stack bounds, but ensure that we don't layout the dragging
// task view, so add it back to the ignore set after updating the layout
+ mWindowRect.set(mStableWindowRect);
mStackBounds.set(mStableStackBounds);
removeIgnoreTask(event.task);
- mLayoutAlgorithm.initialize(mStackBounds,
+ mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
updateLayoutAlgorithm(true /* boundScroll */);
addIgnoreTask(event.task);
}
- relayoutTaskViews(animation);
+ relayoutTaskViews(animation, mIgnoreTasks, ignoreTaskOverrides);
}
public final void onBusEvent(final DragEndEvent event) {
// We don't handle drops on the dock regions
if (event.dropTarget instanceof TaskStack.DockState) {
+ // However, we do need to reset the overrides, since the last state of this task stack
+ // view layout was ignoring task overrides (see DragDropTargetChangedEvent handler)
+ mLayoutAlgorithm.clearUnfocusedTaskOverrides();
return;
}
@@ -1888,22 +1892,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
}
- public final void onBusEvent(ShowHistoryEvent event) {
- ReferenceCountedTrigger postAnimTrigger = new ReferenceCountedTrigger();
- postAnimTrigger.addLastDecrementRunnable(new Runnable() {
- @Override
- public void run() {
- setVisibility(View.INVISIBLE);
- }
- });
- mAnimationHelper.startShowHistoryAnimation(postAnimTrigger);
- }
-
- public final void onBusEvent(HideHistoryEvent event) {
- setVisibility(View.VISIBLE);
- mAnimationHelper.startHideHistoryAnimation();
- }
-
public final void onBusEvent(MultiWindowStateChangedEvent event) {
if (!event.inMultiWindow) {
// Scroll the stack to the front to see the undocked task
@@ -1924,7 +1912,7 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
public final void onBusEvent(ConfigurationChangedEvent event) {
mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
- mLayoutAlgorithm.initialize(mStackBounds,
+ mLayoutAlgorithm.initialize(mWindowRect, mStackBounds,
TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
}
@@ -1993,13 +1981,6 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
}
/**
- * @return whether the history button should be visible
- */
- private boolean shouldShowHistoryButton() {
- return !mStack.getHistoricalTasks().isEmpty();
- }
-
- /**
* Reads current system flags related to accessibility and screen pinning.
*/
private void readSystemFlags() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
index 9be3542bf59e..583fb88e4069 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewScroller.java
@@ -28,8 +28,6 @@ import android.widget.OverScroller;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
-import com.android.systemui.recents.Recents;
-import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
/* The scrolling logic for a TaskStackView */
@@ -189,7 +187,7 @@ public class TaskStackViewScroller {
// Finish any current scrolling animations
if (mScrollAnimator != null && mScrollAnimator.isRunning()) {
setStackScroll(mFinalAnimatedScroll);
- mScroller.startScroll(0, progressToScrollRange(mFinalAnimatedScroll), 0, 0, 0);
+ mScroller.forceFinished(true);
}
stopScroller();
stopBoundScrollAnimation();
@@ -223,12 +221,6 @@ public class TaskStackViewScroller {
/**** OverScroller ****/
- // TODO: Remove
- @Deprecated
- int progressToScrollRange(float p) {
- return (int) (p * mLayoutAlgorithm.mStackRect.height());
- }
-
/** Called from the view draw, computes the next scroll. */
boolean computeScroll() {
if (mScroller.computeScrollOffset()) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index 863591124ff7..aed19c3e0b9a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -121,7 +121,7 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
mScrollTouchSlop = configuration.getScaledTouchSlop();
mWindowTouchSlop = configuration.getScaledWindowTouchSlop();
mFlingAnimUtils = new FlingAnimationUtils(context, 0.2f);
- mOverscrollSize = res.getDimensionPixelSize(R.dimen.recents_stack_overscroll);
+ mOverscrollSize = res.getDimensionPixelSize(R.dimen.recents_fling_overscroll_distance);
mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, context) {
@Override
protected float getSize(View v) {
@@ -458,12 +458,13 @@ class TaskStackViewTouchHandler implements SwipeHelper.Callback {
newStackScroll = stackScroller.getBoundedStackScroll(newStackScroll);
} else if (pullStackForward) {
// Otherwise, offset the scroll by the movement of the anchor task
- float anchorTaskScroll = layoutAlgorithm.getStackScrollForTask(anchorTask);
+ float anchorTaskScroll =
+ layoutAlgorithm.getStackScrollForTaskIgnoreOverrides(anchorTask);
float stackScrollOffset = (anchorTaskScroll - prevAnchorTaskScroll);
if (layoutAlgorithm.getFocusState() != TaskStackLayoutAlgorithm.STATE_FOCUSED) {
// If we are focused, we don't want the front task to move, but otherwise, we
// allow the back task to move up, and the front task to move back
- stackScrollOffset /= 2;
+ stackScrollOffset *= 0.75f;
}
newStackScroll = stackScroller.getBoundedStackScroll(stackScroller.getStackScroll()
+ stackScrollOffset);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 7584a2e08f85..107d8d41e9a3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,13 +16,14 @@
package com.android.systemui.recents.views;
+import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
+
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
-import android.graphics.Color;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Point;
@@ -59,8 +60,6 @@ import com.android.systemui.recents.model.TaskStack;
import java.util.ArrayList;
-import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
-
/**
* A {@link TaskView} represents a fixed view of a task. Because the TaskView's layout is directed
* solely by the {@link TaskStackView}, we make it a fixed size layout which allows relayouts down
@@ -559,6 +558,13 @@ public class TaskView extends FixedSizeFrameLayout implements Task.TaskCallbacks
postAnimationTrigger.decrementOnAnimationEnd());
}
+ @Override
+ public void onStartFrontTaskEnterAnimation(boolean screenPinningEnabled) {
+ if (screenPinningEnabled) {
+ showActionButton(false /* fadeIn */, 0 /* fadeInDuration */);
+ }
+ }
+
/**** TaskCallbacks Implementation ****/
public void onTaskBound(Task t) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index b2a7d902f002..a2e95737eecf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -337,6 +337,11 @@ public class TaskViewHeader extends FrameLayout
}
}
+ /** Only exposed for the workaround for b/27815919. */
+ public ImageView getIconView() {
+ return mIconView;
+ }
+
/** Returns the secondary color for a primary color. */
int getSecondaryColor(int primaryColor, boolean useLightOverlayColor) {
int overlayColor = useLightOverlayColor ? Color.WHITE : Color.BLACK;
@@ -350,6 +355,7 @@ public class TaskViewHeader extends FrameLayout
public void setDimAlpha(float dimAlpha) {
if (Float.compare(mDimAlpha, dimAlpha) != 0) {
mDimAlpha = dimAlpha;
+ mTitleView.setAlpha(1f - dimAlpha);
updateBackgroundColor(mBackground.getColor(), dimAlpha);
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
index 7f61e7a33577..132c09f03bdd 100644
--- a/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
+++ b/packages/SystemUI/src/com/android/systemui/stackdivider/DividerView.java
@@ -83,18 +83,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
private static final int TASK_POSITION_SAME = Integer.MAX_VALUE;
/**
- * Fraction of the divider position between two snap targets to switch to the full-screen
- * target.
- */
- private static final float SWITCH_FULLSCREEN_FRACTION = 0.12f;
-
- /**
- * Fraction of the divider position between two snap targets to switch to the larger target
- * for the bottom/right app layout.
- */
- private static final float BOTTOM_RIGHT_SWITCH_BIGGER_FRACTION = 0.2f;
-
- /**
* How much the background gets scaled when we are in the minimized dock state.
*/
private static final float MINIMIZE_DOCK_SCALE = 0.375f;
@@ -653,12 +641,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
restrictDismissingTaskPosition(taskPosition, mDockSide, taskSnapTarget);
int taskPositionOther =
restrictDismissingTaskPosition(taskPosition, dockSideInverted, taskSnapTarget);
-
- taskPositionDocked = minimizeHoles(position, taskPositionDocked, mDockSide,
- taskSnapTarget);
- taskPositionOther = minimizeHoles(position, taskPositionOther, dockSideInverted,
- taskSnapTarget);
-
calculateBoundsForPosition(taskPositionDocked, mDockSide, mDockedTaskRect);
calculateBoundsForPosition(taskPositionOther, dockSideInverted, mOtherTaskRect);
mDisplayRect.set(0, 0, mDisplayWidth, mDisplayHeight);
@@ -724,51 +706,6 @@ public class DividerView extends FrameLayout implements OnTouchListener,
}
/**
- * Given the current split position and the task position calculated by dragging, this
- * method calculates a "better" task position in a sense so holes get smaller while dragging.
- *
- * @return the new task position
- */
- private int minimizeHoles(int position, int taskPosition, int dockSide,
- SnapTarget taskSnapTarget) {
- if (dockSideTopLeft(dockSide)) {
- if (position > taskPosition) {
- SnapTarget nextTarget = mSnapAlgorithm.getNextTarget(taskSnapTarget);
-
- // If the next target is the dismiss end target, switch earlier to make the hole
- // smaller.
- if (nextTarget != taskSnapTarget
- && nextTarget == mSnapAlgorithm.getDismissEndTarget()) {
- float t = (float) (position - taskPosition)
- / (nextTarget.position - taskPosition);
- if (t > SWITCH_FULLSCREEN_FRACTION) {
- return nextTarget.position;
- }
- }
- }
- } else if (dockSideBottomRight(dockSide)) {
- if (position < taskPosition) {
- SnapTarget previousTarget = mSnapAlgorithm.getPreviousTarget(taskSnapTarget);
- if (previousTarget != taskSnapTarget) {
- float t = (float) (taskPosition - position)
- / (taskPosition - previousTarget.position);
-
- // In general, switch a bit earlier (at 20% instead of 50%), but if we are
- // dismissing the top, switch really early.
- float threshold = previousTarget == mSnapAlgorithm.getDismissStartTarget()
- ? SWITCH_FULLSCREEN_FRACTION
- : BOTTOM_RIGHT_SWITCH_BIGGER_FRACTION;
- if (t > threshold) {
- return previousTarget.position;
- }
-
- }
- }
- }
- return taskPosition;
- }
-
- /**
* When the snap target is dismissing one side, make sure that the dismissing side doesn't get
* 0 size.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java
index 700ea346e327..ef03d5f7e746 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java
@@ -17,18 +17,14 @@
package com.android.systemui.statusbar;
import android.content.Context;
-import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.ImageView;
-import com.android.systemui.R;
-
/**
* An ImageView which supports an attribute specifying whether it has overlapping rendering
* commands and therefore does not need a layer when alpha is changed.
*/
public class AlphaOptimizedImageView extends ImageView {
- private final boolean mHasOverlappingRendering;
public AlphaOptimizedImageView(Context context) {
this(context, null /* attrs */);
@@ -45,21 +41,10 @@ public class AlphaOptimizedImageView extends ImageView {
public AlphaOptimizedImageView(Context context, AttributeSet attrs, int defStyleAttr,
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
-
- TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
- R.styleable.AlphaOptimizedImageView, 0, 0);
-
- try {
- // Default to true, which is what View.java defaults to
- mHasOverlappingRendering = a.getBoolean(
- R.styleable.AlphaOptimizedImageView_hasOverlappingRendering, true);
- } finally {
- a.recycle();
- }
}
@Override
public boolean hasOverlappingRendering() {
- return mHasOverlappingRendering;
+ return false;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
index 767022321209..ae665c7fcee7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
@@ -17,14 +17,19 @@
package com.android.systemui.statusbar;
import android.content.Context;
+import android.content.res.TypedArray;
import android.graphics.drawable.AnimationDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.View;
+import android.widget.ImageView;
import android.widget.RemoteViews.RemoteView;
+import com.android.systemui.R;
+
@RemoteView
-public class AnimatedImageView extends AlphaOptimizedImageView {
+public class AnimatedImageView extends ImageView {
+ private final boolean mHasOverlappingRendering;
AnimationDrawable mAnim;
boolean mAttached;
@@ -34,11 +39,21 @@ public class AnimatedImageView extends AlphaOptimizedImageView {
int mDrawableId;
public AnimatedImageView(Context context) {
- super(context);
+ this(context, null);
}
public AnimatedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
+ TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
+ R.styleable.AnimatedImageView, 0, 0);
+
+ try {
+ // Default to true, which is what View.java defaults toA
+ mHasOverlappingRendering = a.getBoolean(
+ R.styleable.AnimatedImageView_hasOverlappingRendering, true);
+ } finally {
+ a.recycle();
+ }
}
private void updateAnim() {
@@ -106,5 +121,10 @@ public class AnimatedImageView extends AlphaOptimizedImageView {
}
}
}
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return mHasOverlappingRendering;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index bb4a771ec3d6..2d2a08a06227 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1527,6 +1527,21 @@ public abstract class BaseStatusBar extends SystemUI implements
row.setHeadsUpManager(mHeadsUpManager);
row.setRemoteInputController(mRemoteInputController);
row.setOnExpandClickListener(this);
+
+ // Get the app name
+ final String pkg = sbn.getPackageName();
+ String appname = pkg;
+ try {
+ final ApplicationInfo info = pmUser.getApplicationInfo(pkg,
+ PackageManager.GET_UNINSTALLED_PACKAGES
+ | PackageManager.GET_DISABLED_COMPONENTS);
+ if (info != null) {
+ appname = String.valueOf(pmUser.getApplicationLabel(info));
+ }
+ } catch (NameNotFoundException e) {
+ // Do nothing
+ }
+ row.setAppName(appname);
}
workAroundBadLayerDrawableOpacity(row);
@@ -2056,24 +2071,24 @@ public abstract class BaseStatusBar extends SystemUI implements
}
for (int i = 0; i < N; i++) {
NotificationData.Entry entry = activeNotifications.get(i);
+ boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification);
if (onKeyguard) {
entry.row.setOnKeyguard(true);
} else {
entry.row.setOnKeyguard(false);
- boolean top = (i == 0);
- entry.row.setSystemExpanded(top);
+ entry.row.setSystemExpanded(visibleNotifications == 0 && !childNotification);
}
- boolean childNotification = mGroupManager.isChildInGroupWithSummary(entry.notification);
+ boolean suppressedSummary = mGroupManager.isSummaryOfSuppressedGroup(entry.notification);
boolean childWithVisibleSummary = childNotification
&& mGroupManager.getGroupSummary(entry.notification).getVisibility()
== View.VISIBLE;
boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
- if ((isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
+ if (suppressedSummary || (isLockscreenPublicMode() && !mShowLockscreenNotifications) ||
(onKeyguard && (visibleNotifications >= maxNotifications
&& !childWithVisibleSummary
|| !showOnKeyguard))) {
entry.row.setVisibility(View.GONE);
- if (onKeyguard && showOnKeyguard && !childNotification) {
+ if (onKeyguard && showOnKeyguard && !childNotification && !suppressedSummary) {
mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
}
} else {
@@ -2082,7 +2097,8 @@ public abstract class BaseStatusBar extends SystemUI implements
if (!childNotification) {
if (wasGone) {
// notify the scroller of a child addition
- mStackScroller.generateAddAnimation(entry.row, true /* fromMoreCard */);
+ mStackScroller.generateAddAnimation(entry.row,
+ !showOnKeyguard /* fromMoreCard */);
}
visibleNotifications++;
}
@@ -2220,6 +2236,12 @@ public abstract class BaseStatusBar extends SystemUI implements
// swipe-dismissable)
bindVetoButtonClickListener(entry.row, notification);
+ if (!notification.isClearable()) {
+ // The user may have performed a dismiss action on the notification, since it's
+ // not clearable we should snap it back.
+ mStackScroller.snapViewIfNeeded(entry.row);
+ }
+
if (DEBUG) {
// Is this for you?
boolean isForCurrentUser = isNotificationForCurrentProfiles(notification);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index 22bb8ebb2dc4..f9edeb312644 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -43,6 +43,7 @@ import android.widget.RemoteViews;
import com.android.systemui.R;
import com.android.systemui.classifier.FalsingManager;
+import com.android.systemui.statusbar.notification.HybridNotificationView;
import com.android.systemui.statusbar.notification.NotificationViewWrapper;
import com.android.systemui.statusbar.phone.NotificationGroupManager;
import com.android.systemui.statusbar.policy.HeadsUpManager;
@@ -109,6 +110,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
private NotificationGuts mGuts;
private NotificationData.Entry mEntry;
private StatusBarNotification mStatusBarNotification;
+ private String mAppName;
private boolean mIsHeadsUp;
private boolean mLastChronometerRunning = true;
private NotificationHeaderView mNotificationHeader;
@@ -227,6 +229,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
updateClearability();
if (mIsSummaryWithChildren) {
recreateNotificationHeader();
+ mChildrenContainer.onNotificationUpdated();
}
if (mIconAnimationRunning) {
setIconAnimationRunning(true);
@@ -285,6 +288,13 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mPrivateLayout.setRemoteInputController(r);
}
+ public void setAppName(String appName) {
+ mAppName = appName;
+ if (mSettingsIconRow != null) {
+ mSettingsIconRow.setAppName(mAppName);
+ }
+ }
+
public void addChildNotification(ExpandableNotificationRow row) {
addChildNotification(row, -1);
}
@@ -564,6 +574,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mSettingsIconRow = (NotificationSettingsIconRow) LayoutInflater.from(mContext).inflate(
R.layout.notification_settings_icon_row, this, false);
mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
+ mSettingsIconRow.setAppName(mAppName);
mSettingsIconRow.setVisibility(oldSettings.getVisibility());
addView(mSettingsIconRow, settingsIndex);
@@ -584,6 +595,29 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
mPublicLayout.closeRemoteInput();
}
+ /**
+ * Set by how much the single line view should be indented.
+ */
+ public void setSingleLineWidthIndention(int indention) {
+ mPrivateLayout.setSingleLineWidthIndention(indention);
+ }
+
+ public int getNotificationColor() {
+ int color = getStatusBarNotification().getNotification().color;
+ if (color == Notification.COLOR_DEFAULT) {
+ return mContext.getColor(com.android.internal.R.color.notification_icon_default_color);
+ }
+ return color;
+ }
+
+ public HybridNotificationView getSingleLineView() {
+ return mPrivateLayout.getSingleLineView();
+ }
+
+ public boolean isOnKeyguard() {
+ return mOnKeyguard;
+ }
+
public interface ExpansionLogger {
public void logNotificationExpansion(String key, boolean userAction, boolean expanded);
}
@@ -658,6 +692,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
public void onInflate(ViewStub stub, View inflated) {
mSettingsIconRow = (NotificationSettingsIconRow) inflated;
mSettingsIconRow.setNotificationRowParent(ExpandableNotificationRow.this);
+ mSettingsIconRow.setAppName(mAppName);
}
});
mGutsStub = (ViewStub) findViewById(R.id.notification_guts_stub);
@@ -677,6 +712,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
public void onInflate(ViewStub stub, View inflated) {
mChildrenContainer = (NotificationChildrenContainer) inflated;
mChildrenContainer.setNotificationParent(ExpandableNotificationRow.this);
+ mChildrenContainer.onNotificationUpdated();
mTranslateableViews.add(mChildrenContainer);
}
});
@@ -1026,11 +1062,8 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
private void onChildrenCountChanged() {
mIsSummaryWithChildren = BaseStatusBar.ENABLE_CHILD_NOTIFICATIONS
- && mGroupManager.hasGroupChildren(mStatusBarNotification);
+ && mChildrenContainer != null && mChildrenContainer.getChildCount() > 0;
if (mIsSummaryWithChildren) {
- if (mChildrenContainer == null) {
- mChildrenContainerStub.inflate();
- }
if (mNotificationHeader == null) {
recreateNotificationHeader();
}
@@ -1270,7 +1303,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
@Override
public int getMinExpandHeight() {
if (mIsSummaryWithChildren && !mShowingPublic) {
- return mChildrenContainer.getMinExpandHeight(mOnKeyguard);
+ return mChildrenContainer.getMinExpandHeight();
}
return getMinHeight();
}
@@ -1357,7 +1390,7 @@ public class ExpandableNotificationRow extends ActivatableNotificationView {
if (isGroupExpanded()) {
return 1.0f;
} else if (isUserLocked()) {
- return mChildrenContainer.getChildExpandFraction();
+ return mChildrenContainer.getGroupExpandFraction();
}
}
return 0.0f;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index c2df292c0880..f4fb0b925b07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -29,9 +29,10 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.FrameLayout;
+import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import com.android.systemui.statusbar.notification.HybridNotificationView;
-import com.android.systemui.statusbar.notification.HybridNotificationViewManager;
+import com.android.systemui.statusbar.notification.HybridGroupManager;
import com.android.systemui.statusbar.notification.NotificationCustomViewWrapper;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.notification.NotificationViewWrapper;
@@ -75,7 +76,7 @@ public class NotificationContentView extends FrameLayout {
private NotificationViewWrapper mContractedWrapper;
private NotificationViewWrapper mExpandedWrapper;
private NotificationViewWrapper mHeadsUpWrapper;
- private HybridNotificationViewManager mHybridViewManager;
+ private HybridGroupManager mHybridGroupManager;
private int mClipTopAmount;
private int mContentHeight;
private int mUnrestrictedContentHeight;
@@ -116,10 +117,11 @@ public class NotificationContentView extends FrameLayout {
private ExpandableNotificationRow mContainingNotification;
private int mTransformationStartVisibleType;
private boolean mUserExpanding;
+ private int mSingleLineWidthIndention;
public NotificationContentView(Context context, AttributeSet attrs) {
super(context, attrs);
- mHybridViewManager = new HybridNotificationViewManager(getContext(), this);
+ mHybridGroupManager = new HybridGroupManager(getContext(), this);
mMinContractedHeight = getResources().getDimensionPixelSize(
R.dimen.min_notification_layout_height);
mNotificationContentMarginEnd = getResources().getDimensionPixelSize(
@@ -139,6 +141,7 @@ public class NotificationContentView extends FrameLayout {
boolean hasFixedHeight = heightMode == MeasureSpec.EXACTLY;
boolean isHeightLimited = heightMode == MeasureSpec.AT_MOST;
int maxSize = Integer.MAX_VALUE;
+ int width = MeasureSpec.getSize(widthMeasureSpec);
if (hasFixedHeight || isHeightLimited) {
maxSize = MeasureSpec.getSize(heightMeasureSpec);
}
@@ -187,12 +190,18 @@ public class NotificationContentView extends FrameLayout {
maxChildHeight = Math.max(maxChildHeight, mHeadsUpChild.getMeasuredHeight());
}
if (mSingleLineView != null) {
- mSingleLineView.measure(widthMeasureSpec,
+ int singleLineWidthSpec = widthMeasureSpec;
+ if (mSingleLineWidthIndention != 0
+ && MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED) {
+ singleLineWidthSpec = MeasureSpec.makeMeasureSpec(
+ width - mSingleLineWidthIndention + mSingleLineView.getPaddingEnd(),
+ MeasureSpec.AT_MOST);
+ }
+ mSingleLineView.measure(singleLineWidthSpec,
MeasureSpec.makeMeasureSpec(maxSize, MeasureSpec.AT_MOST));
maxChildHeight = Math.max(maxChildHeight, mSingleLineView.getMeasuredHeight());
}
int ownHeight = Math.min(maxChildHeight, maxSize);
- int width = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width, ownHeight);
}
@@ -715,7 +724,7 @@ public class NotificationContentView extends FrameLayout {
private void updateSingleLineView() {
if (mIsChildInGroup) {
- mSingleLineView = mHybridViewManager.bindFromNotification(
+ mSingleLineView = mHybridGroupManager.bindFromNotification(
mSingleLineView, mStatusBarNotification.getNotification());
} else if (mSingleLineView != null) {
removeView(mSingleLineView);
@@ -779,13 +788,16 @@ public class NotificationContentView extends FrameLayout {
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT)
);
+ existing = riv;
+ }
+ if (hasRemoteInput) {
int color = entry.notification.getNotification().color;
if (color == Notification.COLOR_DEFAULT) {
color = mContext.getColor(R.color.default_remote_input_background);
}
- riv.setBackgroundColor(color);
-
- return riv;
+ existing.setBackgroundColor(NotificationColorUtil.ensureTextBackgroundColor(color,
+ mContext.getColor(R.color.remote_input_text),
+ mContext.getColor(R.color.remote_input_hint)));
}
return existing;
}
@@ -878,4 +890,20 @@ public class NotificationContentView extends FrameLayout {
updateBackgroundColor(false);
}
}
+
+ /**
+ * Set by how much the single line view should be indented. Used when a overflow indicator is
+ * present and only during measuring
+ */
+ public void setSingleLineWidthIndention(int singleLineWidthIndention) {
+ if (singleLineWidthIndention != mSingleLineWidthIndention) {
+ mSingleLineWidthIndention = singleLineWidthIndention;
+ mContainingNotification.forceLayout();
+ forceLayout();
+ }
+ }
+
+ public HybridNotificationView getSingleLineView() {
+ return mSingleLineView;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
index fcc48bf8d510..a3e78c165b2f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationSettingsIconRow.java
@@ -20,6 +20,7 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
+import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.View;
import android.widget.FrameLayout;
@@ -105,6 +106,13 @@ public class NotificationSettingsIconRow extends FrameLayout implements View.OnC
mParent = parent;
}
+ public void setAppName(String appName) {
+ Resources res = getResources();
+ String description = String.format(res.getString(R.string.notification_gear_accessibility),
+ appName);
+ mGearIcon.setContentDescription(description);
+ }
+
public ExpandableNotificationRow getNotificationParent() {
return mParent;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
index c32ef0e9daf6..726aed329124 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/car/CarStatusBar.java
@@ -17,7 +17,6 @@
package com.android.systemui.statusbar.car;
import android.app.ActivityManager;
-import android.app.ITaskStackListener;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -33,6 +32,7 @@ import android.view.WindowManager;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import com.android.systemui.statusbar.StatusBarState;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
@@ -40,9 +40,7 @@ import com.android.systemui.statusbar.phone.PhoneStatusBar;
* A status bar (and navigation bar) tailored for the automotive use case.
*/
public class CarStatusBar extends PhoneStatusBar {
- private SystemServicesProxy mSystemServicesProxy;
private TaskStackListenerImpl mTaskStackListener;
- private Handler mHandler;
private CarNavigationBarView mCarNavigationBar;
private CarNavigationBarController mController;
@@ -51,10 +49,8 @@ public class CarStatusBar extends PhoneStatusBar {
@Override
public void start() {
super.start();
- mHandler = new Handler();
- mTaskStackListener = new TaskStackListenerImpl(mHandler);
- mSystemServicesProxy = new SystemServicesProxy(mContext);
- mSystemServicesProxy.registerTaskStackListener(mTaskStackListener);
+ mTaskStackListener = new TaskStackListenerImpl();
+ SystemServicesProxy.getInstance(mContext).registerTaskStackListener(mTaskStackListener);
registerPackageChangeReceivers();
}
@@ -114,47 +110,16 @@ public class CarStatusBar extends PhoneStatusBar {
}
/**
- * An implementation of ITaskStackListener, that listens for changes in the system task
+ * An implementation of TaskStackListener, that listens for changes in the system task
* stack and notifies the navigation bar.
*/
- private class TaskStackListenerImpl extends ITaskStackListener.Stub implements Runnable {
- private Handler mHandler;
-
- public TaskStackListenerImpl(Handler handler) {
- this.mHandler = handler;
- }
-
- @Override
- public void onActivityPinned() {
- }
-
- @Override
- public void onPinnedActivityRestartAttempt() {
- }
-
- @Override
- public void onPinnedStackAnimationEnded() {
- }
-
+ private class TaskStackListenerImpl extends TaskStackListener {
@Override
public void onTaskStackChanged() {
- mHandler.removeCallbacks(this);
- mHandler.post(this);
- }
-
- @Override
- public void run() {
- ensureMainThread();
SystemServicesProxy ssp = Recents.getSystemServices();
ActivityManager.RunningTaskInfo runningTaskInfo = ssp.getTopMostTask();
mController.taskChanged(runningTaskInfo.baseActivity.getPackageName());
}
-
- private void ensureMainThread() {
- if (!Looper.getMainLooper().isCurrentThread()) {
- throw new RuntimeException("Must be called on the UI thread");
- }
- }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java
index 28bb66f39572..8f2c81f0726b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridGroupManager.java
@@ -26,6 +26,7 @@ import android.text.style.TextAppearanceSpan;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.statusbar.ExpandableNotificationRow;
@@ -33,18 +34,18 @@ import com.android.systemui.statusbar.ExpandableNotificationRow;
import java.util.List;
/**
- * A class managing {@link HybridNotificationView} views
+ * A class managing hybrid groups that include {@link HybridNotificationView} and the notification
+ * group overflow.
*/
-public class HybridNotificationViewManager {
+public class HybridGroupManager {
private final Context mContext;
private ViewGroup mParent;
- private String mDivider;
+ private int mOverflowNumberColor;
- public HybridNotificationViewManager(Context ctx, ViewGroup parent) {
+ public HybridGroupManager(Context ctx, ViewGroup parent) {
mContext = ctx;
mParent = parent;
- mDivider = " • ";
}
private HybridNotificationView inflateHybridView() {
@@ -55,6 +56,26 @@ public class HybridNotificationViewManager {
return hybrid;
}
+ private TextView inflateOverflowNumber() {
+ LayoutInflater inflater = mContext.getSystemService(LayoutInflater.class);
+ TextView numberView = (TextView) inflater.inflate(
+ R.layout.hybrid_overflow_number, mParent, false);
+ mParent.addView(numberView);
+ updateOverFlowNumberColor(numberView);
+ return numberView;
+ }
+
+ private void updateOverFlowNumberColor(TextView numberView) {
+ numberView.setTextColor(mOverflowNumberColor);
+ }
+
+ public void setOverflowNumberColor(TextView numberView, int overflowNumberColor) {
+ mOverflowNumberColor = overflowNumberColor;
+ if (numberView != null) {
+ updateOverFlowNumberColor(numberView);
+ }
+ }
+
public HybridNotificationView bindFromNotification(HybridNotificationView reusableView,
Notification notification) {
if (reusableView == null) {
@@ -82,33 +103,15 @@ public class HybridNotificationViewManager {
return titleText;
}
- public HybridNotificationView bindFromNotificationGroup(
- HybridNotificationView reusableView,
- List<ExpandableNotificationRow> group, int startIndex) {
+ public TextView bindOverflowNumber(TextView reusableView, int number) {
if (reusableView == null) {
- reusableView = inflateHybridView();
+ reusableView = inflateOverflowNumber();
}
- SpannableStringBuilder summary = new SpannableStringBuilder();
- int childCount = group.size();
- for (int i = startIndex; i < childCount; i++) {
- ExpandableNotificationRow child = group.get(i);
- CharSequence titleText = resolveTitle(
- child.getStatusBarNotification().getNotification());
- if (titleText == null) {
- continue;
- }
- if (!TextUtils.isEmpty(summary)) {
- summary.append(mDivider,
- new TextAppearanceSpan(mContext, R.style.
- TextAppearance_Material_Notification_HybridNotificationDivider),
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- }
- summary.append(BidiFormatter.getInstance().unicodeWrap(titleText));
+ String text = mContext.getResources().getString(
+ R.string.notification_group_overflow_indicator, number);
+ if (!text.equals(reusableView.getText())) {
+ reusableView.setText(text);
}
- // We want to force the same orientation as the layout RTL mode
- BidiFormatter formater = BidiFormatter.getInstance(
- reusableView.getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
- reusableView.bind(formater.unicodeWrap(summary));
return reusableView;
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
index c80cad836f48..0a1795f21234 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/HybridNotificationView.java
@@ -60,6 +60,14 @@ public class HybridNotificationView extends AlphaOptimizedLinearLayout
super(context, attrs, defStyleAttr, defStyleRes);
}
+ public TextView getTitleView() {
+ return mTitleView;
+ }
+
+ public TextView getTextView() {
+ return mTextView;
+ }
+
@Override
protected void onFinishInflate() {
super.onFinishInflate();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
index 6ef61ec337c4..844a2c495501 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationUtils.java
@@ -17,15 +17,19 @@
package com.android.systemui.statusbar.notification;
import android.graphics.Color;
+import android.view.View;
import android.widget.ImageView;
import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
+import com.android.systemui.statusbar.stack.NotificationChildrenContainer;
/**
* A util class for various reusable functions
*/
public class NotificationUtils {
+ private static final int[] sLocationBase = new int[2];
+ private static final int[] sLocationOffset = new int[2];
public static boolean isGrayscale(ImageView v, NotificationColorUtil colorUtil) {
Object isGrayscale = v.getTag(R.id.icon_is_grayscale);
if (isGrayscale != null) {
@@ -47,4 +51,10 @@ public class NotificationUtils {
(int) interpolate(Color.green(startColor), Color.green(endColor), amount),
(int) interpolate(Color.blue(startColor), Color.blue(endColor), amount));
}
+
+ public static float getRelativeYOffset(View offsetView, View baseView) {
+ baseView.getLocationOnScreen(sLocationBase);
+ offsetView.getLocationOnScreen(sLocationOffset);
+ return sLocationOffset[1] - sLocationBase[1];
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
index 50ead3d17833..225751a627b2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/IconMerger.java
@@ -17,6 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.content.Context;
+import android.content.res.Resources;
import android.util.AttributeSet;
import android.view.View;
import android.widget.LinearLayout;
@@ -27,14 +28,17 @@ public class IconMerger extends LinearLayout {
private static final String TAG = "IconMerger";
private static final boolean DEBUG = false;
- private int mIconSize;
+ private final int mIconSize;
+ private final int mIconHPadding;
+
private View mMoreView;
public IconMerger(Context context, AttributeSet attrs) {
super(context, attrs);
- mIconSize = context.getResources().getDimensionPixelSize(
- R.dimen.status_bar_icon_size);
+ Resources res = context.getResources();
+ mIconSize = res.getDimensionPixelSize(R.dimen.status_bar_icon_size);
+ mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_padding);
if (DEBUG) {
setBackgroundColor(0x800099FF);
@@ -45,12 +49,16 @@ public class IconMerger extends LinearLayout {
mMoreView = v;
}
+ private int getFullIconWidth() {
+ return mIconSize + 2 * mIconHPadding;
+ }
+
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// we need to constrain this to an integral multiple of our children
int width = getMeasuredWidth();
- setMeasuredDimension(width - (width % mIconSize), getMeasuredHeight());
+ setMeasuredDimension(width - (width % getFullIconWidth()), getMeasuredHeight());
}
@Override
@@ -70,7 +78,7 @@ public class IconMerger extends LinearLayout {
final boolean overflowShown = (mMoreView.getVisibility() == View.VISIBLE);
// let's assume we have one more slot if the more icon is already showing
if (overflowShown) visibleChildren --;
- final boolean moreRequired = visibleChildren * mIconSize > width;
+ final boolean moreRequired = visibleChildren * getFullIconWidth() > width;
if (moreRequired != overflowShown) {
post(new Runnable() {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
index 03dd25e3c5b0..54af684c3cd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/MultiUserSwitch.java
@@ -130,7 +130,9 @@ public class MultiUserSwitch extends FrameLayout implements View.OnClickListener
Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
getContext(), v, ContactsContract.Profile.CONTENT_URI,
ContactsContract.QuickContact.MODE_LARGE, null);
- getContext().startActivityAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+ if (mQsPanel != null) {
+ mQsPanel.getHost().startActivityDismissingKeyguard(intent);
+ }
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 99896f8b7f23..56a7dbed52cb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -25,7 +25,6 @@ import android.app.ActivityManagerNative;
import android.app.StatusBarManager;
import android.content.Context;
import android.content.res.Configuration;
-import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -90,14 +89,13 @@ public class NavigationBarView extends LinearLayout {
private final NavTransitionListener mTransitionListener = new NavTransitionListener();
private OnVerticalChangedListener mOnVerticalChangedListener;
- private boolean mIsLayoutRtl;
private boolean mLayoutTransitionsEnabled = true;
private boolean mWakeAndUnlocking;
private boolean mCarMode = false;
private boolean mDockedStackExists;
private final SparseArray<ButtonDispatcher> mButtonDisatchers = new SparseArray<>();
- private int mDensity;
+ private Configuration mConfiguration;
private class NavTransitionListener implements TransitionListener {
private boolean mBackTransitioning;
@@ -183,13 +181,13 @@ public class NavigationBarView extends LinearLayout {
mDisplay = ((WindowManager) context.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay();
- final Resources res = getContext().getResources();
mVertical = false;
mShowMenu = false;
mGestureHelper = new NavigationBarGestureHelper(context);
- mDensity = context.getResources().getConfiguration().densityDpi;
- getIcons(context);
+ mConfiguration = new Configuration();
+ mConfiguration.updateFrom(context.getResources().getConfiguration());
+ updateIcons(context, Configuration.EMPTY, mConfiguration);
mBarTransitions = new NavigationBarTransitions(this);
@@ -263,7 +261,7 @@ public class NavigationBarView extends LinearLayout {
return mButtonDisatchers.get(R.id.ime_switcher);
}
- private void getCarModeIcons(Context ctx) {
+ private void updateCarModeIcons(Context ctx) {
mBackCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_carmode);
mBackLandCarModeIcon = mBackCarModeIcon;
mBackAltCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime_carmode);
@@ -271,22 +269,27 @@ public class NavigationBarView extends LinearLayout {
mHomeCarModeIcon = ctx.getDrawable(R.drawable.ic_sysbar_home_carmode);
}
- private void getIcons(Context ctx) {
- mBackIcon = ctx.getDrawable(R.drawable.ic_sysbar_back);
- mBackLandIcon = mBackIcon;
- mBackAltIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime);
- mBackAltLandIcon = mBackAltIcon;
+ private void updateIcons(Context ctx, Configuration oldConfig, Configuration newConfig) {
+ if (oldConfig.orientation != newConfig.orientation) {
+ mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
+ }
+ if (oldConfig.densityDpi != newConfig.densityDpi) {
+ mBackIcon = ctx.getDrawable(R.drawable.ic_sysbar_back);
+ mBackLandIcon = mBackIcon;
+ mBackAltIcon = ctx.getDrawable(R.drawable.ic_sysbar_back_ime);
+ mBackAltLandIcon = mBackAltIcon;
- mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
+ mHomeDefaultIcon = ctx.getDrawable(R.drawable.ic_sysbar_home);
- mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
- mDockedIcon = ctx.getDrawable(R.drawable.ic_sysbar_docked);
- getCarModeIcons(ctx);
+ mRecentIcon = ctx.getDrawable(R.drawable.ic_sysbar_recent);
+ updateCarModeIcons(ctx);
+ }
}
@Override
public void setLayoutDirection(int layoutDirection) {
- getIcons(getContext());
+ // Reload all the icons
+ updateIcons(getContext(), Configuration.EMPTY, mConfiguration);
super.setLayoutDirection(layoutDirection);
}
@@ -598,10 +601,9 @@ public class NavigationBarView extends LinearLayout {
// we are switching to.
setNavigationIconHints(mNavigationIconHints, true);
}
- if (mDensity != newConfig.densityDpi) {
- mDensity = newConfig.densityDpi;
- getIcons(getContext());
- }
+ updateIcons(getContext(), mConfiguration, newConfig);
+ updateRecentsIcon();
+ mConfiguration.updateFrom(newConfig);
}
/**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
index d3681b72372b..f7a6b271bcc6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationGroupManager.java
@@ -17,7 +17,7 @@
package com.android.systemui.statusbar.phone;
import android.service.notification.StatusBarNotification;
-import android.util.ArraySet;
+import android.support.annotation.Nullable;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.NotificationData;
@@ -35,7 +35,7 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
private final HashMap<String, NotificationGroup> mGroupMap = new HashMap<>();
private OnGroupChangeListener mListener;
private int mBarState = -1;
- private ArraySet<String> mHeadsUpedEntries = new ArraySet<>();
+ private HashMap<String, StatusBarNotification> mIsolatedEntries = new HashMap<>();
public void setOnGroupChangeListener(OnGroupChangeListener listener) {
mListener = listener;
@@ -91,6 +91,7 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
} else {
group.summary = null;
}
+ updateSuppression(group);
if (group.children.isEmpty()) {
if (group.summary == null) {
mGroupMap.remove(groupKey);
@@ -109,43 +110,81 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
}
if (isGroupChild) {
group.children.add(added);
+ updateSuppression(group);
} else {
group.summary = added;
group.expanded = added.row.areChildrenExpanded();
+ updateSuppression(group);
if (!group.children.isEmpty()) {
mListener.onGroupCreatedFromChildren(group);
}
}
}
+ private void updateSuppression(NotificationGroup group) {
+ if (group == null) {
+ return;
+ }
+ boolean prevSuppressed = group.suppressed;
+ group.suppressed = group.summary != null && !group.expanded
+ && (group.children.size() == 1
+ || (group.children.size() == 0
+ && !group.summary.notification.getNotification().isGroupChild()
+ && hasIsolatedChildren(group)));
+ if (prevSuppressed != group.suppressed) {
+ mListener.onGroupsChanged();
+ }
+ }
+
+ private boolean hasIsolatedChildren(NotificationGroup group) {
+ return getNumberOfIsolatedChildren(group.summary.notification.getGroupKey()) != 0;
+ }
+
+ private int getNumberOfIsolatedChildren(String groupKey) {
+ int count = 0;
+ for (StatusBarNotification sbn : mIsolatedEntries.values()) {
+ if (sbn.getGroupKey().equals(groupKey) && isIsolated(sbn)) {
+ count++;
+ }
+ }
+ return count;
+ }
+
public void onEntryUpdated(NotificationData.Entry entry,
StatusBarNotification oldNotification) {
if (mGroupMap.get(getGroupKey(oldNotification)) != null) {
onEntryRemovedInternal(entry, oldNotification);
}
onEntryAdded(entry);
+ if (isIsolated(entry.notification)) {
+ mIsolatedEntries.put(entry.key, entry.notification);
+ String oldKey = oldNotification.getGroupKey();
+ String newKey = entry.notification.getGroupKey();
+ if (!oldKey.equals(newKey)) {
+ updateSuppression(mGroupMap.get(oldKey));
+ updateSuppression(mGroupMap.get(newKey));
+ }
+ }
}
- public boolean isVisible(StatusBarNotification sbn) {
- if (!isGroupChild(sbn)) {
- return true;
- }
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
- if (group != null && (group.expanded || group.summary == null)) {
- return true;
- }
- return false;
+ public boolean isSummaryOfSuppressedGroup(StatusBarNotification sbn) {
+ return isGroupSuppressed(getGroupKey(sbn)) && sbn.getNotification().isGroupSummary();
}
- public boolean hasGroupChildren(StatusBarNotification sbn) {
- if (!isGroupSummary(sbn)) {
- return false;
- }
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
- if (group == null) {
- return false;
- }
- return !group.children.isEmpty();
+ public boolean isOnlyChildInSuppressedGroup(StatusBarNotification sbn) {
+ return isGroupSuppressed(sbn.getGroupKey())
+ && sbn.getNotification().isGroupChild()
+ && getTotalNumberOfChildren(sbn) == 1;
+ }
+
+ private int getTotalNumberOfChildren(StatusBarNotification sbn) {
+ return getNumberOfIsolatedChildren(sbn.getGroupKey())
+ + mGroupMap.get(sbn.getGroupKey()).children.size();
+ }
+
+ private boolean isGroupSuppressed(String groupKey) {
+ NotificationGroup group = mGroupMap.get(groupKey);
+ return group != null && group.suppressed;
}
public void setStatusBarState(int newState) {
@@ -163,6 +202,7 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
if (group.expanded) {
setGroupExpanded(group, false);
}
+ updateSuppression(group);
}
}
@@ -174,7 +214,7 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
return false;
}
NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
- if (group == null || group.summary == null) {
+ if (group == null || group.summary == null || group.suppressed) {
return false;
}
return true;
@@ -194,11 +234,30 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
return !group.children.isEmpty();
}
+ /**
+ * Get the summary of a specified status bar notification. For isolated notification this return
+ * itself.
+ */
public ExpandableNotificationRow getGroupSummary(StatusBarNotification sbn) {
- NotificationGroup group = mGroupMap.get(getGroupKey(sbn));
+ return getGroupSummary(getGroupKey(sbn));
+ }
+
+ /**
+ * Similar to {@link #getGroupSummary(StatusBarNotification)} but doesn't get the visual summary
+ * but the logical summary, i.e when a child is isolated, it still returns the summary as if
+ * it wasn't isolated.
+ */
+ public ExpandableNotificationRow getLogicalGroupSummary(
+ StatusBarNotification sbn) {
+ return getGroupSummary(sbn.getGroupKey());
+ }
+
+ @Nullable
+ private ExpandableNotificationRow getGroupSummary(String groupKey) {
+ NotificationGroup group = mGroupMap.get(groupKey);
return group == null ? null
: group.summary == null ? null
- : group.summary.row;
+ : group.summary.row;
}
public void toggleGroupExpansion(StatusBarNotification sbn) {
@@ -210,7 +269,7 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
}
private boolean isIsolated(StatusBarNotification sbn) {
- return mHeadsUpedEntries.contains(sbn.getKey()) && sbn.getNotification().isGroupChild();
+ return mIsolatedEntries.containsKey(sbn.getKey());
}
private boolean isGroupSummary(StatusBarNotification sbn) {
@@ -249,38 +308,55 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
public void onHeadsUpStateChanged(NotificationData.Entry entry, boolean isHeadsUp) {
final StatusBarNotification sbn = entry.notification;
if (entry.row.isHeadsUp()) {
- if (!mHeadsUpedEntries.contains(sbn.getKey())) {
- final boolean groupChild = sbn.getNotification().isGroupChild();
- if (groupChild) {
- // We will be isolated now, so lets update the groups
- onEntryRemovedInternal(entry, entry.notification);
- }
- mHeadsUpedEntries.add(sbn.getKey());
- if (groupChild) {
- onEntryAdded(entry);
- mListener.onChildIsolationChanged();
- }
+ if (shouldIsolate(sbn)) {
+ // We will be isolated now, so lets update the groups
+ onEntryRemovedInternal(entry, entry.notification);
+
+ mIsolatedEntries.put(sbn.getKey(), sbn);
+
+ onEntryAdded(entry);
+ // We also need to update the suppression of the old group, because this call comes
+ // even before the groupManager knows about the notification at all.
+ // When the notification gets added afterwards it is already isolated and therefore
+ // it doesn't lead to an update.
+ updateSuppression(mGroupMap.get(entry.notification.getGroupKey()));
+ mListener.onGroupsChanged();
}
} else {
- if (mHeadsUpedEntries.contains(sbn.getKey())) {
- boolean isolatedBefore = isIsolated(sbn);
- if (isolatedBefore) {
- // not isolated anymore, we need to update the groups
- onEntryRemovedInternal(entry, entry.notification);
- }
- mHeadsUpedEntries.remove(sbn.getKey());
- if (isolatedBefore) {
- onEntryAdded(entry);
- mListener.onChildIsolationChanged();
- }
+ if (mIsolatedEntries.containsKey(sbn.getKey())) {
+ // not isolated anymore, we need to update the groups
+ onEntryRemovedInternal(entry, entry.notification);
+ mIsolatedEntries.remove(sbn.getKey());
+ onEntryAdded(entry);
+ mListener.onGroupsChanged();
}
}
}
+ private boolean shouldIsolate(StatusBarNotification sbn) {
+ NotificationGroup notificationGroup = mGroupMap.get(sbn.getGroupKey());
+ return sbn.getNotification().isGroupChild()
+ && (sbn.getNotification().fullScreenIntent != null
+ || notificationGroup == null
+ || !notificationGroup.expanded
+ || isGroupNotFullyVisible(notificationGroup));
+ }
+
+ private boolean isGroupNotFullyVisible(NotificationGroup notificationGroup) {
+ return notificationGroup.summary == null
+ || notificationGroup.summary.row.getClipTopOptimization() > 0
+ || notificationGroup.summary.row.getClipTopAmount() > 0
+ || notificationGroup.summary.row.getTranslationY() < 0;
+ }
+
public static class NotificationGroup {
public final HashSet<NotificationData.Entry> children = new HashSet<>();
public NotificationData.Entry summary;
public boolean expanded;
+ /**
+ * Is this notification group suppressed, i.e its summary is hidden
+ */
+ public boolean suppressed;
}
public interface OnGroupChangeListener {
@@ -301,8 +377,9 @@ public class NotificationGroupManager implements HeadsUpManager.OnHeadsUpChanged
void onGroupCreatedFromChildren(NotificationGroup group);
/**
- * The isolation of a child has changed i.e it's group changes.
+ * The groups have changed. This can happen if the isolation of a child has changes or if a
+ * group became suppressed / unsuppressed
*/
- void onChildIsolationChanged();
+ void onGroupsChanged();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index 6e345f088b5d..c4917a1c80fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -17,6 +17,7 @@ import com.android.systemui.statusbar.StatusBarIconView;
import com.android.systemui.statusbar.notification.NotificationUtils;
import java.util.ArrayList;
+import java.util.List;
/**
* A controller for the space in the status bar to the left of the system icons. This area is
@@ -42,6 +43,10 @@ public class NotificationIconAreaController {
initializeNotificationAreaViews(context);
}
+ protected View inflateIconArea(LayoutInflater inflater) {
+ return inflater.inflate(R.layout.notification_icon_area, null);
+ }
+
/**
* Initializes the views that will represent the notification area.
*/
@@ -51,14 +56,16 @@ public class NotificationIconAreaController {
mIconHPadding = res.getDimensionPixelSize(R.dimen.status_bar_icon_padding);
LayoutInflater layoutInflater = LayoutInflater.from(context);
- mNotificationIconArea = layoutInflater.inflate(R.layout.notification_icon_area, null);
-
- mMoreIcon = (ImageView) mNotificationIconArea.findViewById(R.id.moreIcon);
- mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
+ mNotificationIconArea = inflateIconArea(layoutInflater);
mNotificationIcons =
(IconMerger) mNotificationIconArea.findViewById(R.id.notificationIcons);
- mNotificationIcons.setOverflowIndicator(mMoreIcon);
+
+ mMoreIcon = (ImageView) mNotificationIconArea.findViewById(R.id.moreIcon);
+ if (mMoreIcon != null) {
+ mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
+ mNotificationIcons.setOverflowIndicator(mMoreIcon);
+ }
}
/**
@@ -88,16 +95,38 @@ public class NotificationIconAreaController {
*/
public void setIconTint(int iconTint) {
mIconTint = iconTint;
- mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
+ if (mMoreIcon != null) {
+ mMoreIcon.setImageTintList(ColorStateList.valueOf(mIconTint));
+ }
applyNotificationIconsTint();
}
+ protected int getHeight() {
+ return mPhoneStatusBar.getStatusBarHeight();
+ }
+
+ protected boolean shouldShowNotification(NotificationData.Entry entry,
+ NotificationData notificationData) {
+ if (notificationData.isAmbient(entry.key)
+ && !NotificationData.showNotificationEvenIfUnprovisioned(entry.notification)) {
+ return false;
+ }
+ if (!PhoneStatusBar.isTopLevelChild(entry)) {
+ return false;
+ }
+ if (entry.row.getVisibility() == View.GONE) {
+ return false;
+ }
+
+ return true;
+ }
+
/**
* Updates the notifications with the given list of notifications to display.
*/
public void updateNotificationIcons(NotificationData notificationData) {
final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
- mIconSize + 2 * mIconHPadding, mPhoneStatusBar.getStatusBarHeight());
+ mIconSize + 2 * mIconHPadding, getHeight());
ArrayList<NotificationData.Entry> activeNotifications =
notificationData.getActiveNotifications();
@@ -107,14 +136,9 @@ public class NotificationIconAreaController {
// Filter out ambient notifications and notification children.
for (int i = 0; i < size; i++) {
NotificationData.Entry ent = activeNotifications.get(i);
- if (notificationData.isAmbient(ent.key)
- && !NotificationData.showNotificationEvenIfUnprovisioned(ent.notification)) {
- continue;
- }
- if (!PhoneStatusBar.isTopLevelChild(ent)) {
- continue;
+ if (shouldShowNotification(ent, notificationData)) {
+ toShow.add(ent.icon);
}
- toShow.add(ent.icon);
}
ArrayList<View> toRemove = new ArrayList<>();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index e5e3cafe9395..560dbac03b6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1731,7 +1731,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- mNavigationBarBottomHeight = insets.getSystemWindowInsetBottom();
+ mNavigationBarBottomHeight = insets.getStableInsetBottom();
updateMaxHeadsUpTranslation();
return insets;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
index f0df7068b74c..960515b9137a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationsQuickSettingsContainer.java
@@ -75,7 +75,7 @@ public class NotificationsQuickSettingsContainer extends FrameLayout
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
- setPadding(0, 0, 0, insets.getSystemWindowInsetBottom());
+ setPadding(0, 0, 0, insets.getStableInsetBottom());
return insets;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index bf5861107b09..86031e1d9e97 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -48,7 +48,6 @@ import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
-import android.hardware.display.DisplayManager;
import android.inputmethodservice.InputMethodService;
import android.media.AudioAttributes;
import android.media.MediaMetadata;
@@ -304,7 +303,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
Point mCurrentDisplaySize = new Point();
protected StatusBarWindowView mStatusBarWindow;
- PhoneStatusBarView mStatusBarView;
+ protected PhoneStatusBarView mStatusBarView;
private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
protected StatusBarWindowManager mStatusBarWindowManager;
private UnlockMethodCache mUnlockMethodCache;
@@ -316,7 +315,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
int mPixelFormat;
Object mQueueLock = new Object();
- StatusBarIconController mIconController;
+ protected StatusBarIconController mIconController;
// expanded notifications
protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -328,7 +327,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// top bar
BaseStatusBarHeader mHeader;
- KeyguardStatusBarView mKeyguardStatusBar;
+ protected KeyguardStatusBarView mKeyguardStatusBar;
View mKeyguardStatusView;
KeyguardBottomAreaView mKeyguardBottomArea;
boolean mLeaveOpenOnKeyguardHide;
@@ -677,6 +676,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mFalsingManager = FalsingManager.getInstance(mContext);
}
+ protected void createIconController() {
+ mIconController = new StatusBarIconController(
+ mContext, mStatusBarView, mKeyguardStatusBar, this);
+ }
+
// ================================================================================
// Constructing the view
// ================================================================================
@@ -810,8 +814,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
// set the initial view visibility
setAreThereNotifications();
- mIconController = new StatusBarIconController(
- mContext, mStatusBarView, mKeyguardStatusBar, this);
+ createIconController();
// Background thread for any controllers that need it.
mHandlerThread = new HandlerThread(TAG, Process.THREAD_PRIORITY_BACKGROUND);
@@ -1632,16 +1635,14 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void updateSpeedbump() {
int speedbumpIndex = -1;
int currentIndex = 0;
- ArrayList<Entry> activeNotifications = mNotificationData.getActiveNotifications();
- final int N = activeNotifications.size();
+ final int N = mStackScroller.getChildCount();
for (int i = 0; i < N; i++) {
- Entry entry = activeNotifications.get(i);
- boolean isChild = !isTopLevelChild(entry);
- if (isChild) {
+ View view = mStackScroller.getChildAt(i);
+ if (view.getVisibility() == View.GONE || !(view instanceof ExpandableNotificationRow)) {
continue;
}
- if (entry.row.getVisibility() != View.GONE &&
- mNotificationData.isAmbient(entry.key)) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+ if (mNotificationData.isAmbient(row.getStatusBarNotification().getKey())) {
speedbumpIndex = currentIndex;
break;
}
@@ -1990,7 +1991,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
}
- private int adjustDisableFlags(int state) {
+ protected int adjustDisableFlags(int state) {
if (!mLaunchTransitionFadingAway && !mKeyguardFadingAway
&& (mExpandedVisible || mBouncerShowing || mWaitingForKeyguardExit)) {
state |= StatusBarManager.DISABLE_NOTIFICATION_ICONS;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
index f61f31e814f7..a40aa8338d89 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarIconController.java
@@ -42,6 +42,7 @@ import com.android.systemui.BatteryMeterView;
import com.android.systemui.FontSizeUtils;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
+import com.android.systemui.SystemUIFactory;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.SignalClusterView;
import com.android.systemui.statusbar.StatusBarIconView;
@@ -116,8 +117,8 @@ public class StatusBarIconController extends StatusBarIconList implements Tunabl
mStatusIcons = (LinearLayout) statusBar.findViewById(R.id.statusIcons);
mSignalCluster = (SignalClusterView) statusBar.findViewById(R.id.signal_cluster);
- mNotificationIconAreaController =
- new NotificationIconAreaController(context, phoneStatusBar);
+ mNotificationIconAreaController = SystemUIFactory.getInstance()
+ .createNotificationIconAreaController(context, phoneStatusBar);
mNotificationIconAreaInner =
mNotificationIconAreaController.getNotificationInnerAreaView();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index ada745079fef..b271380e496c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -138,11 +138,7 @@ public class StatusBarWindowManager implements RemoteInputController.Callback {
mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
}
- if (state.remoteInputActive) {
- mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
- } else {
- mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
- }
+ mLpChanged.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
}
private void applyHeight(State state) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
index 3a0336bff905..1f4ef4a25f7f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/RemoteInputView.java
@@ -46,7 +46,7 @@ import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.RemoteInputController;
-import com.android.systemui.statusbar.stack.LongPressCancelable;
+import com.android.systemui.statusbar.stack.ScrollContainer;
/**
* Host for the remote input.
@@ -67,7 +67,9 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
private RemoteInputController mController;
private NotificationData.Entry mEntry;
- private LongPressCancelable mLongPressCancelable;
+
+ private ScrollContainer mScrollContainer;
+ private View mScrollContainerChild;
public RemoteInputView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -106,7 +108,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
mEditText.setOnClickListener(this);
mEditText.addTextChangedListener(this);
mEditText.setInnerFocusable(false);
- mEditText.mDefocusListener = this;
+ mEditText.mRemoteInputView = this;
}
private void sendRemoteInput() {
@@ -237,23 +239,34 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- if (mLongPressCancelable == null) {
- ViewParent p = getParent();
- while (p != null) {
- if (p instanceof LongPressCancelable) {
- mLongPressCancelable = (LongPressCancelable) p;
- break;
- }
- p = p.getParent();
- }
- }
- if (mLongPressCancelable != null) {
- mLongPressCancelable.requestDisallowLongPress();
+ findScrollContainer();
+ if (mScrollContainer != null) {
+ mScrollContainer.requestDisallowLongPress();
}
}
return super.onInterceptTouchEvent(ev);
}
+ public boolean requestScrollTo() {
+ findScrollContainer();
+ mScrollContainer.scrollTo(mScrollContainerChild);
+ return true;
+ }
+
+ private void findScrollContainer() {
+ if (mScrollContainer == null) {
+ ViewParent p = this;
+ while (p != null) {
+ if (p.getParent() instanceof ScrollContainer) {
+ mScrollContainer = (ScrollContainer) p.getParent();
+ mScrollContainerChild = (View) p;
+ break;
+ }
+ p = p.getParent();
+ }
+ }
+ }
+
/**
* An EditText that changes appearance based on whether it's focusable and becomes
* un-focusable whenever the user navigates away from it or it becomes invisible.
@@ -261,7 +274,7 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
public static class RemoteEditText extends EditText {
private final Drawable mBackground;
- private RemoteInputView mDefocusListener;
+ private RemoteInputView mRemoteInputView;
boolean mShowImeOnInputConnection;
public RemoteEditText(Context context, AttributeSet attrs) {
@@ -270,13 +283,13 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
}
private void defocusIfNeeded() {
- if (mDefocusListener.mEntry.row.isChangingPosition()) {
+ if (mRemoteInputView != null && mRemoteInputView.mEntry.row.isChangingPosition()) {
return;
}
if (isFocusable() && isEnabled()) {
setInnerFocusable(false);
- if (mDefocusListener != null) {
- mDefocusListener.onDefocus();
+ if (mRemoteInputView != null) {
+ mRemoteInputView.onDefocus();
}
mShowImeOnInputConnection = false;
}
@@ -300,17 +313,15 @@ public class RemoteInputView extends LinearLayout implements View.OnClickListene
}
@Override
- public boolean requestRectangleOnScreen(Rect r) {
+ public void getFocusedRect(Rect r) {
+ super.getFocusedRect(r);
r.top = mScrollY;
r.bottom = mScrollY + (mBottom - mTop);
- return super.requestRectangleOnScreen(r);
}
@Override
- public void getFocusedRect(Rect r) {
- super.getFocusedRect(r);
- r.top = mScrollY;
- r.bottom = mScrollY + (mBottom - mTop);
+ public boolean requestRectangleOnScreen(Rect rectangle) {
+ return mRemoteInputView.requestScrollTo();
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
index 676ff2ebc258..dc567fc20113 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationChildrenContainer.java
@@ -22,13 +22,14 @@ import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.TextView;
import com.android.systemui.R;
import com.android.systemui.ViewInvertHelper;
import com.android.systemui.statusbar.CrossFadeHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.HybridGroupManager;
import com.android.systemui.statusbar.notification.HybridNotificationView;
-import com.android.systemui.statusbar.notification.HybridNotificationViewManager;
import com.android.systemui.statusbar.notification.NotificationUtils;
import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -46,23 +47,22 @@ public class NotificationChildrenContainer extends ViewGroup {
private final List<View> mDividers = new ArrayList<>();
private final List<ExpandableNotificationRow> mChildren = new ArrayList<>();
- private final HybridNotificationViewManager mHybridViewManager;
+ private final HybridGroupManager mHybridGroupManager;
private int mChildPadding;
private int mDividerHeight;
private int mMaxNotificationHeight;
private int mNotificationHeaderHeight;
- private int mNotificationAppearDistance;
private int mNotificatonTopPadding;
private float mCollapsedBottompadding;
private ViewInvertHelper mOverflowInvertHelper;
private boolean mChildrenExpanded;
private ExpandableNotificationRow mNotificationParent;
- private HybridNotificationView mGroupOverflowContainer;
+ private TextView mOverflowNumber;
private ViewState mGroupOverFlowState;
private int mRealHeight;
- private int mLayoutDirection = LAYOUT_DIRECTION_UNDEFINED;
private boolean mUserLocked;
private int mActualHeight;
+ private boolean mNeverAppliedGroupState;
public NotificationChildrenContainer(Context context) {
this(context, null);
@@ -80,7 +80,7 @@ public class NotificationChildrenContainer extends ViewGroup {
int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initDimens();
- mHybridViewManager = new HybridNotificationViewManager(getContext(), this);
+ mHybridGroupManager = new HybridGroupManager(getContext(), this);
}
private void initDimens() {
@@ -90,8 +90,6 @@ public class NotificationChildrenContainer extends ViewGroup {
R.dimen.notification_divider_height));
mMaxNotificationHeight = getResources().getDimensionPixelSize(
R.dimen.notification_max_height);
- mNotificationAppearDistance = getResources().getDimensionPixelSize(
- R.dimen.notification_appear_distance);
mNotificationHeaderHeight = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.notification_content_margin_top);
mNotificatonTopPadding = getResources().getDimensionPixelSize(
@@ -108,12 +106,12 @@ public class NotificationChildrenContainer extends ViewGroup {
if (child.getVisibility() == View.GONE) {
continue;
}
- child.layout(0, 0, getWidth(), child.getMeasuredHeight());
+ child.layout(0, 0, child.getMeasuredWidth(), child.getMeasuredHeight());
mDividers.get(i).layout(0, 0, getWidth(), mDividerHeight);
}
- if (mGroupOverflowContainer != null) {
- mGroupOverflowContainer.layout(0, 0, getWidth(),
- mGroupOverflowContainer.getMeasuredHeight());
+ if (mOverflowNumber != null) {
+ mOverflowNumber.layout(getWidth() - mOverflowNumber.getMeasuredWidth(), 0, getWidth(),
+ mOverflowNumber.getMeasuredHeight());
}
}
@@ -128,11 +126,20 @@ public class NotificationChildrenContainer extends ViewGroup {
ownMaxHeight = Math.min(ownMaxHeight, size);
}
int newHeightSpec = MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.AT_MOST);
+ int width = MeasureSpec.getSize(widthMeasureSpec);
+ if (mOverflowNumber != null) {
+ mOverflowNumber.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
+ newHeightSpec);
+ }
int dividerHeightSpec = MeasureSpec.makeMeasureSpec(mDividerHeight, MeasureSpec.EXACTLY);
int height = mNotificationHeaderHeight + mNotificatonTopPadding;
int childCount = Math.min(mChildren.size(), NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED);
+ int collapsedChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
+ int overflowIndex = childCount > collapsedChildren ? collapsedChildren - 1 : -1;
for (int i = 0; i < childCount; i++) {
- View child = mChildren.get(i);
+ ExpandableNotificationRow child = mChildren.get(i);
+ boolean isOverflow = i == overflowIndex;
+ child.setSingleLineWidthIndention(isOverflow ? mOverflowNumber.getMeasuredWidth() : 0);
child.measure(widthMeasureSpec, newHeightSpec);
height += child.getMeasuredHeight();
@@ -141,10 +148,6 @@ public class NotificationChildrenContainer extends ViewGroup {
divider.measure(widthMeasureSpec, dividerHeightSpec);
height += mDividerHeight;
}
- int width = MeasureSpec.getSize(widthMeasureSpec);
- if (mGroupOverflowContainer != null) {
- mGroupOverflowContainer.measure(widthMeasureSpec, newHeightSpec);
- }
mRealHeight = height;
if (heightMode != MeasureSpec.UNSPECIFIED) {
height = Math.min(height, size);
@@ -200,22 +203,30 @@ public class NotificationChildrenContainer extends ViewGroup {
public void updateGroupOverflow() {
int childCount = mChildren.size();
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
- boolean hasOverflow = childCount > maxAllowedVisibleChildren;
- int lastVisibleIndex = hasOverflow ? maxAllowedVisibleChildren - 2
- : maxAllowedVisibleChildren - 1;
- if (hasOverflow) {
- mGroupOverflowContainer = mHybridViewManager.bindFromNotificationGroup(
- mGroupOverflowContainer, mChildren, lastVisibleIndex + 1);
+ if (childCount > maxAllowedVisibleChildren) {
+ mOverflowNumber = mHybridGroupManager.bindOverflowNumber(
+ mOverflowNumber, childCount - maxAllowedVisibleChildren);
if (mOverflowInvertHelper == null) {
- mOverflowInvertHelper= new ViewInvertHelper(mGroupOverflowContainer,
+ mOverflowInvertHelper= new ViewInvertHelper(mOverflowNumber,
NotificationPanelView.DOZE_ANIMATION_DURATION);
}
if (mGroupOverFlowState == null) {
mGroupOverFlowState = new ViewState();
+ mNeverAppliedGroupState = true;
}
- } else if (mGroupOverflowContainer != null) {
- removeView(mGroupOverflowContainer);
- mGroupOverflowContainer = null;
+ } else if (mOverflowNumber != null) {
+ removeView(mOverflowNumber);
+ if (isShown()) {
+ final View removedOverflowNumber = mOverflowNumber;
+ addTransientView(removedOverflowNumber, getTransientViewCount());
+ CrossFadeHelper.fadeOut(removedOverflowNumber, new Runnable() {
+ @Override
+ public void run() {
+ removeTransientView(removedOverflowNumber);
+ }
+ });
+ }
+ mOverflowNumber = null;
mOverflowInvertHelper = null;
mGroupOverFlowState = null;
}
@@ -224,11 +235,7 @@ public class NotificationChildrenContainer extends ViewGroup {
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- int layoutDirection = getLayoutDirection();
- if (layoutDirection != mLayoutDirection) {
- updateGroupOverflow();
- mLayoutDirection = layoutDirection;
- }
+ updateGroupOverflow();
}
private View inflateDivider() {
@@ -296,7 +303,7 @@ public class NotificationChildrenContainer extends ViewGroup {
boolean firstChild = true;
float expandFactor = 0;
if (mUserLocked) {
- expandFactor = getChildExpandFraction();
+ expandFactor = getGroupExpandFraction();
}
for (int i = 0; i < childCount; i++) {
if (visibleChildren >= maxAllowedVisibleChildren) {
@@ -346,14 +353,12 @@ public class NotificationChildrenContainer extends ViewGroup {
int yPosition = mNotificationHeaderHeight;
boolean firstChild = true;
int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren();
- boolean hasOverflow = !mChildrenExpanded && childCount > maxAllowedVisibleChildren
- && maxAllowedVisibleChildren != NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
- int lastVisibleIndex = hasOverflow
- ? maxAllowedVisibleChildren - 2
- : maxAllowedVisibleChildren - 1;
+ int lastVisibleIndex = maxAllowedVisibleChildren - 1;
+ int firstOverflowIndex = lastVisibleIndex + 1;
float expandFactor = 0;
if (mUserLocked) {
- expandFactor = getChildExpandFraction();
+ expandFactor = getGroupExpandFraction();
+ firstOverflowIndex = getMaxAllowedVisibleChildren(true /* likeCollapsed */);
}
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
@@ -386,19 +391,38 @@ public class NotificationChildrenContainer extends ViewGroup {
childState.belowSpeedBump = parentState.belowSpeedBump;
childState.clipTopAmount = 0;
childState.topOverLap = 0;
- boolean visible = i <= lastVisibleIndex;
- childState.alpha = visible ? 1 : 0;
+ childState.alpha = 0;
+ if (i < firstOverflowIndex) {
+ childState.alpha = 1;
+ } else if (expandFactor == 1.0f && i <= lastVisibleIndex) {
+ childState.alpha = (mActualHeight - childState.yTranslation) / childState.height;
+ childState.alpha = Math.max(0.0f, Math.min(1.0f, childState.alpha));
+ }
childState.location = parentState.location;
yPosition += intrinsicHeight;
}
- if (mGroupOverflowContainer != null) {
- mGroupOverFlowState.initFrom(mGroupOverflowContainer);
- if (hasOverflow) {
- StackViewState firstOverflowState =
- resultState.getViewStateForView(mChildren.get(lastVisibleIndex + 1));
- mGroupOverFlowState.yTranslation = firstOverflowState.yTranslation;
+ if (mOverflowNumber != null) {
+ ExpandableNotificationRow overflowView = mChildren.get(Math.min(
+ getMaxAllowedVisibleChildren(true /* likeCollpased */), childCount) - 1);
+ mGroupOverFlowState.copyFrom(resultState.getViewStateForView(overflowView));
+ if (!mChildrenExpanded) {
+ if (mUserLocked) {
+ HybridNotificationView singleLineView = overflowView.getSingleLineView();
+ View mirrorView = singleLineView.getTextView();
+ if (mirrorView.getVisibility() == GONE) {
+ mirrorView = singleLineView.getTitleView();
+ }
+ if (mirrorView.getVisibility() == GONE) {
+ mirrorView = singleLineView;
+ }
+ mGroupOverFlowState.yTranslation += NotificationUtils.getRelativeYOffset(
+ mirrorView, overflowView);
+ mGroupOverFlowState.alpha = mirrorView.getAlpha();
+ }
+ } else {
+ mGroupOverFlowState.yTranslation += mNotificationHeaderHeight;
+ mGroupOverFlowState.alpha = 0.0f;
}
- mGroupOverFlowState.alpha = mChildrenExpanded || !hasOverflow ? 0.0f : 1.0f;
}
}
@@ -410,7 +434,8 @@ public class NotificationChildrenContainer extends ViewGroup {
if (!likeCollapsed && (mChildrenExpanded || mNotificationParent.isUserLocked())) {
return NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED;
}
- if (mNotificationParent.isExpanded() || mNotificationParent.isHeadsUp()) {
+ if (!mNotificationParent.isOnKeyguard()
+ && (mNotificationParent.isExpanded() || mNotificationParent.isHeadsUp())) {
return NUMBER_OF_CHILDREN_WHEN_SYSTEM_EXPANDED;
}
return NUMBER_OF_CHILDREN_WHEN_COLLAPSED;
@@ -419,7 +444,10 @@ public class NotificationChildrenContainer extends ViewGroup {
public void applyState(StackScrollState state) {
int childCount = mChildren.size();
ViewState tmpState = new ViewState();
- float expandFraction = getChildExpandFraction();
+ float expandFraction = 0.0f;
+ if (mUserLocked) {
+ expandFraction = getGroupExpandFraction();
+ }
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
@@ -431,13 +459,17 @@ public class NotificationChildrenContainer extends ViewGroup {
tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
if (mUserLocked && viewState.alpha != 0) {
- alpha = NotificationUtils.interpolate(0, 0.5f, expandFraction);
+ alpha = NotificationUtils.interpolate(0, 0.5f,
+ Math.min(viewState.alpha, expandFraction));
}
tmpState.alpha = alpha;
state.applyViewState(divider, tmpState);
+ // There is no fake shadow to be drawn on the children
+ child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
}
- if (mGroupOverflowContainer != null) {
- state.applyViewState(mGroupOverflowContainer, mGroupOverFlowState);
+ if (mOverflowNumber != null) {
+ state.applyViewState(mOverflowNumber, mGroupOverFlowState);
+ mNeverAppliedGroupState = false;
}
}
@@ -456,7 +488,7 @@ public class NotificationChildrenContainer extends ViewGroup {
long baseDelay, long duration) {
int childCount = mChildren.size();
ViewState tmpState = new ViewState();
- float expandFraction = getChildExpandFraction();
+ float expandFraction = getGroupExpandFraction();
for (int i = childCount - 1; i >= 0; i--) {
ExpandableNotificationRow child = mChildren.get(i);
StackViewState viewState = state.getViewStateForView(child);
@@ -468,13 +500,23 @@ public class NotificationChildrenContainer extends ViewGroup {
tmpState.yTranslation = viewState.yTranslation - mDividerHeight;
float alpha = mChildrenExpanded && viewState.alpha != 0 ? 0.5f : 0;
if (mUserLocked && viewState.alpha != 0) {
- alpha = NotificationUtils.interpolate(0, 0.5f, expandFraction);
+ alpha = NotificationUtils.interpolate(0, 0.5f,
+ Math.min(viewState.alpha, expandFraction));
}
tmpState.alpha = alpha;
stateAnimator.startViewAnimations(divider, tmpState, baseDelay, duration);
- }
- if (mGroupOverflowContainer != null) {
- stateAnimator.startViewAnimations(mGroupOverflowContainer, mGroupOverFlowState,
+ // There is no fake shadow to be drawn on the children
+ child.setFakeShadowIntensity(0.0f, 0.0f, 0, 0);
+ }
+ if (mOverflowNumber != null) {
+ if (mNeverAppliedGroupState) {
+ float alpha = mGroupOverFlowState.alpha;
+ mGroupOverFlowState.alpha = 0;
+ state.applyViewState(mOverflowNumber, mGroupOverFlowState);
+ mGroupOverFlowState.alpha = alpha;
+ mNeverAppliedGroupState = false;
+ }
+ stateAnimator.startViewAnimations(mOverflowNumber, mGroupOverFlowState,
baseDelay, duration);
}
}
@@ -529,44 +571,49 @@ public class NotificationChildrenContainer extends ViewGroup {
return;
}
mActualHeight = actualHeight;
- float fraction = getChildExpandFraction();
+ float fraction = getGroupExpandFraction();
+ int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
int childCount = mChildren.size();
for (int i = 0; i < childCount; i++) {
ExpandableNotificationRow child = mChildren.get(i);
float childHeight = child.isExpanded(true /* allowOnKeyguard */)
? child.getMaxExpandHeight()
: child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
- float singleLineHeight = child.getShowingLayout().getMinHeight(
- false /* likeGroupExpanded */);
- child.setActualHeight((int) NotificationUtils.interpolate(singleLineHeight, childHeight,
- fraction), false);
+ if (i < maxAllowedVisibleChildren) {
+ float singleLineHeight = child.getShowingLayout().getMinHeight(
+ false /* likeGroupExpanded */);
+ child.setActualHeight((int) NotificationUtils.interpolate(singleLineHeight,
+ childHeight, fraction), false);
+ } else {
+ child.setActualHeight((int) childHeight, false);
+ }
}
}
- public float getChildExpandFraction() {
- int allChildrenVisibleHeight = getChildrenExpandStartHeight();
- int maxContentHeight = getMaxContentHeight();
- float factor = (mActualHeight - allChildrenVisibleHeight)
- / (float) (maxContentHeight - allChildrenVisibleHeight);
+ public float getGroupExpandFraction() {
+ int visibleChildrenExpandedHeight = getVisibleChildrenExpandHeight();
+ int minExpandHeight = getMinExpandHeight();
+ float factor = (mActualHeight - minExpandHeight)
+ / (float) (visibleChildrenExpandedHeight - minExpandHeight);
return Math.max(0.0f, Math.min(1.0f, factor));
}
- private int getChildrenExpandStartHeight() {
- int intrinsicHeight = mNotificationHeaderHeight;
+ private int getVisibleChildrenExpandHeight() {
+ int intrinsicHeight = mNotificationHeaderHeight + mNotificatonTopPadding + mDividerHeight;
int visibleChildren = 0;
int childCount = mChildren.size();
+ int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
for (int i = 0; i < childCount; i++) {
- if (visibleChildren >= NUMBER_OF_CHILDREN_WHEN_CHILDREN_EXPANDED) {
+ if (visibleChildren >= maxAllowedVisibleChildren) {
break;
}
ExpandableNotificationRow child = mChildren.get(i);
- intrinsicHeight += child.getMinHeight();
+ float childHeight = child.isExpanded(true /* allowOnKeyguard */)
+ ? child.getMaxExpandHeight()
+ : child.getShowingLayout().getMinHeight(true /* likeGroupExpanded */);
+ intrinsicHeight += childHeight;
visibleChildren++;
}
- if (visibleChildren > 0) {
- intrinsicHeight += (visibleChildren - 1) * mChildPadding;
- }
- intrinsicHeight += mCollapsedBottompadding;
return intrinsicHeight;
}
@@ -574,9 +621,8 @@ public class NotificationChildrenContainer extends ViewGroup {
return getIntrinsicHeight(NUMBER_OF_CHILDREN_WHEN_COLLAPSED);
}
- public int getMinExpandHeight(boolean onKeyguard) {
- int maxAllowedVisibleChildren = onKeyguard ? NUMBER_OF_CHILDREN_WHEN_COLLAPSED
- : getMaxAllowedVisibleChildren(true /* forceCollapsed */);
+ public int getMinExpandHeight() {
+ int maxAllowedVisibleChildren = getMaxAllowedVisibleChildren(true /* forceCollapsed */);
int minExpandHeight = mNotificationHeaderHeight;
int visibleChildren = 0;
boolean firstChild = true;
@@ -599,7 +645,7 @@ public class NotificationChildrenContainer extends ViewGroup {
}
public void setDark(boolean dark, boolean fade, long delay) {
- if (mGroupOverflowContainer != null) {
+ if (mOverflowNumber != null) {
mOverflowInvertHelper.setInverted(dark, fade, delay);
}
}
@@ -624,4 +670,9 @@ public class NotificationChildrenContainer extends ViewGroup {
child.setUserLocked(userLocked);
}
}
+
+ public void onNotificationUpdated() {
+ mHybridGroupManager.setOverflowNumberColor(mOverflowNumber,
+ mNotificationParent.getNotificationColor());
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 686a71211dc9..632ce2141573 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -43,6 +43,7 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
+import android.view.WindowInsets;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import android.widget.OverScroller;
@@ -83,7 +84,7 @@ import java.util.HashSet;
public class NotificationStackScrollLayout extends ViewGroup
implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
ExpandableView.OnHeightChangedListener, NotificationGroupManager.OnGroupChangeListener,
- SettingsIconRowListener, LongPressCancelable {
+ SettingsIconRowListener, ScrollContainer {
public static final float BACKGROUND_ALPHA_DIMMED = 0.7f;
private static final String TAG = "StackScroller";
@@ -134,7 +135,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private int mPaddingBetweenElements;
private int mIncreasedPaddingBetweenElements;
private int mTopPadding;
- private int mCollapseSecondCardPadding;
+ private int mBottomInset = 0;
/**
* The algorithm which calculates the properties for our children
@@ -206,6 +207,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private float mStackTranslation;
private float mTopPaddingOverflow;
private boolean mDontReportNextOverScroll;
+ private boolean mDontClampNextScroll;
private boolean mRequestViewResizeAnimationOnLayout;
private boolean mNeedViewResizeAnimation;
private View mExpandedGroupView;
@@ -694,11 +696,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mHeadsUpManager.addSwipedOutNotification(row.getStatusBarNotification().getKey());
}
}
- final View veto = v.findViewById(R.id.veto);
- if (veto != null && veto.getVisibility() != View.GONE) {
- veto.performClick();
- }
- if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
+ performDismiss(v);
mFalsingManager.onNotificationDismissed();
if (mFalsingManager.shouldEnforceBouncer()) {
@@ -707,6 +705,24 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ private void performDismiss(View v) {
+ if (v instanceof ExpandableNotificationRow) {
+ ExpandableNotificationRow row = (ExpandableNotificationRow) v;
+ if (mGroupManager.isOnlyChildInSuppressedGroup(row.getStatusBarNotification())) {
+ ExpandableNotificationRow groupSummary =
+ mGroupManager.getLogicalGroupSummary(row.getStatusBarNotification());
+ if (groupSummary.isClearable()) {
+ performDismiss(groupSummary);
+ }
+ }
+ }
+ final View veto = v.findViewById(R.id.veto);
+ if (veto != null && veto.getVisibility() != View.GONE) {
+ veto.performClick();
+ }
+ if (DEBUG) Log.v(TAG, "onChildDismissed: " + v);
+ }
+
@Override
public void onChildSnappedBack(View animView, float targetLeft) {
mAmbientState.onDragFinished(animView);
@@ -905,6 +921,45 @@ public class NotificationStackScrollLayout extends ViewGroup
mScrollingEnabled = enable;
}
+ public void scrollTo(View v) {
+ ExpandableView expandableView = (ExpandableView) v;
+ int positionInLinearLayout = getPositionInLinearLayout(v);
+
+ int targetScroll = positionInLinearLayout + expandableView.getActualHeight() +
+ mBottomInset - getHeight() + getTopPadding();
+ if (mOwnScrollY < targetScroll) {
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0, targetScroll - mOwnScrollY);
+ mDontReportNextOverScroll = true;
+ postInvalidateOnAnimation();
+ }
+ }
+
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets insets) {
+ mBottomInset = Math.max(0, insets.getSystemWindowInsetBottom()
+ - (getRootView().getHeight() - getHeight()));
+
+ int range = getScrollRange();
+ if (mOwnScrollY > range) {
+ // HACK: We're repeatedly getting staggered insets here while the IME is
+ // animating away. To work around that we'll wait until things have settled.
+ removeCallbacks(mReclamp);
+ postDelayed(mReclamp, 50);
+ }
+ return insets;
+ }
+
+ private Runnable mReclamp = new Runnable() {
+ @Override
+ public void run() {
+ int range = getScrollRange();
+ mScroller.startScroll(mScrollX, mOwnScrollY, 0, range - mOwnScrollY);
+ mDontReportNextOverScroll = true;
+ mDontClampNextScroll = true;
+ postInvalidateOnAnimation();
+ }
+ };
+
public void setExpandingEnabled(boolean enable) {
mExpandHelper.setEnabled(enable);
}
@@ -943,6 +998,11 @@ public class NotificationStackScrollLayout extends ViewGroup
mSwipeHelper.dismissChild(child, 0, endRunnable, delay, true, duration);
}
+ public void snapViewIfNeeded(View child) {
+ boolean animate = mIsExpanded || isPinnedHeadsUp(child);
+ mSwipeHelper.snapChildIfNeeded(child, animate);
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
@@ -1237,7 +1297,7 @@ public class NotificationStackScrollLayout extends ViewGroup
int y = mScroller.getCurrY();
if (oldX != x || oldY != y) {
- final int range = getScrollRange();
+ int range = getScrollRange();
if (y < 0 && oldY >= 0 || y > range && oldY <= range) {
float currVelocity = mScroller.getCurrVelocity();
if (currVelocity >= mMinimumVelocity) {
@@ -1245,6 +1305,9 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ if (mDontClampNextScroll) {
+ range = Math.max(range, oldY);
+ }
overScrollBy(x - oldX, y - oldY, oldX, oldY, 0, range,
0, (int) (mMaxOverScroll), false);
onScrollChanged(mScrollX, mOwnScrollY, oldX, oldY);
@@ -1252,6 +1315,8 @@ public class NotificationStackScrollLayout extends ViewGroup
// Keep on drawing until the animation has finished.
postInvalidateOnAnimation();
+ } else {
+ mDontClampNextScroll = false;
}
}
@@ -1455,7 +1520,9 @@ public class NotificationStackScrollLayout extends ViewGroup
- firstChild.getMinHeight());
}
}
- return scrollRange;
+ int imeOverlap = Math.max(0,
+ getContentHeight() - (getHeight() - mBottomInset));
+ return scrollRange + imeOverlap;
}
/**
@@ -3265,7 +3332,7 @@ public class NotificationStackScrollLayout extends ViewGroup
}
@Override
- public void onChildIsolationChanged() {
+ public void onGroupsChanged() {
mPhoneStatusBar.requestNotificationUpdate();
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
index 05f0c07574bb..a35465e85075 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/LongPressCancelable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/ScrollContainer.java
@@ -16,13 +16,21 @@
package com.android.systemui.statusbar.stack;
+import android.view.View;
+
/**
- * Interface for container layouts that listen for long presses. A child that
- * wants to handle long press can use this to cancel the parents long press logic.
+ * Interface for container layouts that scroll and listen for long presses. A child that
+ * wants to handle long press can use this to cancel the parents long press logic or request
+ * to be made visible by scrolling to it.
*/
-public interface LongPressCancelable {
+public interface ScrollContainer {
/**
* Request that the view does not perform long press for the current touch.
*/
void requestDisallowLongPress();
+
+ /**
+ * Request that the view is made visible by scrolling to it.
+ */
+ void scrollTo(View v);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index cf4802d70d15..dba5bbd27a7a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -972,10 +972,10 @@ public class StackStateAnimator {
}
/**
- * Get the end value of the height animation running on a view or the actualHeight
+ * Get the end value of the yTranslation animation running on a view or the yTranslation
* if no animation is running.
*/
- public static float getFinalTranslationY(ExpandableView view) {
+ public static float getFinalTranslationY(View view) {
if (view == null) {
return 0;
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
index 8db75344e483..acb1a7f21e78 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipManager.java
@@ -21,7 +21,6 @@ import android.app.ActivityManager.StackInfo;
import android.app.ActivityManagerNative;
import android.app.ActivityOptions;
import android.app.IActivityManager;
-import android.app.ITaskStackListener;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -38,6 +37,8 @@ import android.os.SystemProperties;
import android.util.Log;
import com.android.systemui.Prefs;
+import com.android.systemui.recents.misc.SystemServicesProxy;
+import com.android.systemui.recents.misc.SystemServicesProxy.TaskStackListener;
import java.util.ArrayList;
import java.util.List;
@@ -95,80 +96,6 @@ public class PipManager {
private boolean mIsRecentsShown;
private boolean mIsPipFocusedInRecent;
- private final Runnable mOnActivityPinnedRunnable = new Runnable() {
- @Override
- public void run() {
- StackInfo stackInfo = null;
- try {
- stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
- if (stackInfo == null) {
- Log.w(TAG, "Cannot find pinned stack");
- return;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "getStackInfo failed", e);
- return;
- }
- if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
- mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
- mPipComponentName = ComponentName.unflattenFromString(
- stackInfo.taskNames[stackInfo.taskNames.length - 1]);
- // Set state to overlay so we show it when the pinned stack animation ends.
- mState = STATE_PIP_OVERLAY;
- mCurrentPipBounds = mPipBounds;
- launchPipOnboardingActivityIfNeeded();
- mMediaSessionManager.addOnActiveSessionsChangedListener(
- mActiveMediaSessionListener, null);
- updateMediaController(mMediaSessionManager.getActiveSessions(null));
- }
- };
- private final Runnable mOnTaskStackChanged = new Runnable() {
- @Override
- public void run() {
- if (mState != STATE_NO_PIP) {
- StackInfo stackInfo = null;
- try {
- stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
- if (stackInfo == null) {
- Log.w(TAG, "There is no pinned stack");
- closePipInternal(false);
- return;
- }
- } catch (RemoteException e) {
- Log.e(TAG, "getStackInfo failed", e);
- return;
- }
- for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) {
- if (stackInfo.taskIds[i] == mPipTaskId) {
- // PIP task is still alive.
- return;
- }
- }
- // PIP task doesn't exist anymore in PINNED_STACK.
- closePipInternal(true);
- }
- }
- };
- private final Runnable mOnPinnedActivityRestartAttempt = new Runnable() {
- @Override
- public void run() {
- movePipToFullscreen();
- }
- };
- private final Runnable mOnPinnedStackAnimationEnded = new Runnable() {
- @Override
- public void run() {
- switch (mState) {
- case STATE_PIP_OVERLAY:
- showPipOverlay();
- break;
- case STATE_PIP_MENU:
- showPipMenu();
- break;
- }
- }
- };
-
private final Runnable mResizePinnedStackRunnable = new Runnable() {
@Override
public void run() {
@@ -232,13 +159,7 @@ public class PipManager {
(int) (mRecentsPipBounds.bottom + scaleBy * mRecentsPipBounds.height()));
mActivityManager = ActivityManagerNative.getDefault();
- TaskStackListener taskStackListener = new TaskStackListener();
- IActivityManager iam = ActivityManagerNative.getDefault();
- try {
- iam.registerTaskStackListener(taskStackListener);
- } catch (RemoteException e) {
- Log.e(TAG, "registerTaskStackListener failed", e);
- }
+ SystemServicesProxy.getInstance(context).registerTaskStackListener(mTaskStackListener);
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
mContext.registerReceiver(mBroadcastReceiver, intentFilter);
@@ -315,11 +236,7 @@ public class PipManager {
private void showPipOverlay() {
if (DEBUG) Log.d(TAG, "showPipOverlay()");
mState = STATE_PIP_OVERLAY;
- Intent intent = new Intent(mContext, PipOverlayActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- final ActivityOptions options = ActivityOptions.makeBasic();
- options.setLaunchStackId(PINNED_STACK_ID);
- mContext.startActivity(intent, options.toBundle());
+ PipOverlayActivity.showPipOverlay(mContext);
}
/**
@@ -387,7 +304,7 @@ public class PipManager {
try {
mActivityManager.resizeStack(PINNED_STACK_ID, mCurrentPipBounds, true, true, true, -1);
} catch (RemoteException e) {
- Log.e(TAG, "showPipMenu failed", e);
+ Log.e(TAG, "resizeStack failed", e);
}
}
@@ -485,17 +402,7 @@ public class PipManager {
* Returns {@code true} if PIP is shown.
*/
public boolean isPipShown() {
- return hasPipTasks();
- }
-
- private boolean hasPipTasks() {
- try {
- StackInfo stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
- return stackInfo != null;
- } catch (RemoteException e) {
- Log.e(TAG, "getStackInfo failed", e);
- return false;
- }
+ return mState != STATE_NO_PIP;
}
private void handleMediaResourceGranted(String[] packageNames) {
@@ -571,38 +478,100 @@ public class PipManager {
return mPipMediaController;
}
- private class TaskStackListener extends ITaskStackListener.Stub {
+ TaskStackListener mTaskStackListener = new TaskStackListener() {
@Override
- public void onTaskStackChanged() throws RemoteException {
- // Post the message back to the UI thread.
- mHandler.post(mOnTaskStackChanged);
+ public void onTaskStackChanged() {
+ if (mState != STATE_NO_PIP) {
+ StackInfo stackInfo = null;
+ try {
+ stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ if (stackInfo == null) {
+ Log.w(TAG, "There is no pinned stack");
+ closePipInternal(false);
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getStackInfo failed", e);
+ return;
+ }
+ for (int i = stackInfo.taskIds.length - 1; i >= 0; --i) {
+ if (stackInfo.taskIds[i] == mPipTaskId) {
+ // PIP task is still alive.
+ return;
+ }
+ }
+ // PIP task doesn't exist anymore in PINNED_STACK.
+ closePipInternal(true);
+ }
}
@Override
- public void onActivityPinned() throws RemoteException {
- // Post the message back to the UI thread.
+ public void onActivityPinned() {
if (DEBUG) Log.d(TAG, "onActivityPinned()");
- mHandler.post(mOnActivityPinnedRunnable);
+ StackInfo stackInfo = null;
+ try {
+ stackInfo = mActivityManager.getStackInfo(PINNED_STACK_ID);
+ if (stackInfo == null) {
+ Log.w(TAG, "Cannot find pinned stack");
+ return;
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "getStackInfo failed", e);
+ return;
+ }
+ if (DEBUG) Log.d(TAG, "PINNED_STACK:" + stackInfo);
+ mPipTaskId = stackInfo.taskIds[stackInfo.taskIds.length - 1];
+ mPipComponentName = ComponentName.unflattenFromString(
+ stackInfo.taskNames[stackInfo.taskNames.length - 1]);
+ // Set state to overlay so we show it when the pinned stack animation ends.
+ mState = STATE_PIP_OVERLAY;
+ mCurrentPipBounds = mPipBounds;
+ launchPipOnboardingActivityIfNeeded();
+ mMediaSessionManager.addOnActiveSessionsChangedListener(
+ mActiveMediaSessionListener, null);
+ updateMediaController(mMediaSessionManager.getActiveSessions(null));
+ if (mIsRecentsShown) {
+ // If an activity becomes PIPed again after the fullscreen, the Recents is shown
+ // behind so we need to resize the pinned stack and show the correct overlay.
+ resizePinnedStack(STATE_PIP_OVERLAY);
+ }
+ for (int i = mListeners.size() - 1; i >= 0; i--) {
+ mListeners.get(i).onPipEntered();
+ }
}
@Override
public void onPinnedActivityRestartAttempt() {
- // Post the message back to the UI thread.
if (DEBUG) Log.d(TAG, "onPinnedActivityRestartAttempt()");
- mHandler.post(mOnPinnedActivityRestartAttempt);
+ // If PIPed activity is launched again by Launcher or intent, make it fullscreen.
+ movePipToFullscreen();
}
@Override
public void onPinnedStackAnimationEnded() {
if (DEBUG) Log.d(TAG, "onPinnedStackAnimationEnded()");
- mHandler.post(mOnPinnedStackAnimationEnded);
+ switch (mState) {
+ case STATE_PIP_OVERLAY:
+ showPipOverlay();
+ break;
+ case STATE_PIP_MENU:
+ showPipMenu();
+ break;
+ }
}
- }
+ };
/**
* A listener interface to receive notification on changes in PIP.
*/
public interface Listener {
+ /**
+ * Invoked when an activity is pinned and PIP manager is set corresponding information.
+ * Classes must use this instead of {@link android.app.ITaskStackListener.onActivityPinned}
+ * because there's no guarantee for the PIP manager be return relavent information
+ * correctly. (e.g. {@link isPipShown}, {@link getPipBounds})
+ */
+ void onPipEntered();
/** Invoked when a PIPed activity is closed. */
void onPipActivityClosed();
/** Invoked when the PIP menu gets shown. */
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
index 285dfd1f9318..b8b837a0cb84 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipMenuActivity.java
@@ -198,6 +198,9 @@ public class PipMenuActivity extends Activity implements PipManager.Listener {
}
@Override
+ public void onPipEntered() { }
+
+ @Override
public void onPipActivityClosed() {
finish();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
index ad45625b0f9c..79daf3d51056 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOnboardingActivity.java
@@ -67,6 +67,9 @@ public class PipOnboardingActivity extends Activity implements PipManager.Listen
}
@Override
+ public void onPipEntered() { }
+
+ @Override
public void onPipActivityClosed() {
finish();
}
diff --git a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
index 95d655c2f320..1de321dd1004 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/pip/PipOverlayActivity.java
@@ -17,21 +17,31 @@
package com.android.systemui.tv.pip;
import android.app.Activity;
+import android.app.ActivityOptions;
+import android.content.Context;
+import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import com.android.systemui.R;
+import static android.app.ActivityManager.StackId.PINNED_STACK_ID;
+
/**
* Activity to show an overlay on top of PIP activity to show how to pop up PIP menu.
*/
public class PipOverlayActivity extends Activity implements PipManager.Listener {
- private static final String TAG = "PipOverlayActivity";
- private static final boolean DEBUG = false;
-
private static final long SHOW_GUIDE_OVERLAY_VIEW_DURATION_MS = 4000;
+ /**
+ * The single instance of PipOverlayActivity to prevent it from restarting.
+ * Note that {@link PipManager} moves the PIPed activity to fullscreen if the activity is
+ * restarted. It's because the activity may be started by the Launcher or an intent again,
+ * but we don't want do so for the PipOverlayActivity.
+ */
+ private static PipOverlayActivity sPipOverlayActivity;
+
private final PipManager mPipManager = PipManager.getInstance();
private final Handler mHandler = new Handler();
private View mGuideOverlayView;
@@ -42,6 +52,19 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
}
};
+ /**
+ * Launches the PIP overlay. This should be only called on the main thread.
+ */
+ public static void showPipOverlay(Context context) {
+ if (sPipOverlayActivity == null) {
+ Intent intent = new Intent(context, PipOverlayActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ final ActivityOptions options = ActivityOptions.makeBasic();
+ options.setLaunchStackId(PINNED_STACK_ID);
+ context.startActivity(intent, options.toBundle());
+ }
+ }
+
@Override
protected void onCreate(Bundle bundle) {
super.onCreate(bundle);
@@ -49,6 +72,8 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
mGuideOverlayView = findViewById(R.id.guide_overlay);
mGuideButtonsView = findViewById(R.id.guide_buttons);
mPipManager.addListener(this);
+
+ sPipOverlayActivity = this;
}
@Override
@@ -76,6 +101,7 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
@Override
protected void onDestroy() {
super.onDestroy();
+ sPipOverlayActivity = null;
mHandler.removeCallbacksAndMessages(null);
mPipManager.removeListener(this);
mPipManager.resumePipResizing(
@@ -83,6 +109,9 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
}
@Override
+ public void onPipEntered() { }
+
+ @Override
public void onPipActivityClosed() {
finish();
}
@@ -105,6 +134,11 @@ public class PipOverlayActivity extends Activity implements PipManager.Listener
}
@Override
- public void onMediaControllerChanged() {
+ public void onMediaControllerChanged() { }
+
+ @Override
+ public void finish() {
+ sPipOverlayActivity = null;
+ super.finish();
}
}
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index d929519bddff..d6f1499ef684 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -1922,10 +1922,12 @@ message MetricsEvent {
// User granted access to the request folder; action takes an integer
// representing the folder's index on Environment.STANDARD_DIRECTORIES
+ // (or -2 for root access, or -1 or unknown directory).
ACTION_SCOPED_DIRECTORY_ACCESS_GRANTED_BY_FOLDER = 326;
// User denied access to the request folder; action takes an integer
// representing the folder's index on Environment.STANDARD_DIRECTORIES
+ // (or -2 for root access, or -1 or unknown directory).
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_BY_FOLDER = 327;
// User granted access to the request folder; action pass package name
@@ -1939,6 +1941,7 @@ message MetricsEvent {
// App requested access to a directory it has already been granted
// access before; action takes an integer representing the folder's
// index on Environment.STANDARD_DIRECTORIES
+ // (or -2 for root access, or -1 or unknown directory).
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_GRANTED_BY_FOLDER = 330;
// App requested access to a directory it has already been granted
@@ -1998,6 +2001,7 @@ message MetricsEvent {
// User already denied access to the request folder; action takes an integer
// representing the folder's index on Environment.STANDARD_DIRECTORIES
+ // (or -2 for root access, or -1 or unknown directory).
ACTION_SCOPED_DIRECTORY_ACCESS_ALREADY_DENIED_BY_FOLDER = 353;
// User already denied access to the request folder; action pass package name
@@ -2006,6 +2010,7 @@ message MetricsEvent {
// User denied access to the request folder and checked 'Do not ask again';
// action takes an integer representing the folder's index on Environment.STANDARD_DIRECTORIES
+ // (or -2 for root access, or -1 or unknown directory).
ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_FOLDER = 355;
// User denied access to the request folder and checked 'Do not ask again';
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 425569cd8fa1..9beaba301072 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -1387,6 +1387,27 @@ public class RenderScript {
}
/**
+ * Name of the file that holds the object cache.
+ */
+ private static String mCachePath;
+
+ /**
+ * Gets the path to the code cache.
+ */
+ static synchronized String getCachePath() {
+ if (mCachePath == null) {
+ final String CACHE_PATH = "com.android.renderscript.cache";
+ if (RenderScriptCacheDir.mCacheDir == null) {
+ throw new RSRuntimeException("RenderScript code cache directory uninitialized.");
+ }
+ File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
+ mCachePath = f.getAbsolutePath();
+ f.mkdirs();
+ }
+ return mCachePath;
+ }
+
+ /**
* Create a RenderScript context.
*
* @param ctx The context.
@@ -1415,11 +1436,7 @@ public class RenderScript {
}
// set up cache directory for entire context
- final String CACHE_PATH = "com.android.renderscript.cache";
- File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
- String mCachePath = f.getAbsolutePath();
- f.mkdirs();
- rs.nContextSetCacheDir(mCachePath);
+ rs.nContextSetCacheDir(RenderScript.getCachePath());
rs.mMessageThread = new MessageThread(rs);
rs.mMessageThread.start();
diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index bf706c131e85..00ebe5756589 100644
--- a/rs/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -84,13 +84,6 @@ public class ScriptC extends Script {
setID(id);
}
- /**
- * Name of the file that holds the object cache.
- */
- private static final String CACHE_PATH = "com.android.renderscript.cache";
-
- static String mCachePath;
-
private static synchronized long internalCreate(RenderScript rs, Resources resources, int resourceID) {
byte[] pgm;
int pgmLength;
@@ -122,26 +115,12 @@ public class ScriptC extends Script {
String resName = resources.getResourceEntryName(resourceID);
- // Create the RS cache path if we haven't done so already.
- if (mCachePath == null) {
- File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
- mCachePath = f.getAbsolutePath();
- f.mkdirs();
- }
// Log.v(TAG, "Create script for resource = " + resName);
- return rs.nScriptCCreate(resName, mCachePath, pgm, pgmLength);
+ return rs.nScriptCCreate(resName, RenderScript.getCachePath(), pgm, pgmLength);
}
private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) {
- // Create the RS cache path if we haven't done so already.
- if (mCachePath == null) {
- File f = new File(RenderScriptCacheDir.mCacheDir, CACHE_PATH);
- mCachePath = f.getAbsolutePath();
- f.mkdirs();
- }
// Log.v(TAG, "Create script for resource = " + resName);
- return rs.nScriptCCreate(resName, mCachePath, bitcode, bitcode.length);
+ return rs.nScriptCCreate(resName, RenderScript.getCachePath(), bitcode, bitcode.length);
}
-
-
}
diff --git a/rs/java/android/renderscript/ScriptGroup.java b/rs/java/android/renderscript/ScriptGroup.java
index 9bbacbc0d84c..9357c3bb0428 100644
--- a/rs/java/android/renderscript/ScriptGroup.java
+++ b/rs/java/android/renderscript/ScriptGroup.java
@@ -396,7 +396,7 @@ public final class ScriptGroup extends BaseObj {
for (int i = 0; i < closureIDs.length; i++) {
closureIDs[i] = closures.get(i).getID(rs);
}
- long id = rs.nScriptGroup2Create(name, ScriptC.mCachePath, closureIDs);
+ long id = rs.nScriptGroup2Create(name, RenderScript.getCachePath(), closureIDs);
setID(id);
}
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index c810e6c89c9f..e710dedd31fe 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1549,7 +1549,7 @@ public class AccessibilityManagerService extends IAccessibilityManager.Stub {
try {
Settings.Secure.putIntForUser(mContext.getContentResolver(),
Settings.Secure.ACCESSIBILITY_ENABLED,
- userState.isHandlingAccessibilityEvents() ? 0 : 1,
+ userState.isHandlingAccessibilityEvents() ? 1 : 0,
userState.mUserId);
} finally {
Binder.restoreCallingIdentity(identity);
diff --git a/services/core/java/com/android/server/AppOpsService.java b/services/core/java/com/android/server/AppOpsService.java
index a94c8b8ebb31..e7db2a87c865 100644
--- a/services/core/java/com/android/server/AppOpsService.java
+++ b/services/core/java/com/android/server/AppOpsService.java
@@ -447,12 +447,8 @@ public class AppOpsService extends IAppOpsService.Stub {
int[] ops) {
mContext.enforcePermission(android.Manifest.permission.GET_APP_OPS_STATS,
Binder.getCallingPid(), Binder.getCallingUid(), null);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return Collections.emptyList();
- }
synchronized (this) {
- Ops pkgOps = getOpsRawLocked(uid, resolvedPackageName, false);
+ Ops pkgOps = getOpsLocked(uid, packageName, false);
if (pkgOps == null) {
return null;
}
@@ -470,7 +466,7 @@ public class AppOpsService extends IAppOpsService.Stub {
private void pruneOp(Op op, int uid, String packageName) {
if (op.time == 0 && op.rejectTime == 0) {
- Ops ops = getOpsRawLocked(uid, packageName, false);
+ Ops ops = getOpsLocked(uid, packageName, false);
if (ops != null) {
ops.remove(op.op);
if (ops.size() <= 0) {
@@ -884,12 +880,8 @@ public class AppOpsService extends IAppOpsService.Stub {
public int checkOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
synchronized (this) {
- if (isOpRestricted(uid, code, resolvedPackageName)) {
+ if (isOpRestricted(uid, code, packageName)) {
return AppOpsManager.MODE_IGNORED;
}
code = AppOpsManager.opToSwitch(code);
@@ -900,7 +892,7 @@ public class AppOpsService extends IAppOpsService.Stub {
return uidMode;
}
}
- Op op = getOpLocked(code, uid, resolvedPackageName, false);
+ Op op = getOpLocked(code, uid, packageName, false);
if (op == null) {
return AppOpsManager.opToDefaultMode(code);
}
@@ -976,7 +968,6 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int checkPackage(int uid, String packageName) {
- Preconditions.checkNotNull(packageName);
synchronized (this) {
if (getOpsRawLocked(uid, packageName, true) != null) {
return AppOpsManager.MODE_ALLOWED;
@@ -990,39 +981,26 @@ public class AppOpsService extends IAppOpsService.Stub {
public int noteProxyOperation(int code, String proxyPackageName,
int proxiedUid, String proxiedPackageName) {
verifyIncomingOp(code);
- final int proxyUid = Binder.getCallingUid();
- String resolveProxyPackageName = resolvePackageName(proxyUid, proxyPackageName);
- if (resolveProxyPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
- final int proxyMode = noteOperationUnchecked(code, proxyUid,
- resolveProxyPackageName, -1, null);
+ final int proxyMode = noteOperationUnchecked(code, Binder.getCallingUid(),
+ proxyPackageName, -1, null);
if (proxyMode != AppOpsManager.MODE_ALLOWED || Binder.getCallingUid() == proxiedUid) {
return proxyMode;
}
- String resolveProxiedPackageName = resolvePackageName(proxiedUid, proxiedPackageName);
- if (resolveProxiedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
- return noteOperationUnchecked(code, proxiedUid, resolveProxiedPackageName,
- proxyMode, resolveProxyPackageName);
+ return noteOperationUnchecked(code, proxiedUid, proxiedPackageName,
+ Binder.getCallingUid(), proxyPackageName);
}
@Override
public int noteOperation(int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
- return noteOperationUnchecked(code, uid, resolvedPackageName, 0, null);
+ return noteOperationUnchecked(code, uid, packageName, 0, null);
}
private int noteOperationUnchecked(int code, int uid, String packageName,
int proxyUid, String proxyPackageName) {
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true);
+ Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
if (DEBUG) Log.d(TAG, "noteOperation: no op for code " + code + " uid " + uid
+ " package " + packageName);
@@ -1070,20 +1048,16 @@ public class AppOpsService extends IAppOpsService.Stub {
public int startOperation(IBinder token, int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return AppOpsManager.MODE_IGNORED;
- }
ClientState client = (ClientState)token;
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, resolvedPackageName, true);
+ Ops ops = getOpsLocked(uid, packageName, true);
if (ops == null) {
if (DEBUG) Log.d(TAG, "startOperation: no op for code " + code + " uid " + uid
- + " package " + resolvedPackageName);
+ + " package " + packageName);
return AppOpsManager.MODE_ERRORED;
}
Op op = getOpLocked(ops, code, true);
- if (isOpRestricted(uid, code, resolvedPackageName)) {
+ if (isOpRestricted(uid, code, packageName)) {
return AppOpsManager.MODE_IGNORED;
}
final int switchCode = AppOpsManager.opToSwitch(code);
@@ -1093,7 +1067,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (uidMode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "noteOperation: reject #" + op.mode + " for code "
+ switchCode + " (" + code + ") uid " + uid + " package "
- + resolvedPackageName);
+ + packageName);
op.rejectTime = System.currentTimeMillis();
return uidMode;
}
@@ -1101,13 +1075,12 @@ public class AppOpsService extends IAppOpsService.Stub {
final Op switchOp = switchCode != code ? getOpLocked(ops, switchCode, true) : op;
if (switchOp.mode != AppOpsManager.MODE_ALLOWED) {
if (DEBUG) Log.d(TAG, "startOperation: reject #" + op.mode + " for code "
- + switchCode + " (" + code + ") uid " + uid + " package "
- + resolvedPackageName);
+ + switchCode + " (" + code + ") uid " + uid + " package " + packageName);
op.rejectTime = System.currentTimeMillis();
return switchOp.mode;
}
if (DEBUG) Log.d(TAG, "startOperation: allowing code " + code + " uid " + uid
- + " package " + resolvedPackageName);
+ + " package " + packageName);
if (op.nesting == 0) {
op.time = System.currentTimeMillis();
op.rejectTime = 0;
@@ -1125,16 +1098,9 @@ public class AppOpsService extends IAppOpsService.Stub {
public void finishOperation(IBinder token, int code, int uid, String packageName) {
verifyIncomingUid(uid);
verifyIncomingOp(code);
- String resolvedPackageName = resolvePackageName(uid, packageName);
- if (resolvedPackageName == null) {
- return;
- }
- if (!(token instanceof ClientState)) {
- return;
- }
- ClientState client = (ClientState) token;
+ ClientState client = (ClientState)token;
synchronized (this) {
- Op op = getOpLocked(code, uid, resolvedPackageName, true);
+ Op op = getOpLocked(code, uid, packageName, true);
if (op == null) {
return;
}
@@ -1150,9 +1116,6 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public int permissionToOpCode(String permission) {
- if (permission == null) {
- return AppOpsManager.OP_NONE;
- }
return AppOpsManager.permissionToOpCode(permission);
}
@@ -1202,6 +1165,15 @@ public class AppOpsService extends IAppOpsService.Stub {
return uidState;
}
+ private Ops getOpsLocked(int uid, String packageName, boolean edit) {
+ if (uid == 0) {
+ packageName = "root";
+ } else if (uid == Process.SHELL_UID) {
+ packageName = "com.android.shell";
+ }
+ return getOpsRawLocked(uid, packageName, edit);
+ }
+
private Ops getOpsRawLocked(int uid, String packageName, boolean edit) {
UidState uidState = getUidStateLocked(uid, edit);
if (uidState == null) {
@@ -1287,7 +1259,7 @@ public class AppOpsService extends IAppOpsService.Stub {
}
private Op getOpLocked(int code, int uid, String packageName, boolean edit) {
- Ops ops = getOpsRawLocked(uid, packageName, edit);
+ Ops ops = getOpsLocked(uid, packageName, edit);
if (ops == null) {
return null;
}
@@ -1345,7 +1317,7 @@ public class AppOpsService extends IAppOpsService.Stub {
if (AppOpsManager.opAllowSystemBypassRestriction(code)) {
// If we are the system, bypass user restrictions for certain codes
synchronized (this) {
- Ops ops = getOpsRawLocked(uid, packageName, true);
+ Ops ops = getOpsLocked(uid, packageName, true);
if ((ops != null) && ops.isPrivileged) {
return false;
}
@@ -1610,7 +1582,7 @@ public class AppOpsService extends IAppOpsService.Stub {
out.startTag(null, "uid");
out.attribute(null, "n", Integer.toString(pkg.getUid()));
synchronized (this) {
- Ops ops = getOpsRawLocked(pkg.getUid(), pkg.getPackageName(), false);
+ Ops ops = getOpsLocked(pkg.getUid(), pkg.getPackageName(), false);
// Should always be present as the list of PackageOps is generated
// from Ops.
if (ops != null) {
@@ -2131,7 +2103,6 @@ public class AppOpsService extends IAppOpsService.Stub {
@Override
public void setUserRestrictions(Bundle restrictions, IBinder token, int userHandle) {
checkSystemUid("setUserRestrictions");
- Preconditions.checkNotNull(restrictions);
Preconditions.checkNotNull(token);
final boolean[] opRestrictions = getOrCreateUserRestrictionsForToken(token, userHandle);
for (int i = 0; i < opRestrictions.length; ++i) {
@@ -2346,15 +2317,6 @@ public class AppOpsService extends IAppOpsService.Stub {
}
}
- private static String resolvePackageName(int uid, String packageName) {
- if (uid == 0) {
- return "root";
- } else if (uid == Process.SHELL_UID) {
- return "com.android.shell";
- }
- return packageName;
- }
-
private static String[] getPackagesForUid(int uid) {
String[] packageNames = null;
try {
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index b7fca1a10ffc..b1398f17c13c 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -630,7 +630,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mDefaultRequest = createInternetRequestForTransport(-1);
NetworkRequestInfo defaultNRI = new NetworkRequestInfo(null, mDefaultRequest,
- new Binder(), NetworkRequestInfo.REQUEST);
+ new Binder(), NetworkRequestType.REQUEST);
mNetworkRequests.put(mDefaultRequest, defaultNRI);
mNetworkRequestInfoLogs.log("REGISTER " + defaultNRI);
@@ -806,7 +806,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (enable) {
handleRegisterNetworkRequest(new NetworkRequestInfo(
- null, mDefaultMobileDataRequest, new Binder(), NetworkRequestInfo.REQUEST));
+ null, mDefaultMobileDataRequest, new Binder(), NetworkRequestType.REQUEST));
} else {
handleReleaseNetworkRequest(mDefaultMobileDataRequest, Process.SYSTEM_UID);
}
@@ -1945,7 +1945,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
private boolean isRequest(NetworkRequest request) {
- return mNetworkRequests.get(request).isRequest;
+ return mNetworkRequests.get(request).isRequest();
}
// must be stateless - things change under us.
@@ -2164,7 +2164,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (VDBG) log("NetworkFactory connected");
// A network factory has connected. Send it all current NetworkRequests.
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
- if (nri.isRequest == false) continue;
+ if (!nri.isRequest()) continue;
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
(nai != null ? nai.getCurrentScore() : 0), 0, nri.request);
@@ -2301,7 +2301,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
mNetworkRequests.put(nri.request, nri);
mNetworkRequestInfoLogs.log("REGISTER " + nri);
- if (!nri.isRequest) {
+ if (!nri.isRequest()) {
for (NetworkAgentInfo network : mNetworkAgentInfos.values()) {
if (nri.request.networkCapabilities.hasSignalStrength() &&
network.satisfiesImmutableCapabilitiesOf(nri.request)) {
@@ -2310,7 +2310,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
rematchAllNetworksAndRequests(null, 0);
- if (nri.isRequest && mNetworkForRequestId.get(nri.request.requestId) == null) {
+ if (nri.isRequest() && mNetworkForRequestId.get(nri.request.requestId) == null) {
sendUpdatedScoreToFactories(nri.request, 0);
}
}
@@ -2331,7 +2331,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
// If this Network is already the highest scoring Network for a request, or if
// there is hope for it to become one if it validated, then it is needed.
- if (nri.isRequest && nai.satisfies(nri.request) &&
+ if (nri.isRequest() && nai.satisfies(nri.request) &&
(nai.networkRequests.get(nri.request.requestId) != null ||
// Note that this catches two important cases:
// 1. Unvalidated cellular will not be reaped when unvalidated WiFi
@@ -2359,7 +2359,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
nri.unlinkDeathRecipient();
mNetworkRequests.remove(request);
mNetworkRequestInfoLogs.log("RELEASE " + nri);
- if (nri.isRequest) {
+ if (nri.isRequest()) {
// Find all networks that are satisfying this request and remove the request
// from their request lists.
// TODO - it's my understanding that for a request there is only a single
@@ -3736,13 +3736,36 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
/**
+ * A NetworkRequest as registered by an application can be one of three
+ * types:
+ *
+ * - "listen", for which the framework will issue callbacks about any
+ * and all networks that match the specified NetworkCapabilities,
+ *
+ * - "request", capable of causing a specific network to be created
+ * first (e.g. a telephony DUN request), the framework will issue
+ * callbacks about the single, highest scoring current network
+ * (if any) that matches the specified NetworkCapabilities, or
+ *
+ * - "track the default network", a hybrid of the two designed such
+ * that the framework will issue callbacks for the single, highest
+ * scoring current network (if any) that matches the capabilities of
+ * the default Internet request (mDefaultRequest), but which cannot
+ * cause the framework to either create or retain the existence of
+ * any specific network.
+ *
+ */
+ private static enum NetworkRequestType {
+ LISTEN,
+ TRACK_DEFAULT,
+ REQUEST
+ };
+
+ /**
* Tracks info about the requester.
* Also used to notice when the calling process dies so we can self-expire
*/
private class NetworkRequestInfo implements IBinder.DeathRecipient {
- static final boolean REQUEST = true;
- static final boolean LISTEN = false;
-
final NetworkRequest request;
final PendingIntent mPendingIntent;
boolean mPendingIntentSent;
@@ -3750,26 +3773,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int mPid;
final int mUid;
final Messenger messenger;
- final boolean isRequest;
+ private final NetworkRequestType mType;
- NetworkRequestInfo(NetworkRequest r, PendingIntent pi, boolean isRequest) {
+ NetworkRequestInfo(NetworkRequest r, PendingIntent pi, NetworkRequestType type) {
request = r;
mPendingIntent = pi;
messenger = null;
mBinder = null;
mPid = getCallingPid();
mUid = getCallingUid();
- this.isRequest = isRequest;
+ mType = type;
}
- NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, boolean isRequest) {
+ NetworkRequestInfo(Messenger m, NetworkRequest r, IBinder binder, NetworkRequestType type) {
super();
messenger = m;
request = r;
mBinder = binder;
mPid = getCallingPid();
mUid = getCallingUid();
- this.isRequest = isRequest;
+ mType = type;
mPendingIntent = null;
try {
@@ -3779,6 +3802,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ private String typeString() {
+ switch (mType) {
+ case LISTEN: return "Listen";
+ case REQUEST: return "Request";
+ case TRACK_DEFAULT: return "Track default";
+ default:
+ return "unknown type";
+ }
+ }
+
void unlinkDeathRecipient() {
if (mBinder != null) {
mBinder.unlinkToDeath(this, 0);
@@ -3791,8 +3824,27 @@ public class ConnectivityService extends IConnectivityManager.Stub
releaseNetworkRequest(request);
}
+ /**
+ * Returns true iff. the contained NetworkRequest is one that:
+ *
+ * - should be associated with at most one satisfying network
+ * at a time;
+ *
+ * - should cause a network to be kept up if it is the only network
+ * which can satisfy the NetworkReqeust.
+ *
+ * For full detail of how isRequest() is used for pairing Networks with
+ * NetworkRequests read rematchNetworkAndRequests().
+ *
+ * TODO: Rename to something more properly descriptive.
+ */
+ public boolean isRequest() {
+ return (mType == NetworkRequestType.TRACK_DEFAULT) ||
+ (mType == NetworkRequestType.REQUEST);
+ }
+
public String toString() {
- return (isRequest ? "Request" : "Listen") +
+ return typeString() +
" from uid/pid:" + mUid + "/" + mPid +
" for " + request +
(mPendingIntent == null ? "" : " to trigger " + mPendingIntent);
@@ -3845,8 +3897,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
Messenger messenger, int timeoutMs, IBinder binder, int legacyType) {
- networkCapabilities = new NetworkCapabilities(networkCapabilities);
- enforceNetworkRequestPermissions(networkCapabilities);
+ final NetworkRequestType type = (networkCapabilities == null)
+ ? NetworkRequestType.TRACK_DEFAULT
+ : NetworkRequestType.REQUEST;
+ // If the requested networkCapabilities is null, take them instead from
+ // the default network request. This allows callers to keep track of
+ // the system default network.
+ if (type == NetworkRequestType.TRACK_DEFAULT) {
+ networkCapabilities = new NetworkCapabilities(mDefaultRequest.networkCapabilities);
+ enforceAccessPermission();
+ } else {
+ networkCapabilities = new NetworkCapabilities(networkCapabilities);
+ enforceNetworkRequestPermissions(networkCapabilities);
+ }
enforceMeteredApnPolicy(networkCapabilities);
ensureRequestableCapabilities(networkCapabilities);
@@ -3862,8 +3925,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, legacyType,
nextNetworkRequestId());
- NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
- NetworkRequestInfo.REQUEST);
+ NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder, type);
if (DBG) log("requestNetwork for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST, nri));
@@ -3928,7 +3990,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequest networkRequest = new NetworkRequest(networkCapabilities, TYPE_NONE,
nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
- NetworkRequestInfo.REQUEST);
+ NetworkRequestType.REQUEST);
if (DBG) log("pendingRequest for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_REQUEST_WITH_INTENT,
nri));
@@ -3980,7 +4042,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequest networkRequest = new NetworkRequest(
new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
- NetworkRequestInfo.LISTEN);
+ NetworkRequestType.LISTEN);
if (DBG) log("listenForNetwork for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
@@ -3998,7 +4060,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkRequest networkRequest = new NetworkRequest(
new NetworkCapabilities(networkCapabilities), TYPE_NONE, nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(networkRequest, operation,
- NetworkRequestInfo.LISTEN);
+ NetworkRequestType.LISTEN);
if (DBG) log("pendingListenForNetwork for " + nri);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_LISTENER, nri));
@@ -4515,7 +4577,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// check if it satisfies the NetworkCapabilities
if (VDBG) log(" checking if request is satisfied: " + nri.request);
if (satisfies) {
- if (!nri.isRequest) {
+ if (!nri.isRequest()) {
// This is not a request, it's a callback listener.
// Add it to newNetwork regardless of score.
if (newNetwork.addRequest(nri.request)) addedRequests.add(nri);
@@ -4575,7 +4637,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mNetworkForRequestId.remove(nri.request.requestId);
sendUpdatedScoreToFactories(nri.request, 0);
} else {
- if (nri.isRequest == true) {
+ if (nri.isRequest()) {
Slog.wtf(TAG, "BUG: Removing request " + nri.request.requestId + " from " +
newNetwork.name() +
" without updating mNetworkForRequestId or factories!");
diff --git a/services/core/java/com/android/server/DeviceIdleController.java b/services/core/java/com/android/server/DeviceIdleController.java
index c8763b135f62..b57e14e98991 100644
--- a/services/core/java/com/android/server/DeviceIdleController.java
+++ b/services/core/java/com/android/server/DeviceIdleController.java
@@ -198,7 +198,6 @@ public class DeviceIdleController extends SystemService
private int mActiveIdleOpCount;
private IBinder mDownloadServiceActive;
- private boolean mSyncActive;
private boolean mJobsActive;
private boolean mAlarmsActive;
private boolean mReportedMaintenanceActivity;
@@ -944,7 +943,7 @@ public class DeviceIdleController extends SystemService
null, mIdleStartedDoneReceiver, null, 0, null, null);
}
// Always start with one active op for the message being sent here.
- // Now we we done!
+ // Now we are done!
decActiveIdleOps();
EventLogTags.writeDeviceIdleOffComplete();
} break;
@@ -1145,10 +1144,6 @@ public class DeviceIdleController extends SystemService
setNetworkPolicyTempWhitelistCallbackInternal(callback);
}
- public void setSyncActive(boolean active) {
- DeviceIdleController.this.setSyncActive(active);
- }
-
public void setJobsActive(boolean active) {
DeviceIdleController.this.setJobsActive(active);
}
@@ -1157,6 +1152,16 @@ public class DeviceIdleController extends SystemService
public void setAlarmsActive(boolean active) {
DeviceIdleController.this.setAlarmsActive(active);
}
+
+ /**
+ * Returns the array of app ids whitelisted by user. Take care not to
+ * modify this, as it is a reference to the original copy. But the reference
+ * can change when the list changes, so it needs to be re-acquired when
+ * {@link PowerManager#ACTION_POWER_SAVE_WHITELIST_CHANGED} is sent.
+ */
+ public int[] getPowerSaveWhitelistUserAppIds() {
+ return DeviceIdleController.this.getPowerSaveWhitelistUserAppIds();
+ }
}
public DeviceIdleController(Context context) {
@@ -1165,6 +1170,12 @@ public class DeviceIdleController extends SystemService
mHandler = new MyHandler(BackgroundThread.getHandler().getLooper());
}
+ int[] getPowerSaveWhitelistUserAppIds() {
+ synchronized (this) {
+ return mPowerSaveWhitelistUserAppIdArray;
+ }
+ }
+
private static File getSystemDir() {
return new File(Environment.getDataDirectory(), "system");
}
@@ -1288,7 +1299,6 @@ public class DeviceIdleController extends SystemService
mLocalPowerManager.setDeviceIdleWhitelist(mPowerSaveWhitelistAllAppIdArray);
mLocalAlarmManager.setDeviceIdleUserWhitelist(mPowerSaveWhitelistUserAppIdArray);
-
mDisplayManager.registerDisplayListener(mDisplayListener, null);
updateDisplayLocked();
}
@@ -1877,16 +1887,6 @@ public class DeviceIdleController extends SystemService
}
}
- void setSyncActive(boolean active) {
- synchronized (this) {
- mSyncActive = active;
- reportMaintenanceActivityIfNeededLocked();
- if (!active) {
- exitMaintenanceEarlyIfNeededLocked();
- }
- }
- }
-
void setJobsActive(boolean active) {
synchronized (this) {
mJobsActive = active;
@@ -1920,7 +1920,7 @@ public class DeviceIdleController extends SystemService
}
void reportMaintenanceActivityIfNeededLocked() {
- boolean active = mJobsActive | mSyncActive | (mDownloadServiceActive != null);
+ boolean active = mJobsActive | (mDownloadServiceActive != null);
if (active == mReportedMaintenanceActivity) {
return;
}
@@ -1933,7 +1933,7 @@ public class DeviceIdleController extends SystemService
void exitMaintenanceEarlyIfNeededLocked() {
if (mState == STATE_IDLE_MAINTENANCE || mLightState == LIGHT_STATE_IDLE_MAINTENANCE) {
if (mActiveIdleOpCount <= 0 && mDownloadServiceActive == null
- && !mSyncActive && !mJobsActive && !mAlarmsActive) {
+ && !mJobsActive && !mAlarmsActive) {
final long now = SystemClock.elapsedRealtime();
if (DEBUG) {
StringBuilder sb = new StringBuilder();
@@ -2741,9 +2741,6 @@ public class DeviceIdleController extends SystemService
TimeUtils.formatDuration(mMaintenanceStartTime, SystemClock.elapsedRealtime(), pw);
pw.println();
}
- if (mSyncActive) {
- pw.print(" mSyncActive="); pw.println(mSyncActive);
- }
if (mJobsActive) {
pw.print(" mJobsActive="); pw.println(mJobsActive);
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index c1b341e7dc67..898d5b73b8d6 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1318,8 +1318,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
/* @InputMethodClient.StartInputReason */ final int startInputReason,
IInputMethodClient client, IInputContext inputContext,
/* @InputConnectionInspector.missingMethods */ final int missingMethods,
- EditorInfo attribute,
- int controlFlags) {
+ @Nullable EditorInfo attribute, int controlFlags) {
// If no method is currently selected, do nothing.
if (mCurMethodId == null) {
return mNoBinding;
@@ -1331,6 +1330,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
+ client.asBinder());
}
+ if (attribute == null) {
+ Slog.w(TAG, "Ignoring startInput with null EditorInfo."
+ + " uid=" + cs.uid + " pid=" + cs.pid);
+ return null;
+ }
+
try {
if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
// Check with the window manager to make sure this client actually
@@ -1476,7 +1481,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
/* @InputMethodClient.StartInputReason */ final int startInputReason,
IInputMethodClient client, IInputContext inputContext,
/* @InputConnectionInspector.missingMethods */ final int missingMethods,
- EditorInfo attribute, int controlFlags) {
+ @Nullable EditorInfo attribute, int controlFlags) {
if (!calledFromValidUser()) {
return null;
}
@@ -2208,7 +2213,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
public InputBindResult startInputOrWindowGainedFocus(
/* @InputMethodClient.StartInputReason */ final int startInputReason,
IInputMethodClient client, IBinder windowToken, int controlFlags, int softInputMode,
- int windowFlags, EditorInfo attribute, IInputContext inputContext,
+ int windowFlags, @Nullable EditorInfo attribute, IInputContext inputContext,
/* @InputConnectionInspector.missingMethods */ final int missingMethods) {
if (windowToken != null) {
return windowGainedFocus(startInputReason, client, windowToken, controlFlags,
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 07c10b09287a..548b66284937 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1149,81 +1149,6 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
@Override
- public RouteInfo[] getRoutes(String interfaceName) {
- mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- ArrayList<RouteInfo> routes = new ArrayList<RouteInfo>();
-
- // v4 routes listed as:
- // iface dest-addr gateway-addr flags refcnt use metric netmask mtu window IRTT
- for (String s : readRouteList("/proc/net/route")) {
- String[] fields = s.split("\t");
-
- if (fields.length > 7) {
- String iface = fields[0];
-
- if (interfaceName.equals(iface)) {
- String dest = fields[1];
- String gate = fields[2];
- String flags = fields[3]; // future use?
- String mask = fields[7];
- try {
- // address stored as a hex string, ex: 0014A8C0
- InetAddress destAddr =
- NetworkUtils.intToInetAddress((int)Long.parseLong(dest, 16));
- int prefixLength =
- NetworkUtils.netmaskIntToPrefixLength(
- (int)Long.parseLong(mask, 16));
- LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
-
- // address stored as a hex string, ex 0014A8C0
- InetAddress gatewayAddr =
- NetworkUtils.intToInetAddress((int)Long.parseLong(gate, 16));
-
- RouteInfo route = new RouteInfo(linkAddress, gatewayAddr);
- routes.add(route);
- } catch (Exception e) {
- Log.e(TAG, "Error parsing route " + s + " : " + e);
- continue;
- }
- }
- }
- }
-
- // v6 routes listed as:
- // dest-addr prefixlength ?? ?? gateway-addr ?? ?? ?? ?? iface
- for (String s : readRouteList("/proc/net/ipv6_route")) {
- String[]fields = s.split("\\s+");
- if (fields.length > 9) {
- String iface = fields[9].trim();
- if (interfaceName.equals(iface)) {
- String dest = fields[0];
- String prefix = fields[1];
- String gate = fields[4];
-
- try {
- // prefix length stored as a hex string, ex 40
- int prefixLength = Integer.parseInt(prefix, 16);
-
- // address stored as a 32 char hex string
- // ex fe800000000000000000000000000000
- InetAddress destAddr = NetworkUtils.hexToInet6Address(dest);
- LinkAddress linkAddress = new LinkAddress(destAddr, prefixLength);
-
- InetAddress gateAddr = NetworkUtils.hexToInet6Address(gate);
-
- RouteInfo route = new RouteInfo(linkAddress, gateAddr);
- routes.add(route);
- } catch (Exception e) {
- Log.e(TAG, "Error parsing route " + s + " : " + e);
- continue;
- }
- }
- }
- }
- return routes.toArray(new RouteInfo[routes.size()]);
- }
-
- @Override
public void setMtu(String iface, int mtu) {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
diff --git a/services/core/java/com/android/server/connectivity/ApfFilter.java b/services/core/java/com/android/server/connectivity/ApfFilter.java
index d62a0b3fb090..824db6541001 100644
--- a/services/core/java/com/android/server/connectivity/ApfFilter.java
+++ b/services/core/java/com/android/server/connectivity/ApfFilter.java
@@ -90,6 +90,7 @@ public class ApfFilter {
}
private static final String TAG = "ApfFilter";
+ private static final boolean DBG = true;
private static final boolean VDBG = false;
private final ConnectivityService mConnectivityService;
@@ -205,6 +206,10 @@ public class ApfFilter {
// For debugging only. How many times this RA was seen.
int seenCount = 0;
+ // For debugging only. Returns the hex representation of the last matching packet.
+ String getLastMatchingPacket() {
+ return HexDump.toHexString(mPacket.array(), 0, mPacket.capacity(), false /* lowercase */);
+ }
private String IPv6AddresstoString(int pos) {
try {
@@ -406,11 +411,17 @@ public class ApfFilter {
for (int i = 0; i < mNonLifetimes.size(); i++) {
// Generate code to match the packet bytes
Pair<Integer, Integer> nonLifetime = mNonLifetimes.get(i);
- gen.addLoadImmediate(Register.R0, nonLifetime.first);
- gen.addJumpIfBytesNotEqual(Register.R0,
- Arrays.copyOfRange(mPacket.array(), nonLifetime.first,
- nonLifetime.first + nonLifetime.second),
- nextFilterLabel);
+ // Don't generate JNEBS instruction for 0 bytes as it always fails the
+ // ASSERT_FORWARD_IN_PROGRAM(pc + cmp_imm - 1) check where cmp_imm is
+ // the number of bytes to compare. nonLifetime is zero between the
+ // valid and preferred lifetimes in the prefix option.
+ if (nonLifetime.second != 0) {
+ gen.addLoadImmediate(Register.R0, nonLifetime.first);
+ gen.addJumpIfBytesNotEqual(Register.R0,
+ Arrays.copyOfRange(mPacket.array(), nonLifetime.first,
+ nonLifetime.first + nonLifetime.second),
+ nextFilterLabel);
+ }
// Generate code to test the lifetimes haven't gone down too far
if ((i + 1) < mNonLifetimes.size()) {
Pair<Integer, Integer> nextNonLifetime = mNonLifetimes.get(i + 1);
@@ -454,7 +465,7 @@ public class ApfFilter {
private long mLastInstalledProgramMinLifetime;
// For debugging only. The length in bytes of the last program.
- private long mLastInstalledProgramLength;
+ private byte[] mLastInstalledProgram;
private void installNewProgram() {
if (mRas.size() == 0) return;
@@ -495,7 +506,7 @@ public class ApfFilter {
}
mLastTimeInstalledProgram = curTime();
mLastInstalledProgramMinLifetime = programMinLifetime;
- mLastInstalledProgramLength = program.length;
+ mLastInstalledProgram = program;
if (VDBG) {
hexDump("Installing filter: ", program, program.length);
} else {
@@ -515,7 +526,7 @@ public class ApfFilter {
}
private void hexDump(String msg, byte[] packet, int length) {
- log(msg + HexDump.toHexString(packet, 0, length));
+ log(msg + HexDump.toHexString(packet, 0, length, false /* lowercase */));
}
private void processRa(byte[] packet, int length) {
@@ -608,7 +619,7 @@ public class ApfFilter {
pw.println(String.format(
"Last program length %d, installed %ds ago, lifetime %d",
- mLastInstalledProgramLength, curTime() - mLastTimeInstalledProgram,
+ mLastInstalledProgram.length, curTime() - mLastTimeInstalledProgram,
mLastInstalledProgramMinLifetime));
pw.println("RA filters:");
@@ -618,8 +629,22 @@ public class ApfFilter {
pw.increaseIndent();
pw.println(String.format(
"Seen: %d, last %ds ago", ra.seenCount, curTime() - ra.mLastSeen));
+ if (DBG) {
+ pw.println("Last match:");
+ pw.increaseIndent();
+ pw.println(ra.getLastMatchingPacket());
+ pw.decreaseIndent();
+ }
+ pw.decreaseIndent();
+ }
+
+ if (DBG) {
+ pw.println("Last program:");
+ pw.increaseIndent();
+ pw.println(HexDump.toHexString(mLastInstalledProgram, false /* lowercase */));
pw.decreaseIndent();
}
+
pw.decreaseIndent();
}
}
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 4eecc8186c1e..da9c48a2a5ee 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -255,6 +255,9 @@ public class Tethering extends BaseNetworkObserver {
// ignore usb0 down after enabling RNDIS
// we will handle disconnect in interfaceRemoved instead
if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
+ } else if (isWifi(iface)) {
+ // handle disconnect in interfaceRemoved
+ if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
} else if (sm != null) {
sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
mIfaces.remove(iface);
diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java
index e34fb9bef2ba..6b00f5fe893b 100644
--- a/services/core/java/com/android/server/job/JobSchedulerService.java
+++ b/services/core/java/com/android/server/job/JobSchedulerService.java
@@ -67,6 +67,7 @@ import com.android.server.job.controllers.AppIdleController;
import com.android.server.job.controllers.BatteryController;
import com.android.server.job.controllers.ConnectivityController;
import com.android.server.job.controllers.ContentObserverController;
+import com.android.server.job.controllers.DeviceIdleJobsController;
import com.android.server.job.controllers.IdleController;
import com.android.server.job.controllers.JobStatus;
import com.android.server.job.controllers.StateController;
@@ -164,11 +165,6 @@ public final class JobSchedulerService extends com.android.server.SystemService
boolean mReadyToRock;
/**
- * True when in device idle mode, so we don't want to schedule any jobs.
- */
- boolean mDeviceIdleMode;
-
- /**
* What we last reported to DeviceIdleController about whether we are active.
*/
boolean mReportedActive;
@@ -228,12 +224,6 @@ public final class JobSchedulerService extends com.android.server.SystemService
Slog.d(TAG, "Removing jobs for user: " + userId);
}
cancelJobsForUser(userId);
- } else if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())
- || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(intent.getAction())) {
- updateIdleMode(mPowerManager != null
- ? (mPowerManager.isDeviceIdleMode()
- || mPowerManager.isLightDeviceIdleMode())
- : false);
}
}
};
@@ -418,44 +408,29 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
}
- void updateIdleMode(boolean enabled) {
- boolean changed = false;
- boolean rocking;
+ @Override
+ public void onDeviceIdleStateChanged(boolean deviceIdle) {
synchronized (mLock) {
- if (mDeviceIdleMode != enabled) {
- changed = true;
- }
- rocking = mReadyToRock;
- }
- if (changed) {
- if (rocking) {
- for (int i=0; i<mControllers.size(); i++) {
- mControllers.get(i).deviceIdleModeChanged(enabled);
- }
- }
- synchronized (mLock) {
- mDeviceIdleMode = enabled;
- if (enabled) {
- // When becoming idle, make sure no jobs are actively running.
- for (int i=0; i<mActiveServices.size(); i++) {
- JobServiceContext jsc = mActiveServices.get(i);
- final JobStatus executing = jsc.getRunningJob();
- if (executing != null) {
- jsc.cancelExecutingJob(JobParameters.REASON_DEVICE_IDLE);
- }
+ if (deviceIdle) {
+ // When becoming idle, make sure no jobs are actively running.
+ for (int i=0; i<mActiveServices.size(); i++) {
+ JobServiceContext jsc = mActiveServices.get(i);
+ final JobStatus executing = jsc.getRunningJob();
+ if (executing != null) {
+ jsc.cancelExecutingJob(JobParameters.REASON_DEVICE_IDLE);
}
- } else {
- // When coming out of idle, allow thing to start back up.
- if (rocking) {
- if (mLocalDeviceIdleController != null) {
- if (!mReportedActive) {
- mReportedActive = true;
- mLocalDeviceIdleController.setJobsActive(true);
- }
+ }
+ } else {
+ // When coming out of idle, allow thing to start back up.
+ if (mReadyToRock) {
+ if (mLocalDeviceIdleController != null) {
+ if (!mReportedActive) {
+ mReportedActive = true;
+ mLocalDeviceIdleController.setJobsActive(true);
}
}
- mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
+ mHandler.obtainMessage(MSG_CHECK_JOB).sendToTarget();
}
}
}
@@ -500,6 +475,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
mControllers.add(BatteryController.get(this));
mControllers.add(AppIdleController.get(this));
mControllers.add(ContentObserverController.get(this));
+ mControllers.add(DeviceIdleJobsController.get(this));
mHandler = new JobHandler(context.getMainLooper());
mJobSchedulerStub = new JobSchedulerStub();
@@ -521,8 +497,6 @@ public final class JobSchedulerService extends com.android.server.SystemService
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, filter, null, null);
final IntentFilter userFilter = new IntentFilter(Intent.ACTION_USER_REMOVED);
- userFilter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
- userFilter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
getContext().registerReceiverAsUser(
mBroadcastReceiver, UserHandle.ALL, userFilter, null, null);
mPowerManager = (PowerManager)getContext().getSystemService(Context.POWER_SERVICE);
@@ -553,7 +527,6 @@ public final class JobSchedulerService extends com.android.server.SystemService
public void process(JobStatus job) {
for (int controller = 0; controller < mControllers.size(); controller++) {
final StateController sc = mControllers.get(controller);
- sc.deviceIdleModeChanged(mDeviceIdleMode);
sc.maybeStartTrackingJobLocked(job, null);
}
}
@@ -1015,10 +988,6 @@ public final class JobSchedulerService extends com.android.server.SystemService
*/
private void maybeRunPendingJobsH() {
synchronized (mLock) {
- if (mDeviceIdleMode) {
- // If device is idle, we will not schedule jobs to run.
- return;
- }
if (DEBUG) {
Slog.d(TAG, "pending queue: " + mPendingJobs.size() + " jobs.");
}
@@ -1188,6 +1157,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
* Returns a list of all pending jobs. A running job is not considered pending. Periodic
* jobs are always considered pending.
*/
+ @Override
public List<JobInfo> getSystemScheduledPendingJobs() {
synchronized (mLock) {
final List<JobInfo> pendingJobs = new ArrayList<JobInfo>();
@@ -1509,7 +1479,6 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
pw.println();
pw.print("mReadyToRock="); pw.println(mReadyToRock);
- pw.print("mDeviceIdleMode="); pw.println(mDeviceIdleMode);
pw.print("mReportedActive="); pw.println(mReportedActive);
pw.print("mMaxActiveJobs="); pw.println(mMaxActiveJobs);
}
diff --git a/services/core/java/com/android/server/job/StateChangedListener.java b/services/core/java/com/android/server/job/StateChangedListener.java
index 97dfad39fa7f..87bfc27a715f 100644
--- a/services/core/java/com/android/server/job/StateChangedListener.java
+++ b/services/core/java/com/android/server/job/StateChangedListener.java
@@ -37,4 +37,6 @@ public interface StateChangedListener {
* indicates to the scheduler that any ready jobs should be flushed.</strong>
*/
public void onRunJobNow(JobStatus jobStatus);
+
+ public void onDeviceIdleStateChanged(boolean deviceIdle);
}
diff --git a/services/core/java/com/android/server/job/controllers/AppIdleController.java b/services/core/java/com/android/server/job/controllers/AppIdleController.java
index f0c579f1ae98..2114fc3b07c8 100644
--- a/services/core/java/com/android/server/job/controllers/AppIdleController.java
+++ b/services/core/java/com/android/server/job/controllers/AppIdleController.java
@@ -87,7 +87,7 @@ public class AppIdleController extends StateController {
pw.println("Parole On: " + mAppIdleParoleOn);
for (JobStatus task : mTrackedTasks) {
pw.print(task.getSourcePackageName());
- pw.print(":idle="
+ pw.print(":runnable="
+ ((task.satisfiedConstraints&JobStatus.CONSTRAINT_APP_NOT_IDLE) != 0));
pw.print(", ");
}
diff --git a/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
new file mode 100644
index 000000000000..d2ef6a2e5aa2
--- /dev/null
+++ b/services/core/java/com/android/server/job/controllers/DeviceIdleJobsController.java
@@ -0,0 +1,184 @@
+/*
+ * 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
+ */
+
+package com.android.server.job.controllers;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PowerManager;
+import android.os.UserHandle;
+import android.util.Slog;
+
+import com.android.internal.util.ArrayUtils;
+import com.android.server.DeviceIdleController;
+import com.android.server.LocalServices;
+import com.android.server.job.JobSchedulerService;
+import com.android.server.job.StateChangedListener;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * When device is dozing, set constraint for all jobs, except whitelisted apps, as not satisfied.
+ * When device is not dozing, set constraint for all jobs as satisfied.
+ */
+public class DeviceIdleJobsController extends StateController {
+
+ private static final String LOG_TAG = "DeviceIdleJobsController";
+ private static final boolean LOG_DEBUG = false;
+
+ // Singleton factory
+ private static Object sCreationLock = new Object();
+ final ArrayList<JobStatus> mTrackedTasks = new ArrayList<JobStatus>();
+ private static DeviceIdleJobsController sController;
+
+ private final PowerManager mPowerManager;
+ private final DeviceIdleController.LocalService mLocalDeviceIdleController;
+
+ /**
+ * True when in device idle mode, so we don't want to schedule any jobs.
+ */
+ private boolean mDeviceIdleMode;
+ private int[] mDeviceIdleWhitelistAppIds;
+
+ /**
+ * Returns a singleton for the DeviceIdleJobsController
+ */
+ public static DeviceIdleJobsController get(JobSchedulerService service) {
+ synchronized (sCreationLock) {
+ if (sController == null) {
+ sController = new DeviceIdleJobsController(service, service.getContext(),
+ service.getLock());
+ }
+ return sController;
+ }
+ }
+
+ // onReceive
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED.equals(action)
+ || PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED.equals(action)) {
+ updateIdleMode(mPowerManager != null
+ ? (mPowerManager.isDeviceIdleMode()
+ || mPowerManager.isLightDeviceIdleMode())
+ : false);
+ } else if (PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED.equals(action)) {
+ updateWhitelist();
+ }
+ }
+ };
+
+ private DeviceIdleJobsController(StateChangedListener stateChangedListener, Context context,
+ Object lock) {
+ super(stateChangedListener, context, lock);
+
+ // Register for device idle mode changes
+ mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+ mLocalDeviceIdleController =
+ LocalServices.getService(DeviceIdleController.LocalService.class);
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(PowerManager.ACTION_DEVICE_IDLE_MODE_CHANGED);
+ filter.addAction(PowerManager.ACTION_LIGHT_DEVICE_IDLE_MODE_CHANGED);
+ filter.addAction(PowerManager.ACTION_POWER_SAVE_WHITELIST_CHANGED);
+ mContext.registerReceiverAsUser(
+ mBroadcastReceiver, UserHandle.ALL, filter, null, null);
+ }
+
+ void updateIdleMode(boolean enabled) {
+ boolean changed = false;
+ // Need the whitelist to be ready when going into idle
+ if (mDeviceIdleWhitelistAppIds == null) {
+ updateWhitelist();
+ }
+ synchronized (mLock) {
+ if (mDeviceIdleMode != enabled) {
+ changed = true;
+ }
+ mDeviceIdleMode = enabled;
+ if (LOG_DEBUG) Slog.d(LOG_TAG, "mDeviceIdleMode=" + mDeviceIdleMode);
+ for (JobStatus task : mTrackedTasks) {
+ updateTaskStateLocked(task);
+ }
+ }
+ // Inform the job scheduler service about idle mode changes
+ if (changed) {
+ mStateChangedListener.onDeviceIdleStateChanged(enabled);
+ }
+ }
+
+ /**
+ * Fetches the latest whitelist from the device idle controller.
+ */
+ void updateWhitelist() {
+ synchronized (mLock) {
+ if (mLocalDeviceIdleController != null) {
+ mDeviceIdleWhitelistAppIds =
+ mLocalDeviceIdleController.getPowerSaveWhitelistUserAppIds();
+ if (LOG_DEBUG) {
+ Slog.d(LOG_TAG, "Got whitelist " + Arrays.toString(mDeviceIdleWhitelistAppIds));
+ }
+ }
+ }
+ }
+
+ /**
+ * Checks if the given job's scheduling app id exists in the device idle user whitelist.
+ */
+ boolean isWhitelistedLocked(JobStatus job) {
+ if (mDeviceIdleWhitelistAppIds != null
+ && ArrayUtils.contains(mDeviceIdleWhitelistAppIds,
+ UserHandle.getAppId(job.getSourceUid()))) {
+ return true;
+ }
+ return false;
+ }
+
+ private void updateTaskStateLocked(JobStatus task) {
+ boolean enableTask = !mDeviceIdleMode || isWhitelistedLocked(task);
+ task.setDeviceNotDozingConstraintSatisfied(enableTask);
+ }
+
+ @Override
+ public void maybeStartTrackingJobLocked(JobStatus jobStatus, JobStatus lastJob) {
+ synchronized (mLock) {
+ mTrackedTasks.add(jobStatus);
+ updateTaskStateLocked(jobStatus);
+ }
+ }
+
+ @Override
+ public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
+ mTrackedTasks.remove(jobStatus);
+ }
+
+ @Override
+ public void dumpControllerStateLocked(PrintWriter pw) {
+ pw.println("DeviceIdleJobsController");
+ for (JobStatus task : mTrackedTasks) {
+ pw.print(task.getSourcePackageName());
+ pw.print(":runnable="
+ + ((task.satisfiedConstraints & JobStatus.CONSTRAINT_DEVICE_NOT_DOZING) != 0));
+ pw.print(", ");
+ }
+ pw.println();
+ }
+} \ No newline at end of file
diff --git a/services/core/java/com/android/server/job/controllers/JobStatus.java b/services/core/java/com/android/server/job/controllers/JobStatus.java
index 4a2c88c2f733..39905d8e57e2 100644
--- a/services/core/java/com/android/server/job/controllers/JobStatus.java
+++ b/services/core/java/com/android/server/job/controllers/JobStatus.java
@@ -54,6 +54,7 @@ public final class JobStatus {
static final int CONSTRAINT_CONNECTIVITY = 1<<5;
static final int CONSTRAINT_APP_NOT_IDLE = 1<<6;
static final int CONSTRAINT_CONTENT_TRIGGER = 1<<7;
+ static final int CONSTRAINT_DEVICE_NOT_DOZING = 1<<8;
// Soft override: ignore constraints like time that don't affect API availability
public static final int OVERRIDE_SOFT = 1;
@@ -363,6 +364,10 @@ public final class JobStatus {
return setConstraintSatisfied(CONSTRAINT_CONTENT_TRIGGER, state);
}
+ boolean setDeviceNotDozingConstraintSatisfied(boolean state) {
+ return setConstraintSatisfied(CONSTRAINT_DEVICE_NOT_DOZING, state);
+ }
+
boolean setConstraintSatisfied(int constraint, boolean state) {
boolean old = (satisfiedConstraints&constraint) != 0;
if (old == state) {
@@ -380,11 +385,14 @@ public final class JobStatus {
// Deadline constraint trumps other constraints (except for periodic jobs where deadline
// is an implementation detail. A periodic job should only run if its constraints are
// satisfied).
- // AppNotIdle implicit constraint trumps all!
+ // AppNotIdle implicit constraint must be satisfied
+ // DeviceNotDozing implicit constraint must be satisfied
return (isConstraintsSatisfied()
|| (!job.isPeriodic()
- && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0))
- && (satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0;
+ && hasDeadlineConstraint() && (satisfiedConstraints&CONSTRAINT_DEADLINE) != 0)
+ )
+ && (satisfiedConstraints & CONSTRAINT_APP_NOT_IDLE) != 0
+ && (satisfiedConstraints & CONSTRAINT_DEVICE_NOT_DOZING) != 0;
}
static final int CONSTRAINTS_OF_INTEREST =
@@ -433,6 +441,7 @@ public final class JobStatus {
+ ",U=" + (job.getTriggerContentUris() != null)
+ ",F=" + numFailures + ",P=" + job.isPersisted()
+ ",ANI=" + ((satisfiedConstraints&CONSTRAINT_APP_NOT_IDLE) != 0)
+ + ",DND=" + ((satisfiedConstraints&CONSTRAINT_DEVICE_NOT_DOZING) != 0)
+ (isReady() ? "(READY)" : "")
+ "]";
}
@@ -492,6 +501,9 @@ public final class JobStatus {
if ((constraints&CONSTRAINT_CONTENT_TRIGGER) != 0) {
pw.print(" CONTENT_TRIGGER");
}
+ if ((constraints&CONSTRAINT_DEVICE_NOT_DOZING) != 0) {
+ pw.print(" DEVICE_NOT_DOZING");
+ }
}
// Dumpsys infrastructure
diff --git a/services/core/java/com/android/server/job/controllers/StateController.java b/services/core/java/com/android/server/job/controllers/StateController.java
index 7882bc4d86ab..ac7f4c3f4756 100644
--- a/services/core/java/com/android/server/job/controllers/StateController.java
+++ b/services/core/java/com/android/server/job/controllers/StateController.java
@@ -33,7 +33,6 @@ public abstract class StateController {
protected final Context mContext;
protected final Object mLock;
protected final StateChangedListener mStateChangedListener;
- protected boolean mDeviceIdleMode;
public StateController(StateChangedListener stateChangedListener, Context context,
Object lock) {
@@ -42,10 +41,6 @@ public abstract class StateController {
mLock = lock;
}
- public void deviceIdleModeChanged(boolean enabled) {
- mDeviceIdleMode = enabled;
- }
-
/**
* Implement the logic here to decide whether a job should be tracked by this controller.
* This logic is put here so the JobManager can be completely agnostic of Controller logic.
diff --git a/services/core/java/com/android/server/media/MediaResourceMonitorService.java b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
index 50dd607e5a5a..e169d638c442 100644
--- a/services/core/java/com/android/server/media/MediaResourceMonitorService.java
+++ b/services/core/java/com/android/server/media/MediaResourceMonitorService.java
@@ -37,13 +37,6 @@ public class MediaResourceMonitorService extends SystemService {
private static final String SERVICE_NAME = "media_resource_monitor";
- /*
- * Resource types. Should be in sync with:
- * frameworks/av/media/libmedia/MediaResource.cpp
- */
- private static final String RESOURCE_AUDIO_CODEC = "audio-codec";
- private static final String RESOURCE_VIDEO_CODEC = "video-codec";
-
private final MediaResourceMonitorImpl mMediaResourceMonitorImpl;
public MediaResourceMonitorService(Context context) {
@@ -58,25 +51,18 @@ public class MediaResourceMonitorService extends SystemService {
class MediaResourceMonitorImpl extends IMediaResourceMonitor.Stub {
@Override
- public void notifyResourceGranted(int pid, String type, String subType, long value)
+ public void notifyResourceGranted(int pid, int type)
throws RemoteException {
if (DEBUG) {
- Slog.d(TAG, "notifyResourceGranted(pid=" + pid + ", type=" + type + ", subType="
- + subType + ", value=" + value + ")");
+ Slog.d(TAG, "notifyResourceGranted(pid=" + pid + ", type=" + type + ")");
}
final long identity = Binder.clearCallingIdentity();
try {
String pkgNames[] = getPackageNamesFromPid(pid);
- Integer resourceType = null;
- if (RESOURCE_AUDIO_CODEC.equals(subType)) {
- resourceType = Intent.EXTRA_MEDIA_RESOURCE_TYPE_AUDIO_CODEC;
- } else if (RESOURCE_VIDEO_CODEC.equals(subType)) {
- resourceType = Intent.EXTRA_MEDIA_RESOURCE_TYPE_VIDEO_CODEC;
- }
- if (pkgNames != null && resourceType != null) {
+ if (pkgNames != null) {
Intent intent = new Intent(Intent.ACTION_MEDIA_RESOURCE_GRANTED);
intent.putExtra(Intent.EXTRA_PACKAGES, pkgNames);
- intent.putExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE, resourceType);
+ intent.putExtra(Intent.EXTRA_MEDIA_RESOURCE_TYPE, type);
getContext().sendBroadcastAsUser(intent,
new UserHandle(ActivityManager.getCurrentUser()),
android.Manifest.permission.RECEIVE_MEDIA_RESOURCE_USAGE);
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 274a73f28673..0f23fded2e92 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1852,16 +1852,11 @@ public class NotificationManagerService extends SystemService {
}
private boolean checkPolicyAccess(String pkg) {
- if (PackageManager.PERMISSION_GRANTED == getContext().checkCallingPermission(
- android.Manifest.permission.MANAGE_NOTIFICATIONS)) {
+ if (PackageManager.PERMISSION_GRANTED == ActivityManager.checkComponentPermission(
+ android.Manifest.permission.MANAGE_NOTIFICATIONS, Binder.getCallingUid(),
+ -1, true)) {
return true;
}
- if (mAudioManagerInternal != null) {
- final int vcuid = mAudioManagerInternal.getVolumeControllerUid();
- if (vcuid > 0 && Binder.getCallingUid() == vcuid) {
- return true;
- }
- }
return checkPackagePolicyAccess(pkg) || mListeners.isComponentEnabledForPackage(pkg);
}
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 0eacd13e1a80..d449ce55bfba 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -16,6 +16,8 @@
package com.android.server.pm;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.REASON_BACKGROUND_DEXOPT;
+
import android.app.AlarmManager;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
@@ -51,8 +53,6 @@ public class BackgroundDexOptService extends JobService {
final AtomicBoolean mIdleTime = new AtomicBoolean(false);
- private boolean useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
-
public static void schedule(Context context) {
JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
JobInfo job = new JobInfo.Builder(BACKGROUND_DEXOPT_JOB, sDexoptServiceName)
@@ -93,8 +93,8 @@ public class BackgroundDexOptService extends JobService {
// skip previously failing package
continue;
}
- if (!pm.performDexOpt(pkg, /* instruction set */ null, useJitProfiles,
- /* extractOnly */ false, /* force */ false)) {
+ if (!pm.performDexOpt(pkg, /* instruction set */ null, /* checkProfiles */ true,
+ REASON_BACKGROUND_DEXOPT, /* force */ false)) {
// there was a problem running dexopt,
// remember this so we do not keep retrying.
sFailedPackageNames.add(pkg);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 206a1438bd61..a1f937aba519 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -20,7 +20,6 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.PackageStats;
import android.os.Build;
-import android.os.storage.StorageManager;
import android.util.Slog;
import com.android.internal.os.InstallerConnection;
@@ -37,17 +36,17 @@ public final class Installer extends SystemService {
* frameworks/native/cmds/installd/installd.h
* **************************************************************************/
/** Application should be visible to everyone */
- public static final int DEXOPT_PUBLIC = 1 << 1;
+ public static final int DEXOPT_PUBLIC = 1 << 1;
/** Application wants to run in VM safe mode */
- public static final int DEXOPT_SAFEMODE = 1 << 2;
+ public static final int DEXOPT_SAFEMODE = 1 << 2;
/** Application wants to allow debugging of its code */
- public static final int DEXOPT_DEBUGGABLE = 1 << 3;
+ public static final int DEXOPT_DEBUGGABLE = 1 << 3;
/** The system boot has finished */
- public static final int DEXOPT_BOOTCOMPLETE = 1 << 4;
- /** Do not compile, only extract bytecode into an OAT file */
- public static final int DEXOPT_EXTRACTONLY = 1 << 5;
+ public static final int DEXOPT_BOOTCOMPLETE = 1 << 4;
+ /** Hint that the dexopt type is profile-guided. */
+ public static final int DEXOPT_PROFILE_GUIDED = 1 << 5;
/** This is an OTA update dexopt */
- public static final int DEXOPT_OTA = 1 << 6;
+ public static final int DEXOPT_OTA = 1 << 6;
// NOTE: keep in sync with installd
public static final int FLAG_CLEAR_CACHE_ONLY = 1 << 8;
@@ -137,19 +136,23 @@ public final class Installer extends SystemService {
}
public void dexopt(String apkPath, int uid, String instructionSet, int dexoptNeeded,
- int dexFlags, String volumeUuid, boolean useProfiles) throws InstallerException {
+ int dexFlags, String compilerFilter, String volumeUuid) throws InstallerException {
assertValidInstructionSet(instructionSet);
mInstaller.dexopt(apkPath, uid, instructionSet, dexoptNeeded, dexFlags,
- volumeUuid, useProfiles);
+ compilerFilter, volumeUuid);
}
public void dexopt(String apkPath, int uid, String pkgName, String instructionSet,
int dexoptNeeded, @Nullable String outputPath, int dexFlags,
- String volumeUuid, boolean useProfiles)
+ String compilerFilter, String volumeUuid)
throws InstallerException {
assertValidInstructionSet(instructionSet);
mInstaller.dexopt(apkPath, uid, pkgName, instructionSet, dexoptNeeded,
- outputPath, dexFlags, volumeUuid, useProfiles);
+ outputPath, dexFlags, compilerFilter, volumeUuid);
+ }
+
+ public boolean mergeProfiles(int uid, String pkgName) throws InstallerException {
+ return mInstaller.mergeProfiles(uid, pkgName);
}
public void idmap(String targetApkPath, String overlayApkPath, int uid)
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 67aeed116df5..03e838b7e148 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -19,11 +19,12 @@ package com.android.server.pm;
import static com.android.server.pm.Installer.DEXOPT_OTA;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.REASON_AB_OTA;
import android.content.Context;
import android.content.pm.IOtaDexopt;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.Package;
import android.os.Environment;
import android.os.RemoteException;
import android.os.ResultReceiver;
@@ -130,6 +131,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
// TODO: If apps are not installed in the internal /data partition, we should compare
// against that storage's free capacity.
File dataDir = Environment.getDataDirectory();
+ @SuppressWarnings("deprecation")
long lowThreshold = StorageManager.from(mContext).getStorageLowBytes(dataDir);
if (lowThreshold == 0) {
throw new IllegalStateException("Invalid low memory threshold");
@@ -142,7 +144,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub {
}
mPackageDexOptimizer.performDexOpt(nextPackage, null /* ISAs */, false /* useProfiles */,
- false /* extractOnly */);
+ getCompilerFilterForReason(REASON_AB_OTA));
}
private void moveAbArtifacts(Installer installer) {
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index 561682c5c478..5ceb65fb81fa 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -20,13 +20,10 @@ import android.annotation.Nullable;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
-import android.content.pm.PackageParser.Package;
import android.os.Environment;
import android.os.PowerManager;
import android.os.UserHandle;
import android.os.WorkSource;
-import android.os.storage.StorageManager;
-import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
@@ -34,18 +31,18 @@ import com.android.internal.os.InstallerConnection.InstallerException;
import java.io.File;
import java.io.IOException;
-import java.util.ArrayList;
import java.util.List;
import dalvik.system.DexFile;
import static com.android.server.pm.Installer.DEXOPT_BOOTCOMPLETE;
import static com.android.server.pm.Installer.DEXOPT_DEBUGGABLE;
+import static com.android.server.pm.Installer.DEXOPT_PROFILE_GUIDED;
import static com.android.server.pm.Installer.DEXOPT_PUBLIC;
import static com.android.server.pm.Installer.DEXOPT_SAFEMODE;
-import static com.android.server.pm.Installer.DEXOPT_EXTRACTONLY;
import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.getFullCompilerFilter;
/**
* Helper class for running dexopt command on packages.
@@ -59,8 +56,6 @@ class PackageDexOptimizer {
static final int DEX_OPT_DEFERRED = 2;
static final int DEX_OPT_FAILED = -1;
- private static final boolean DEBUG_DEXOPT = PackageManagerService.DEBUG_DEXOPT;
-
private final Installer mInstaller;
private final Object mInstallLock;
@@ -94,8 +89,8 @@ class PackageDexOptimizer {
* <p>Calls to {@link com.android.server.pm.Installer#dexopt} on {@link #mInstaller} are
* synchronized on {@link #mInstallLock}.
*/
- int performDexOpt(PackageParser.Package pkg, String[] instructionSets, boolean useProfiles,
- boolean extractOnly) {
+ int performDexOpt(PackageParser.Package pkg, String[] instructionSets, boolean checkProfiles,
+ String targetCompilationFilter) {
synchronized (mInstallLock) {
final boolean useLock = mSystemReady;
if (useLock) {
@@ -103,7 +98,8 @@ class PackageDexOptimizer {
mDexoptWakeLock.acquire();
}
try {
- return performDexOptLI(pkg, instructionSets, useProfiles, extractOnly);
+ return performDexOptLI(pkg, instructionSets, checkProfiles,
+ targetCompilationFilter);
} finally {
if (useLock) {
mDexoptWakeLock.release();
@@ -128,7 +124,7 @@ class PackageDexOptimizer {
}
private int performDexOptLI(PackageParser.Package pkg, String[] targetInstructionSets,
- boolean useProfiles, boolean extractOnly) {
+ boolean checkProfiles, String targetCompilerFilter) {
final String[] instructionSets = targetInstructionSets != null ?
targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo);
@@ -136,36 +132,51 @@ class PackageDexOptimizer {
return DEX_OPT_SKIPPED;
}
+ final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
+ final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+
+ boolean isProfileGuidedFilter = DexFile.isProfileGuidedCompilerFilter(targetCompilerFilter);
+ // If any part of the app is used by other apps, we cannot use profile-guided
+ // compilation.
+ // TODO: This needs to be refactored to be also checked when the target mode is
+ // profile-guided.
+ if (isProfileGuidedFilter) {
+ for (String path : paths) {
+ if (isUsedByOtherApps(path)) {
+ checkProfiles = false;
+
+ // TODO: Should we only upgrade to the non-profile-guided version? That is,
+ // given verify-profile, should we move to interpret-only?
+ targetCompilerFilter = getFullCompilerFilter();
+ isProfileGuidedFilter = false;
+
+ break;
+ }
+ }
+ }
+
+ // If we're asked to take profile updates into account, check now.
+ boolean newProfile = false;
+ if (checkProfiles && isProfileGuidedFilter) {
+ // Merge profiles, see if we need to do anything.
+ try {
+ newProfile = mInstaller.mergeProfiles(sharedGid, pkg.packageName);
+ } catch (InstallerException e) {
+ Slog.w(TAG, "Failed to merge profiles", e);
+ }
+ }
+
final boolean vmSafeMode = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0;
final boolean debuggable = (pkg.applicationInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
- final List<String> paths = pkg.getAllCodePathsExcludingResourceOnly();
boolean performedDexOpt = false;
final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets);
for (String dexCodeInstructionSet : dexCodeInstructionSets) {
for (String path : paths) {
- if (useProfiles && isUsedByOtherApps(path)) {
- // We cannot use profile guided compilation if the apk was used by another app.
- useProfiles = false;
- }
int dexoptNeeded;
-
try {
- int compilationTypeMask = 0;
- if (extractOnly) {
- // For extract only, any type of compilation is good.
- compilationTypeMask = DexFile.COMPILATION_TYPE_FULL
- | DexFile.COMPILATION_TYPE_PROFILE_GUIDE
- | DexFile.COMPILATION_TYPE_EXTRACT_ONLY;
- } else {
- // Branch taken for profile guide and full compilation.
- // Profile guide compilation should only recompile a previous
- // profile compiled/extract only file and should not be attempted if the
- // apk is already fully compiled. So test against a full compilation type.
- compilationTypeMask = DexFile.COMPILATION_TYPE_FULL;
- }
dexoptNeeded = DexFile.getDexOptNeeded(path,
- dexCodeInstructionSet, compilationTypeMask);
+ dexCodeInstructionSet, targetCompilerFilter, newProfile);
} catch (IOException ioe) {
Slog.w(TAG, "IOException reading apk: " + path, ioe);
return DEX_OPT_FAILED;
@@ -194,20 +205,20 @@ class PackageDexOptimizer {
Log.i(TAG, "Running dexopt (" + dexoptType + ") on: " + path + " pkg="
+ pkg.applicationInfo.packageName + " isa=" + dexCodeInstructionSet
+ " vmSafeMode=" + vmSafeMode + " debuggable=" + debuggable
- + " extractOnly=" + extractOnly + " oatDir = " + oatDir);
- final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
+ + " target-filter=" + targetCompilerFilter + " oatDir = " + oatDir);
// Profile guide compiled oat files should not be public.
- final boolean isPublic = !pkg.isForwardLocked() && !useProfiles;
+ final boolean isPublic = !pkg.isForwardLocked() && !isProfileGuidedFilter;
+ final int profileFlag = isProfileGuidedFilter ? DEXOPT_PROFILE_GUIDED : 0;
final int dexFlags = adjustDexoptFlags(
( isPublic ? DEXOPT_PUBLIC : 0)
| (vmSafeMode ? DEXOPT_SAFEMODE : 0)
| (debuggable ? DEXOPT_DEBUGGABLE : 0)
- | (extractOnly ? DEXOPT_EXTRACTONLY : 0)
+ | profileFlag
| DEXOPT_BOOTCOMPLETE);
try {
mInstaller.dexopt(path, sharedGid, pkg.packageName, dexCodeInstructionSet,
- dexoptNeeded, oatDir, dexFlags, pkg.volumeUuid, useProfiles);
+ dexoptNeeded, oatDir, dexFlags, targetCompilerFilter, pkg.volumeUuid);
performedDexOpt = true;
} catch (InstallerException e) {
Slog.w(TAG, "Failed to dexopt", e);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index c2e0992e7b79..b73d8f3b2705 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -92,6 +92,13 @@ import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
import static com.android.server.pm.InstructionSets.getPreferredInstructionSet;
import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.getFullCompilerFilter;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.REASON_BOOT;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.REASON_FORCED_DEXOPT;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.REASON_INSTALL;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.REASON_NON_SYSTEM_LIBRARY;
+import static com.android.server.pm.PackageManagerServiceCompilerMapping.REASON_SHARED_APK;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS;
import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
@@ -1956,6 +1963,9 @@ public class PackageManagerService extends IPackageManager.Stub {
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
+ // Self-check for initial settings.
+ PackageManagerServiceCompilerMapping.checkProperties();
+
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
m.enableSystemUserPackages();
@@ -2168,12 +2178,13 @@ public class PackageManagerService extends IPackageManager.Stub {
// AOT compilation (if needed).
int dexoptNeeded = DexFile.getDexOptNeeded(
lib, dexCodeInstructionSet,
- DexFile.COMPILATION_TYPE_FULL);
+ getCompilerFilterForReason(REASON_SHARED_APK),
+ false /* newProfile */);
if (dexoptNeeded != DexFile.NO_DEXOPT_NEEDED) {
mInstaller.dexopt(lib, Process.SYSTEM_UID, dexCodeInstructionSet,
dexoptNeeded, DEXOPT_PUBLIC /*dexFlags*/,
- StorageManager.UUID_PRIVATE_INTERNAL,
- false /*useProfiles*/);
+ getCompilerFilterForReason(REASON_SHARED_APK),
+ StorageManager.UUID_PRIVATE_INTERNAL);
}
} catch (FileNotFoundException e) {
Slog.w(TAG, "Library not found: " + lib);
@@ -6928,7 +6939,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// and would have to be patched (would be SELF_PATCHOAT, which is deprecated).
// Instead, force the extraction in this case.
performDexOpt(pkg.packageName, null /* instructionSet */,
- false /* useProfiles */, true /* extractOnly */, prunedCache);
+ false /* checkProfiles */, REASON_BOOT, prunedCache);
}
}
}
@@ -6947,29 +6958,37 @@ public class PackageManagerService extends IPackageManager.Stub {
// TODO: this is not used nor needed. Delete it.
@Override
public boolean performDexOptIfNeeded(String packageName, String instructionSet) {
- return performDexOptTraced(packageName, instructionSet, false /* useProfiles */,
- false /* extractOnly */, false /* force */);
+ return performDexOptTraced(packageName, instructionSet, false /* checkProfiles */,
+ getFullCompilerFilter(), false /* force */);
}
@Override
- public boolean performDexOpt(String packageName, String instructionSet, boolean useProfiles,
- boolean extractOnly, boolean force) {
- return performDexOptTraced(packageName, instructionSet, useProfiles, extractOnly, force);
+ public boolean performDexOpt(String packageName, String instructionSet,
+ boolean checkProfiles, int compileReason, boolean force) {
+ return performDexOptTraced(packageName, instructionSet, checkProfiles,
+ getCompilerFilterForReason(compileReason), force);
+ }
+
+ @Override
+ public boolean performDexOptMode(String packageName, String instructionSet,
+ boolean checkProfiles, String targetCompilerFilter, boolean force) {
+ return performDexOptTraced(packageName, instructionSet, checkProfiles,
+ targetCompilerFilter, force);
}
private boolean performDexOptTraced(String packageName, String instructionSet,
- boolean useProfiles, boolean extractOnly, boolean force) {
+ boolean checkProfiles, String targetCompilerFilter, boolean force) {
Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt");
try {
- return performDexOptInternal(packageName, instructionSet, useProfiles, extractOnly,
- force);
+ return performDexOptInternal(packageName, instructionSet, checkProfiles,
+ targetCompilerFilter, force);
} finally {
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
}
}
private boolean performDexOptInternal(String packageName, String instructionSet,
- boolean useProfiles, boolean extractOnly, boolean force) {
+ boolean checkProfiles, String targetCompilerFilter, boolean force) {
PackageParser.Package p;
final String targetInstructionSet;
synchronized (mPackages) {
@@ -6987,7 +7006,7 @@ public class PackageManagerService extends IPackageManager.Stub {
synchronized (mInstallLock) {
final String[] instructionSets = new String[] { targetInstructionSet };
int result = performDexOptInternalWithDependenciesLI(p, instructionSets,
- useProfiles, extractOnly, force);
+ checkProfiles, targetCompilerFilter, force);
return result == PackageDexOptimizer.DEX_OPT_PERFORMED;
}
} finally {
@@ -7008,7 +7027,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private int performDexOptInternalWithDependenciesLI(PackageParser.Package p,
- String instructionSets[], boolean useProfiles, boolean extractOnly, boolean force) {
+ String instructionSets[], boolean checkProfiles, String targetCompilerFilter,
+ boolean force) {
// Select the dex optimizer based on the force parameter.
// Note: The force option is rarely used (cmdline input for testing, mostly), so it's OK to
// allocate an object here.
@@ -7022,13 +7042,13 @@ public class PackageManagerService extends IPackageManager.Stub {
if (!deps.isEmpty()) {
for (PackageParser.Package depPackage : deps) {
// TODO: Analyze and investigate if we (should) profile libraries.
- // Currently this will do a full compilation of the library.
- pdo.performDexOpt(depPackage, instructionSets, false /* useProfiles */,
- false /* extractOnly */);
+ // Currently this will do a full compilation of the library by default.
+ pdo.performDexOpt(depPackage, instructionSets, false /* checkProfiles */,
+ getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY));
}
}
- return pdo.performDexOpt(p, instructionSets, useProfiles, extractOnly);
+ return pdo.performDexOpt(p, instructionSets, checkProfiles, targetCompilerFilter);
}
Collection<PackageParser.Package> findSharedNonSystemLibraries(PackageParser.Package p) {
@@ -7106,7 +7126,8 @@ public class PackageManagerService extends IPackageManager.Stub {
// Whoever is calling forceDexOpt wants a fully compiled package.
// Don't use profiles since that may cause compilation to be skipped.
final int res = performDexOptInternalWithDependenciesLI(pkg, instructionSets,
- false /* useProfiles */, false /* extractOnly */, true /* force */);
+ false /* checkProfiles */, getCompilerFilterForReason(REASON_FORCED_DEXOPT),
+ true /* force */);
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (res != PackageDexOptimizer.DEX_OPT_PERFORMED) {
@@ -10451,10 +10472,10 @@ public class PackageManagerService extends IPackageManager.Stub {
void startCleaningPackages() {
// reader
+ if (!isExternalMediaAvailable()) {
+ return;
+ }
synchronized (mPackages) {
- if (!isExternalMediaAvailable()) {
- return;
- }
if (mSettings.mPackagesToBeCleaned.isEmpty()) {
return;
}
@@ -13973,7 +13994,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Do not run PackageDexOptimizer through the local performDexOpt
// method because `pkg` is not in `mPackages` yet.
int result = mPackageDexOptimizer.performDexOpt(pkg, null /* instructionSets */,
- false /* useProfiles */, true /* extractOnly */);
+ false /* checkProfiles */, getCompilerFilterForReason(REASON_INSTALL));
Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
if (result == PackageDexOptimizer.DEX_OPT_FAILED) {
String msg = "Extracking package failed for " + pkgName;
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
new file mode 100644
index 000000000000..b53f8d143d96
--- /dev/null
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceCompilerMapping.java
@@ -0,0 +1,139 @@
+/*
+ * 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.
+ */
+
+package com.android.server.pm;
+
+import android.os.SystemProperties;
+
+import dalvik.system.DexFile;
+
+/**
+ * Manage (retrieve) mappings from compilation reason to compilation filter.
+ */
+class PackageManagerServiceCompilerMapping {
+ // Compilation reasons.
+ public static final int REASON_BOOT = 0;
+ public static final int REASON_INSTALL = 1;
+ public static final int REASON_BACKGROUND_DEXOPT = 2;
+ public static final int REASON_AB_OTA = 3;
+ public static final int REASON_NON_SYSTEM_LIBRARY = 4;
+ public static final int REASON_SHARED_APK = 5;
+ public static final int REASON_FORCED_DEXOPT = 6;
+
+ private static final int REASON_LAST = REASON_FORCED_DEXOPT;
+
+ // Names for compilation reasons.
+ static final String REASON_STRINGS[] = {
+ "boot", "install", "bg-dexopt", "ab-ota", "nsys-library", "shared-apk", "forced-dexopt"
+ };
+
+ // Static block to ensure the strings array is of the right length.
+ static {
+ if (REASON_LAST + 1 != REASON_STRINGS.length) {
+ throw new IllegalStateException("REASON_STRINGS not correct");
+ }
+ }
+
+ private static String getSystemPropertyName(int reason) {
+ if (reason < 0 || reason >= REASON_STRINGS.length) {
+ throw new IllegalArgumentException("reason " + reason + " invalid");
+ }
+
+ return "pm.dexopt." + REASON_STRINGS[reason];
+ }
+
+ // Load the property for the given reason and check for validity. This will throw an
+ // exception in case the reason or value are invalid.
+ private static String getAndCheckValidity(int reason) {
+ String sysPropValue = SystemProperties.get(getSystemPropertyName(reason));
+ if (sysPropValue == null || sysPropValue.isEmpty() ||
+ !DexFile.isValidCompilerFilter(sysPropValue)) {
+ throw new IllegalStateException("Value \"" + sysPropValue +"\" not valid "
+ + "(reason " + REASON_STRINGS[reason] + ")");
+ }
+
+ // Ensure that some reasons are not mapped to profile-guided filters.
+ switch (reason) {
+ case REASON_SHARED_APK:
+ case REASON_FORCED_DEXOPT:
+ if (DexFile.isProfileGuidedCompilerFilter(sysPropValue)) {
+ throw new IllegalStateException("\"" + sysPropValue + "\" is profile-guided, "
+ + "but not allowed for " + REASON_STRINGS[reason]);
+ }
+ break;
+ }
+
+ return sysPropValue;
+ }
+
+ // Check that the properties are set and valid.
+ // Note: this is done in a separate method so this class can be statically initialized.
+ static void checkProperties() {
+ // We're gonna check all properties and collect the exceptions, so we can give a general
+ // overview. Store the exceptions here.
+ RuntimeException toThrow = null;
+
+ for (int reason = 0; reason <= REASON_LAST; reason++) {
+ try {
+ // Check that the system property name is legal.
+ String sysPropName = getSystemPropertyName(reason);
+ if (sysPropName == null ||
+ sysPropName.isEmpty() ||
+ sysPropName.length() > SystemProperties.PROP_NAME_MAX) {
+ throw new IllegalStateException("Reason system property name \"" +
+ sysPropName +"\" for reason " + REASON_STRINGS[reason]);
+ }
+
+ // Check validity, ignore result.
+ getAndCheckValidity(reason);
+ } catch (Exception exc) {
+ if (toThrow == null) {
+ toThrow = new IllegalStateException("PMS compiler filter settings are bad.");
+ }
+ toThrow.addSuppressed(exc);
+ }
+ }
+
+ if (toThrow != null) {
+ throw toThrow;
+ }
+ }
+
+ public static String getCompilerFilterForReason(int reason) {
+ return getAndCheckValidity(reason);
+ }
+
+ /**
+ * Return the compiler filter for "full" compilation.
+ *
+ * We derive that from the traditional "dalvik.vm.dex2oat-filter" property and just make
+ * sure this isn't profile-guided. Returns "speed" in case of invalid (or missing) values.
+ */
+ public static String getFullCompilerFilter() {
+ String value = SystemProperties.get("dalvik.vm.dex2oat-filter");
+ if (value == null || value.isEmpty()) {
+ return "speed";
+ }
+
+ if (!DexFile.isValidCompilerFilter(value) ||
+ DexFile.isProfileGuidedCompilerFilter(value)) {
+ return "speed";
+ }
+
+ return value;
+ }
+
+}
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 319fc3741828..7f626b2f0303 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -50,6 +50,8 @@ import android.text.TextUtils;
import android.util.PrintWriterPrinter;
import com.android.internal.util.SizedInputStream;
+import dalvik.system.DexFile;
+
import libcore.io.IoUtils;
import java.io.File;
@@ -249,11 +251,38 @@ class PackageManagerShellCommand extends ShellCommand {
private int runCompile() throws RemoteException {
final PrintWriter pw = getOutPrintWriter();
boolean useJitProfiles = false;
- boolean extractOnly = false;
boolean forceCompilation = false;
boolean allPackages = false;
boolean clearProfileData = false;
- String compilationMode = "default";
+ String compilerFilter = null;
+ String compilationReason = null;
+
+ if (peekNextArg() == null) {
+ // No arguments, show help.
+ pw.println("Usage: cmd package compile [-c] [-f] [--reset] [-m mode] " +
+ "[-r reason] [-a|pkg]");
+ pw.println();
+ pw.println(" -c Clear profile data");
+ pw.println(" -f Force compilation");
+ pw.println(" --reset Reset package");
+ pw.println(" -m mode Compilation mode, one of the dex2oat compiler filters");
+ pw.println(" verify-none");
+ pw.println(" verify-at-runtime");
+ pw.println(" verify-profile");
+ pw.println(" interpret-only");
+ pw.println(" space-profile");
+ pw.println(" space");
+ pw.println(" speed-profile");
+ pw.println(" speed");
+ pw.println(" everything");
+ pw.println(" -r reason Compiler reason, one of the package manager reasons");
+ for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
+ pw.println(" " +
+ PackageManagerServiceCompilerMapping.REASON_STRINGS[i]);
+ }
+ pw.println(" -a Apply to all packages");
+ return 1;
+ }
String opt;
while ((opt = getNextOption()) != null) {
@@ -268,12 +297,15 @@ class PackageManagerShellCommand extends ShellCommand {
forceCompilation = true;
break;
case "-m":
- compilationMode = getNextArgRequired();
+ compilerFilter = getNextArgRequired();
+ break;
+ case "-r":
+ compilationReason = getNextArgRequired();
break;
case "--reset":
forceCompilation = true;
clearProfileData = true;
- compilationMode = "extract";
+ compilerFilter = "reset";
break;
default:
pw.println("Error: Unknown option: " + opt);
@@ -281,28 +313,56 @@ class PackageManagerShellCommand extends ShellCommand {
}
}
- switch (compilationMode) {
- case "default":
- useJitProfiles = SystemProperties.getBoolean("dalvik.vm.usejitprofiles", false);
- extractOnly = false;
- break;
- case "full":
- useJitProfiles = false;
- extractOnly = false;
- break;
- case "profile":
- useJitProfiles = true;
- extractOnly = false;
- break;
- case "extract":
- useJitProfiles = false;
- extractOnly = true;
- break;
- default:
- pw.println("Error: Unknown compilation mode: " + compilationMode);
+ if (compilerFilter != null && compilationReason != null) {
+ pw.println("Cannot use compilation filter (\"-m\") and compilation reason (\"-r\") " +
+ "at the same time");
+ return 1;
+ }
+ if (compilerFilter == null && compilationReason == null) {
+ pw.println("Cannot run without any of compilation filter (\"-m\") and compilation " +
+ "reason (\"-r\") at the same time");
+ return 1;
+ }
+
+ String targetCompilerFilter;
+ if (compilerFilter != null) {
+ // Specially recognize default and reset. Otherwise, only accept valid modes.
+ if ("default".equals(compilerFilter)) {
+ // Use the default mode for background dexopt.
+ targetCompilerFilter =
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+ PackageManagerServiceCompilerMapping.REASON_BACKGROUND_DEXOPT);
+ } else if ("reset".equals(compilerFilter)) {
+ // Use the default mode for install.
+ targetCompilerFilter =
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(
+ PackageManagerServiceCompilerMapping.REASON_INSTALL);
+ } else {
+ if (!DexFile.isValidCompilerFilter(compilerFilter)) {
+ pw.println("Error: \"" + compilerFilter +
+ "\" is not a valid compilation filter.");
+ return 1;
+ }
+ targetCompilerFilter = compilerFilter;
+ }
+ } else {
+ int reason = -1;
+ for (int i = 0; i < PackageManagerServiceCompilerMapping.REASON_STRINGS.length; i++) {
+ if (PackageManagerServiceCompilerMapping.REASON_STRINGS[i].equals(
+ compilationReason)) {
+ reason = i;
+ break;
+ }
+ }
+ if (reason == -1) {
+ pw.println("Error: Unknown compilation reason: " + compilationReason);
return 1;
+ }
+ targetCompilerFilter =
+ PackageManagerServiceCompilerMapping.getCompilerFilterForReason(reason);
}
+
List<String> packageNames = null;
if (allPackages) {
packageNames = mInterface.getAllPackages();
@@ -321,8 +381,8 @@ class PackageManagerShellCommand extends ShellCommand {
mInterface.clearApplicationProfileData(packageName);
}
- boolean result = mInterface.performDexOpt(packageName, null /* instructionSet */,
- useJitProfiles, extractOnly, forceCompilation);
+ boolean result = mInterface.performDexOptMode(packageName, null /* instructionSet */,
+ useJitProfiles, targetCompilerFilter, forceCompilation);
if (!result) {
failedPackages.add(packageName);
}
diff --git a/services/core/java/com/android/server/pm/ShortcutLauncher.java b/services/core/java/com/android/server/pm/ShortcutLauncher.java
new file mode 100644
index 000000000000..f1920c7e8e22
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ShortcutLauncher.java
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.pm.ShortcutInfo;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.List;
+
+/**
+ * Launcher information used by {@link ShortcutService}.
+ */
+class ShortcutLauncher {
+ private static final String TAG = ShortcutService.TAG;
+
+ static final String TAG_ROOT = "launcher-pins";
+
+ private static final String TAG_PACKAGE = "package";
+ private static final String TAG_PIN = "pin";
+
+ private static final String ATTR_VALUE = "value";
+ private static final String ATTR_PACKAGE_NAME = "package-name";
+
+ @UserIdInt
+ final int mUserId;
+
+ @NonNull
+ final String mPackageName;
+
+ /**
+ * Package name -> IDs.
+ */
+ final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
+
+ ShortcutLauncher(@UserIdInt int userId, @NonNull String packageName) {
+ mUserId = userId;
+ mPackageName = packageName;
+ }
+
+ public void pinShortcuts(@NonNull ShortcutService s, @NonNull String packageName,
+ @NonNull List<String> ids) {
+ final int idSize = ids.size();
+ if (idSize == 0) {
+ mPinnedShortcuts.remove(packageName);
+ } else {
+ final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName);
+
+ // Pin shortcuts. Make sure only pin the ones that were visible to the caller.
+ // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
+
+ final ShortcutPackage packageShortcuts =
+ s.getPackageShortcutsLocked(packageName, mUserId);
+ final ArraySet<String> newSet = new ArraySet<>();
+
+ for (int i = 0; i < idSize; i++) {
+ final String id = ids.get(i);
+ final ShortcutInfo si = packageShortcuts.findShortcutById(id);
+ if (si == null) {
+ continue;
+ }
+ if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) {
+ newSet.add(id);
+ }
+ }
+ mPinnedShortcuts.put(packageName, newSet);
+ }
+ s.getPackageShortcutsLocked(packageName, mUserId).refreshPinnedFlags(s);
+ }
+
+ /**
+ * Return the pinned shortcut IDs for the publisher package.
+ */
+ public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) {
+ return mPinnedShortcuts.get(packageName);
+ }
+
+ boolean cleanUpPackage(String packageName) {
+ return mPinnedShortcuts.remove(packageName) != null;
+ }
+
+ /**
+ * Persist.
+ */
+ public void saveToXml(XmlSerializer out) throws IOException {
+ final int size = mPinnedShortcuts.size();
+ if (size == 0) {
+ return; // Nothing to write.
+ }
+
+ out.startTag(null, TAG_ROOT);
+ ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
+ mPackageName);
+
+ for (int i = 0; i < size; i++) {
+ out.startTag(null, TAG_PACKAGE);
+ ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
+ mPinnedShortcuts.keyAt(i));
+
+ final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+ final int idSize = ids.size();
+ for (int j = 0; j < idSize; j++) {
+ ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j));
+ }
+ out.endTag(null, TAG_PACKAGE);
+ }
+
+ out.endTag(null, TAG_ROOT);
+ }
+
+ /**
+ * Load.
+ */
+ public static ShortcutLauncher loadFromXml(XmlPullParser parser, int userId)
+ throws IOException, XmlPullParserException {
+ final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
+ ATTR_PACKAGE_NAME);
+
+ final ShortcutLauncher ret = new ShortcutLauncher(userId, launcherPackageName);
+
+ ArraySet<String> ids = null;
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ final int depth = parser.getDepth();
+ final String tag = parser.getName();
+ switch (tag) {
+ case TAG_PACKAGE: {
+ final String packageName = ShortcutService.parseStringAttribute(parser,
+ ATTR_PACKAGE_NAME);
+ ids = new ArraySet<>();
+ ret.mPinnedShortcuts.put(packageName, ids);
+ continue;
+ }
+ case TAG_PIN: {
+ ids.add(ShortcutService.parseStringAttribute(parser,
+ ATTR_VALUE));
+ continue;
+ }
+ }
+ throw ShortcutService.throwForInvalidTag(depth, tag);
+ }
+ return ret;
+ }
+
+ public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.println();
+
+ pw.print(prefix);
+ pw.print("Launcher: ");
+ pw.print(mPackageName);
+ pw.println();
+
+ final int size = mPinnedShortcuts.size();
+ for (int i = 0; i < size; i++) {
+ pw.println();
+
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("Package: ");
+ pw.println(mPinnedShortcuts.keyAt(i));
+
+ final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
+ final int idSize = ids.size();
+
+ for (int j = 0; j < idSize; j++) {
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print(ids.valueAt(j));
+ pw.println();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
new file mode 100644
index 000000000000..d6142510015e
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -0,0 +1,520 @@
+/*
+ * 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.
+ */
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
+import android.os.PersistableBundle;
+import android.text.format.Formatter;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Slog;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.Predicate;
+
+/**
+ * Package information used by {@link ShortcutService}.
+ */
+class ShortcutPackage {
+ private static final String TAG = ShortcutService.TAG;
+
+ static final String TAG_ROOT = "package";
+ private static final String TAG_INTENT_EXTRAS = "intent-extras";
+ private static final String TAG_EXTRAS = "extras";
+ private static final String TAG_SHORTCUT = "shortcut";
+
+ private static final String ATTR_NAME = "name";
+ private static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
+ private static final String ATTR_CALL_COUNT = "call-count";
+ private static final String ATTR_LAST_RESET = "last-reset";
+ private static final String ATTR_ID = "id";
+ private static final String ATTR_ACTIVITY = "activity";
+ private static final String ATTR_TITLE = "title";
+ private static final String ATTR_INTENT = "intent";
+ private static final String ATTR_WEIGHT = "weight";
+ private static final String ATTR_TIMESTAMP = "timestamp";
+ private static final String ATTR_FLAGS = "flags";
+ private static final String ATTR_ICON_RES = "icon-res";
+ private static final String ATTR_BITMAP_PATH = "bitmap-path";
+
+ @UserIdInt
+ final int mUserId;
+
+ @NonNull
+ final String mPackageName;
+
+ /**
+ * All the shortcuts from the package, keyed on IDs.
+ */
+ final private ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
+
+ /**
+ * # of dynamic shortcuts.
+ */
+ private int mDynamicShortcutCount = 0;
+
+ /**
+ * # of times the package has called rate-limited APIs.
+ */
+ private int mApiCallCount;
+
+ /**
+ * When {@link #mApiCallCount} was reset last time.
+ */
+ private long mLastResetTime;
+
+ ShortcutPackage(int userId, String packageName) {
+ mUserId = userId;
+ mPackageName = packageName;
+ }
+
+ @Nullable
+ public ShortcutInfo findShortcutById(String id) {
+ return mShortcuts.get(id);
+ }
+
+ private ShortcutInfo deleteShortcut(@NonNull ShortcutService s,
+ @NonNull String id) {
+ final ShortcutInfo shortcut = mShortcuts.remove(id);
+ if (shortcut != null) {
+ s.removeIcon(mUserId, shortcut);
+ shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED);
+ }
+ return shortcut;
+ }
+
+ void addShortcut(@NonNull ShortcutService s, @NonNull ShortcutInfo newShortcut) {
+ deleteShortcut(s, newShortcut.getId());
+ s.saveIconAndFixUpShortcut(mUserId, newShortcut);
+ mShortcuts.put(newShortcut.getId(), newShortcut);
+ }
+
+ /**
+ * Add a shortcut, or update one with the same ID, with taking over existing flags.
+ *
+ * It checks the max number of dynamic shortcuts.
+ */
+ public void addDynamicShortcut(@NonNull ShortcutService s,
+ @NonNull ShortcutInfo newShortcut) {
+ newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
+
+ final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
+
+ final boolean wasPinned;
+ final int newDynamicCount;
+
+ if (oldShortcut == null) {
+ wasPinned = false;
+ newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
+ } else {
+ wasPinned = oldShortcut.isPinned();
+ if (oldShortcut.isDynamic()) {
+ newDynamicCount = mDynamicShortcutCount; // not adding a dynamic shortcut.
+ } else {
+ newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
+ }
+ }
+
+ // Make sure there's still room.
+ s.enforceMaxDynamicShortcuts(newDynamicCount);
+
+ // Okay, make it dynamic and add.
+ if (wasPinned) {
+ newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
+ }
+
+ addShortcut(s, newShortcut);
+ mDynamicShortcutCount = newDynamicCount;
+ }
+
+ /**
+ * Remove all shortcuts that aren't pinned nor dynamic.
+ */
+ private void removeOrphans(@NonNull ShortcutService s) {
+ ArrayList<String> removeList = null; // Lazily initialize.
+
+ for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+ final ShortcutInfo si = mShortcuts.valueAt(i);
+
+ if (si.isPinned() || si.isDynamic()) continue;
+
+ if (removeList == null) {
+ removeList = new ArrayList<>();
+ }
+ removeList.add(si.getId());
+ }
+ if (removeList != null) {
+ for (int i = removeList.size() - 1; i >= 0; i--) {
+ deleteShortcut(s, removeList.get(i));
+ }
+ }
+ }
+
+ /**
+ * Remove all dynamic shortcuts.
+ */
+ public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
+ for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+ mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+ }
+ removeOrphans(s);
+ mDynamicShortcutCount = 0;
+ }
+
+ /**
+ * Remove a dynamic shortcut by ID.
+ */
+ public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
+ final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
+
+ if (oldShortcut == null) {
+ return;
+ }
+ if (oldShortcut.isDynamic()) {
+ mDynamicShortcutCount--;
+ }
+ if (oldShortcut.isPinned()) {
+ oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
+ } else {
+ deleteShortcut(s, shortcutId);
+ }
+ }
+
+ /**
+ * Called after a launcher updates the pinned set. For each shortcut in this package,
+ * set FLAG_PINNED if any launcher has pinned it. Otherwise, clear it.
+ *
+ * <p>Then remove all shortcuts that are not dynamic and no longer pinned either.
+ */
+ public void refreshPinnedFlags(@NonNull ShortcutService s) {
+ // First, un-pin all shortcuts
+ for (int i = mShortcuts.size() - 1; i >= 0; i--) {
+ mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
+ }
+
+ // Then, for the pinned set for each launcher, set the pin flag one by one.
+ final ArrayMap<String, ShortcutLauncher> launchers =
+ s.getUserShortcutsLocked(mUserId).getLaunchers();
+
+ for (int l = launchers.size() - 1; l >= 0; l--) {
+ final ShortcutLauncher launcherShortcuts = launchers.valueAt(l);
+ final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(mPackageName);
+
+ if (pinned == null || pinned.size() == 0) {
+ continue;
+ }
+ for (int i = pinned.size() - 1; i >= 0; i--) {
+ final ShortcutInfo si = mShortcuts.get(pinned.valueAt(i));
+ if (si == null) {
+ s.wtf("Shortcut not found");
+ } else {
+ si.addFlags(ShortcutInfo.FLAG_PINNED);
+ }
+ }
+ }
+
+ // Lastly, remove the ones that are no longer pinned nor dynamic.
+ removeOrphans(s);
+ }
+
+ /**
+ * Number of calls that the caller has made, since the last reset.
+ */
+ public int getApiCallCount(@NonNull ShortcutService s) {
+ final long last = s.getLastResetTimeLocked();
+
+ final long now = s.injectCurrentTimeMillis();
+ if (ShortcutService.isClockValid(now) && mLastResetTime > now) {
+ Slog.w(TAG, "Clock rewound");
+ // Clock rewound.
+ mLastResetTime = now;
+ mApiCallCount = 0;
+ return mApiCallCount;
+ }
+
+ // If not reset yet, then reset.
+ if (mLastResetTime < last) {
+ if (ShortcutService.DEBUG) {
+ Slog.d(TAG, String.format("My last reset=%d, now=%d, last=%d: resetting",
+ mLastResetTime, now, last));
+ }
+ mApiCallCount = 0;
+ mLastResetTime = last;
+ }
+ return mApiCallCount;
+ }
+
+ /**
+ * If the caller app hasn't been throttled yet, increment {@link #mApiCallCount}
+ * and return true. Otherwise just return false.
+ */
+ public boolean tryApiCall(@NonNull ShortcutService s) {
+ if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
+ return false;
+ }
+ mApiCallCount++;
+ return true;
+ }
+
+ public void resetRateLimitingForCommandLine() {
+ mApiCallCount = 0;
+ mLastResetTime = 0;
+ }
+
+ /**
+ * Find all shortcuts that match {@code query}.
+ */
+ public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
+ @Nullable Predicate<ShortcutInfo> query, int cloneFlag,
+ @Nullable String callingLauncher) {
+
+ // Set of pinned shortcuts by the calling launcher.
+ final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
+ : s.getLauncherShortcuts(callingLauncher, mUserId)
+ .getPinnedShortcutIds(mPackageName);
+
+ for (int i = 0; i < mShortcuts.size(); i++) {
+ final ShortcutInfo si = mShortcuts.valueAt(i);
+
+ // If it's called by non-launcher (i.e. publisher, always include -> true.
+ // Otherwise, only include non-dynamic pinned one, if the calling launcher has pinned
+ // it.
+ final boolean isPinnedByCaller = (callingLauncher == null)
+ || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId()));
+ if (!si.isDynamic()) {
+ if (!si.isPinned()) {
+ s.wtf("Shortcut not pinned here");
+ continue;
+ }
+ if (!isPinnedByCaller) {
+ continue;
+ }
+ }
+ final ShortcutInfo clone = si.clone(cloneFlag);
+ // Fix up isPinned for the caller. Note we need to do it before the "test" callback,
+ // since it may check isPinned.
+ if (!isPinnedByCaller) {
+ clone.clearFlags(ShortcutInfo.FLAG_PINNED);
+ }
+ if (query == null || query.test(clone)) {
+ result.add(clone);
+ }
+ }
+ }
+
+ public void resetThrottling() {
+ mApiCallCount = 0;
+ }
+
+ public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.println();
+
+ pw.print(prefix);
+ pw.print("Package: ");
+ pw.print(mPackageName);
+ pw.println();
+
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("Calls: ");
+ pw.print(getApiCallCount(s));
+ pw.println();
+
+ // This should be after getApiCallCount(), which may update it.
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("Last reset: [");
+ pw.print(mLastResetTime);
+ pw.print("] ");
+ pw.print(s.formatTime(mLastResetTime));
+ pw.println();
+
+ pw.println(" Shortcuts:");
+ long totalBitmapSize = 0;
+ final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
+ final int size = shortcuts.size();
+ for (int i = 0; i < size; i++) {
+ final ShortcutInfo si = shortcuts.valueAt(i);
+ pw.print(" ");
+ pw.println(si.toInsecureString());
+ if (si.getBitmapPath() != null) {
+ final long len = new File(si.getBitmapPath()).length();
+ pw.print(" ");
+ pw.print("bitmap size=");
+ pw.println(len);
+
+ totalBitmapSize += len;
+ }
+ }
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("Total bitmap size: ");
+ pw.print(totalBitmapSize);
+ pw.print(" (");
+ pw.print(Formatter.formatFileSize(s.mContext, totalBitmapSize));
+ pw.println(")");
+ }
+
+ public void saveToXml(@NonNull XmlSerializer out) throws IOException, XmlPullParserException {
+ final int size = mShortcuts.size();
+
+ if (size == 0 && mApiCallCount == 0) {
+ return; // nothing to write.
+ }
+
+ out.startTag(null, TAG_ROOT);
+
+ ShortcutService.writeAttr(out, ATTR_NAME, mPackageName);
+ ShortcutService.writeAttr(out, ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
+ ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
+ ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
+
+ for (int j = 0; j < size; j++) {
+ saveShortcut(out, mShortcuts.valueAt(j));
+ }
+
+ out.endTag(null, TAG_ROOT);
+ }
+
+ private static void saveShortcut(XmlSerializer out, ShortcutInfo si)
+ throws IOException, XmlPullParserException {
+ out.startTag(null, TAG_SHORTCUT);
+ ShortcutService.writeAttr(out, ATTR_ID, si.getId());
+ // writeAttr(out, "package", si.getPackageName()); // not needed
+ ShortcutService.writeAttr(out, ATTR_ACTIVITY, si.getActivityComponent());
+ // writeAttr(out, "icon", si.getIcon()); // We don't save it.
+ ShortcutService.writeAttr(out, ATTR_TITLE, si.getTitle());
+ ShortcutService.writeAttr(out, ATTR_INTENT, si.getIntentNoExtras());
+ ShortcutService.writeAttr(out, ATTR_WEIGHT, si.getWeight());
+ ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
+ si.getLastChangedTimestamp());
+ ShortcutService.writeAttr(out, ATTR_FLAGS, si.getFlags());
+ ShortcutService.writeAttr(out, ATTR_ICON_RES, si.getIconResourceId());
+ ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
+
+ ShortcutService.writeTagExtra(out, TAG_INTENT_EXTRAS,
+ si.getIntentPersistableExtras());
+ ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
+
+ out.endTag(null, TAG_SHORTCUT);
+ }
+
+ public static ShortcutPackage loadFromXml(XmlPullParser parser, int userId)
+ throws IOException, XmlPullParserException {
+
+ final String packageName = ShortcutService.parseStringAttribute(parser,
+ ATTR_NAME);
+
+ final ShortcutPackage ret = new ShortcutPackage(userId, packageName);
+
+ ret.mDynamicShortcutCount =
+ ShortcutService.parseIntAttribute(parser, ATTR_DYNAMIC_COUNT);
+ ret.mApiCallCount =
+ ShortcutService.parseIntAttribute(parser, ATTR_CALL_COUNT);
+ ret.mLastResetTime =
+ ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
+
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ final int depth = parser.getDepth();
+ final String tag = parser.getName();
+ switch (tag) {
+ case TAG_SHORTCUT:
+ final ShortcutInfo si = parseShortcut(parser, packageName);
+
+ // Don't use addShortcut(), we don't need to save the icon.
+ ret.mShortcuts.put(si.getId(), si);
+ continue;
+ }
+ throw ShortcutService.throwForInvalidTag(depth, tag);
+ }
+ return ret;
+ }
+
+ private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName)
+ throws IOException, XmlPullParserException {
+ String id;
+ ComponentName activityComponent;
+ // Icon icon;
+ String title;
+ Intent intent;
+ PersistableBundle intentPersistableExtras = null;
+ int weight;
+ PersistableBundle extras = null;
+ long lastChangedTimestamp;
+ int flags;
+ int iconRes;
+ String bitmapPath;
+
+ id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
+ activityComponent = ShortcutService.parseComponentNameAttribute(parser,
+ ATTR_ACTIVITY);
+ title = ShortcutService.parseStringAttribute(parser, ATTR_TITLE);
+ intent = ShortcutService.parseIntentAttribute(parser, ATTR_INTENT);
+ weight = (int) ShortcutService.parseLongAttribute(parser, ATTR_WEIGHT);
+ lastChangedTimestamp = (int) ShortcutService.parseLongAttribute(parser,
+ ATTR_TIMESTAMP);
+ flags = (int) ShortcutService.parseLongAttribute(parser, ATTR_FLAGS);
+ iconRes = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES);
+ bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH);
+
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ final int depth = parser.getDepth();
+ final String tag = parser.getName();
+ if (ShortcutService.DEBUG_LOAD) {
+ Slog.d(TAG, String.format(" depth=%d type=%d name=%s",
+ depth, type, tag));
+ }
+ switch (tag) {
+ case TAG_INTENT_EXTRAS:
+ intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
+ continue;
+ case TAG_EXTRAS:
+ extras = PersistableBundle.restoreFromXml(parser);
+ continue;
+ }
+ throw ShortcutService.throwForInvalidTag(depth, tag);
+ }
+ return new ShortcutInfo(
+ id, packageName, activityComponent, /* icon =*/ null, title, intent,
+ intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
+ iconRes, bitmapPath);
+ }
+}
diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java
index e831bb1a67ee..42954f528a2b 100644
--- a/services/core/java/com/android/server/pm/ShortcutService.java
+++ b/services/core/java/com/android/server/pm/ShortcutService.java
@@ -53,6 +53,7 @@ import android.os.ResultReceiver;
import android.os.SELinux;
import android.os.ShellCommand;
import android.os.UserHandle;
+import android.os.UserManager;
import android.text.TextUtils;
import android.text.format.Formatter;
import android.text.format.Time;
@@ -67,6 +68,7 @@ import android.util.Xml;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.Preconditions;
@@ -99,6 +101,11 @@ import java.util.function.Predicate;
*
* - Default launcher check does take a few ms. Worth caching.
*
+ * - Allow non-default launcher to start pinned shortcuts. (but not dynamic.)
+ *
+ * - Extract the user/package/launcher classes to their own files. Maybe rename so they all have
+ * the same "Shortcut" prefix.
+ *
* - Listen to PACKAGE_*, remove orphan info, update timestamp for icon res
* -> Need to scan all packages when a user starts too.
* -> Clear data -> remove all dynamic? but not the pinned?
@@ -215,7 +222,7 @@ public class ShortcutService extends IShortcutService.Stub {
* User ID -> UserShortcuts
*/
@GuardedBy("mLock")
- private final SparseArray<UserShortcuts> mUsers = new SparseArray<>();
+ private final SparseArray<ShortcutUser> mUsers = new SparseArray<>();
/**
* Max number of dynamic shortcuts that each application can have at a time.
@@ -243,6 +250,7 @@ public class ShortcutService extends IShortcutService.Stub {
private int mSaveDelayMillis;
private final PackageManagerInternal mPackageManagerInternal;
+ private final UserManager mUserManager;
@GuardedBy("mLock")
private List<Integer> mDirtyUserIds = new ArrayList<>();
@@ -257,6 +265,9 @@ public class ShortcutService extends IShortcutService.Stub {
LocalServices.addService(ShortcutServiceInternal.class, new LocalService());
mHandler = new Handler(looper);
mPackageManagerInternal = LocalServices.getService(PackageManagerInternal.class);
+ mUserManager = context.getSystemService(UserManager.class);
+
+ mPackageMonitor.register(context, looper, UserHandle.ALL, /* externalStorage= */ false);
}
/**
@@ -282,16 +293,12 @@ public class ShortcutService extends IShortcutService.Stub {
@Override
public void onCleanupUser(int userHandle) {
- synchronized (mService.mLock) {
- mService.onCleanupUserLocked(userHandle);
- }
+ mService.handleCleanupUser(userHandle);
}
@Override
public void onUnlockUser(int userId) {
- synchronized (mService.mLock) {
- mService.onStartUserLocked(userId);
- }
+ mService.handleUnlockUser(userId);
}
}
@@ -308,13 +315,24 @@ public class ShortcutService extends IShortcutService.Stub {
}
/** lifecycle event */
- void onStartUserLocked(int userId) {
- // Preload
- getUserShortcutsLocked(userId);
+ void handleUnlockUser(int userId) {
+ synchronized (mLock) {
+ // Preload
+ getUserShortcutsLocked(userId);
+ }
}
/** lifecycle event */
- void onCleanupUserLocked(int userId) {
+ void handleCleanupUser(int userId) {
+ synchronized (mLock) {
+ unloadUserLocked(userId);
+ }
+ }
+
+ private void unloadUserLocked(int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "unloadUserLocked: user=" + userId);
+ }
// Save all dirty information.
saveDirtyInfo();
@@ -615,7 +633,7 @@ public class ShortcutService extends IShortcutService.Stub {
}
@Nullable
- private UserShortcuts loadUserLocked(@UserIdInt int userId) {
+ private ShortcutUser loadUserLocked(@UserIdInt int userId) {
final File path = new File(injectUserDataPath(userId), FILENAME_USER_PACKAGES);
if (DEBUG) {
Slog.d(TAG, "Loading from " + path);
@@ -631,7 +649,7 @@ public class ShortcutService extends IShortcutService.Stub {
}
return null;
}
- UserShortcuts ret = null;
+ ShortcutUser ret = null;
try {
XmlPullParser parser = Xml.newPullParser();
parser.setInput(in, StandardCharsets.UTF_8.name());
@@ -648,8 +666,8 @@ public class ShortcutService extends IShortcutService.Stub {
Slog.d(TAG, String.format("depth=%d type=%d name=%s",
depth, type, tag));
}
- if ((depth == 1) && UserShortcuts.TAG_ROOT.equals(tag)) {
- ret = UserShortcuts.loadFromXml(parser, userId);
+ if ((depth == 1) && ShortcutUser.TAG_ROOT.equals(tag)) {
+ ret = ShortcutUser.loadFromXml(parser, userId);
continue;
}
throwForInvalidTag(depth, tag);
@@ -752,15 +770,21 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
+ @GuardedBy("mLock")
+ @NonNull
+ boolean isUserLoadedLocked(@UserIdInt int userId) {
+ return mUsers.get(userId) != null;
+ }
+
/** Return the per-user state. */
@GuardedBy("mLock")
@NonNull
- UserShortcuts getUserShortcutsLocked(@UserIdInt int userId) {
- UserShortcuts userPackages = mUsers.get(userId);
+ ShortcutUser getUserShortcutsLocked(@UserIdInt int userId) {
+ ShortcutUser userPackages = mUsers.get(userId);
if (userPackages == null) {
userPackages = loadUserLocked(userId);
if (userPackages == null) {
- userPackages = new UserShortcuts(userId);
+ userPackages = new ShortcutUser(userId);
}
mUsers.put(userId, userPackages);
}
@@ -770,14 +794,14 @@ public class ShortcutService extends IShortcutService.Stub {
/** Return the per-user per-package state. */
@GuardedBy("mLock")
@NonNull
- PackageShortcuts getPackageShortcutsLocked(
+ ShortcutPackage getPackageShortcutsLocked(
@NonNull String packageName, @UserIdInt int userId) {
return getUserShortcutsLocked(userId).getPackageShortcuts(packageName);
}
@GuardedBy("mLock")
@NonNull
- LauncherShortcuts getLauncherShortcuts(
+ ShortcutLauncher getLauncherShortcuts(
@NonNull String packageName, @UserIdInt int userId) {
return getUserShortcutsLocked(userId).getLauncherShortcuts(packageName);
}
@@ -1047,6 +1071,9 @@ public class ShortcutService extends IShortcutService.Stub {
}
private void notifyListeners(@NonNull String packageName, @UserIdInt int userId) {
+ if (!mUserManager.isUserRunning(userId)) {
+ return;
+ }
postToHandler(() -> {
final ArrayList<ShortcutChangeListener> copy;
synchronized (mLock) {
@@ -1142,7 +1169,7 @@ public class ShortcutService extends IShortcutService.Stub {
final int size = newShortcuts.size();
synchronized (mLock) {
- final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);
+ final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
// Throttling.
if (!ps.tryApiCall(this)) {
@@ -1177,7 +1204,7 @@ public class ShortcutService extends IShortcutService.Stub {
final int size = newShortcuts.size();
synchronized (mLock) {
- final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);
+ final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
// Throttling.
if (!ps.tryApiCall(this)) {
@@ -1214,7 +1241,7 @@ public class ShortcutService extends IShortcutService.Stub {
verifyCaller(packageName, userId);
synchronized (mLock) {
- final PackageShortcuts ps = getPackageShortcutsLocked(packageName, userId);
+ final ShortcutPackage ps = getPackageShortcutsLocked(packageName, userId);
// Throttling.
if (!ps.tryApiCall(this)) {
@@ -1354,7 +1381,7 @@ public class ShortcutService extends IShortcutService.Stub {
start = System.currentTimeMillis();
}
- final UserShortcuts user = getUserShortcutsLocked(userId);
+ final ShortcutUser user = getUserShortcutsLocked(userId);
final List<ResolveInfo> allHomeCandidates = new ArrayList<>();
@@ -1420,6 +1447,44 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
+ // === House keeping ===
+
+ @VisibleForTesting
+ void cleanUpPackageLocked(String packageName, int userId) {
+ final boolean wasUserLoaded = isUserLoadedLocked(userId);
+
+ final ShortcutUser mUser = getUserShortcutsLocked(userId);
+ boolean doNotify = false;
+
+ // First, remove the package from the package list (if the package is a publisher).
+ if (mUser.getPackages().remove(packageName) != null) {
+ doNotify = true;
+ }
+ // Also remove from the launcher list (if the package is a launcher).
+ mUser.getLaunchers().remove(packageName);
+
+ // Then remove pinned shortcuts from all launchers.
+ for (int i = mUser.getLaunchers().size() - 1; i >= 0; i--) {
+ mUser.getLaunchers().valueAt(i).cleanUpPackage(packageName);
+ }
+ // Now there may be orphan shortcuts because we removed pinned shortucts at the previous
+ // step. Remove them too.
+ for (int i = mUser.getPackages().size() - 1; i >= 0; i--) {
+ mUser.getPackages().valueAt(i).refreshPinnedFlags(this);
+ }
+
+ scheduleSaveUser(userId);
+
+ if (doNotify) {
+ notifyListeners(packageName, userId);
+ }
+
+ if (!wasUserLoaded) {
+ // Note this will execute the scheduled save.
+ unloadUserLocked(userId);
+ }
+ }
+
/**
* Entry point from {@link LauncherApps}.
*/
@@ -1441,7 +1506,7 @@ public class ShortcutService extends IShortcutService.Stub {
callingPackage, packageName, changedSince,
componentName, queryFlags, userId, ret, cloneFlag);
} else {
- final ArrayMap<String, PackageShortcuts> packages =
+ final ArrayMap<String, ShortcutPackage> packages =
getUserShortcutsLocked(userId).getPackages();
for (int i = packages.size() - 1; i >= 0; i--) {
getShortcutsInnerLocked(
@@ -1575,6 +1640,50 @@ public class ShortcutService extends IShortcutService.Stub {
}
}
+ private PackageMonitor mPackageMonitor = new PackageMonitor() {
+ @Override
+ public void onPackageUpdateFinished(String packageName, int uid) {
+ handlePackageUpdateFinished(packageName, getChangingUserId());
+ }
+
+ @Override
+ public void onPackageRemoved(String packageName, int uid) {
+ handlePackageRemoved(packageName, getChangingUserId());
+ }
+
+ @Override
+ public void onPackageRemovedAllUsers(String packageName, int uid) {
+ handlePackageRemovedAllUsers(packageName, getChangingUserId());
+ }
+ };
+
+ void handlePackageUpdateFinished(String packageName, @UserIdInt int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "onPackageUpdateFinished() userId=" + userId);
+ }
+ // TODO Update the version.
+ }
+
+ void handlePackageRemoved(String packageName, @UserIdInt int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "onPackageRemoved() userId=" + userId);
+ }
+ synchronized (mLock) {
+ cleanUpPackageLocked(packageName, userId);
+ }
+ }
+
+ void handlePackageRemovedAllUsers(String packageName, @UserIdInt int userId) {
+ if (DEBUG) {
+ Slog.d(TAG, "onPackageRemovedAllUsers() userId=" + userId);
+ }
+ synchronized (mLock) {
+ cleanUpPackageLocked(packageName, userId);
+ }
+
+ // TODO Remove from all users, which we can't if the user is locked.
+ }
+
// === Dump ===
@Override
@@ -1823,25 +1932,29 @@ public class ShortcutService extends IShortcutService.Stub {
// === Unit test support ===
// Injection point.
+ @VisibleForTesting
long injectCurrentTimeMillis() {
return System.currentTimeMillis();
}
// Injection point.
+ @VisibleForTesting
int injectBinderCallingUid() {
return getCallingUid();
}
- final int getCallingUserId() {
+ private int getCallingUserId() {
return UserHandle.getUserId(injectBinderCallingUid());
}
// Injection point.
+ @VisibleForTesting
long injectClearCallingIdentity() {
return Binder.clearCallingIdentity();
}
// Injection point.
+ @VisibleForTesting
void injectRestoreCallingIdentity(long token) {
Binder.restoreCallingIdentity(token);
}
@@ -1854,10 +1967,12 @@ public class ShortcutService extends IShortcutService.Stub {
Slog.wtf(TAG, message, e);
}
+ @VisibleForTesting
File injectSystemDataPath() {
return Environment.getDataSystemDirectory();
}
+ @VisibleForTesting
File injectUserDataPath(@UserIdInt int userId) {
return new File(Environment.getDataSystemCeDirectory(userId), DIRECTORY_PER_USER);
}
@@ -1867,16 +1982,18 @@ public class ShortcutService extends IShortcutService.Stub {
return ActivityManager.isLowRamDeviceStatic();
}
+ @VisibleForTesting
PackageManagerInternal injectPackageManagerInternal() {
return mPackageManagerInternal;
}
+ @VisibleForTesting
File getUserBitmapFilePath(@UserIdInt int userId) {
return new File(injectUserDataPath(userId), DIRECTORY_BITMAPS);
}
@VisibleForTesting
- SparseArray<UserShortcuts> getShortcutsForTest() {
+ SparseArray<ShortcutUser> getShortcutsForTest() {
return mUsers;
}
@@ -1913,790 +2030,13 @@ public class ShortcutService extends IShortcutService.Stub {
@VisibleForTesting
ShortcutInfo getPackageShortcutForTest(String packageName, String shortcutId, int userId) {
synchronized (mLock) {
- return getPackageShortcutsLocked(packageName, userId).findShortcutById(shortcutId);
- }
- }
-}
-
-/**
- * Per-user information.
- */
-class UserShortcuts {
- private static final String TAG = ShortcutService.TAG;
-
- static final String TAG_ROOT = "user";
- private static final String TAG_LAUNCHER = "launcher";
-
- private static final String ATTR_VALUE = "value";
-
- @UserIdInt
- final int mUserId;
-
- private final ArrayMap<String, PackageShortcuts> mPackages = new ArrayMap<>();
-
- private final ArrayMap<String, LauncherShortcuts> mLaunchers = new ArrayMap<>();
-
- private ComponentName mLauncherComponent;
-
- public UserShortcuts(int userId) {
- mUserId = userId;
- }
-
- public ArrayMap<String, PackageShortcuts> getPackages() {
- return mPackages;
- }
-
- public ArrayMap<String, LauncherShortcuts> getLaunchers() {
- return mLaunchers;
- }
-
- public PackageShortcuts getPackageShortcuts(@NonNull String packageName) {
- PackageShortcuts ret = mPackages.get(packageName);
- if (ret == null) {
- ret = new PackageShortcuts(mUserId, packageName);
- mPackages.put(packageName, ret);
- }
- return ret;
- }
-
- public LauncherShortcuts getLauncherShortcuts(@NonNull String packageName) {
- LauncherShortcuts ret = mLaunchers.get(packageName);
- if (ret == null) {
- ret = new LauncherShortcuts(mUserId, packageName);
- mLaunchers.put(packageName, ret);
- }
- return ret;
- }
-
- public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
- out.startTag(null, TAG_ROOT);
-
- ShortcutService.writeTagValue(out, TAG_LAUNCHER,
- mLauncherComponent);
-
- final int lsize = mLaunchers.size();
- for (int i = 0; i < lsize; i++) {
- mLaunchers.valueAt(i).saveToXml(out);
- }
-
- final int psize = mPackages.size();
- for (int i = 0; i < psize; i++) {
- mPackages.valueAt(i).saveToXml(out);
- }
-
- out.endTag(null, TAG_ROOT);
- }
-
- public static UserShortcuts loadFromXml(XmlPullParser parser, int userId)
- throws IOException, XmlPullParserException {
- final UserShortcuts ret = new UserShortcuts(userId);
-
- final int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- final int depth = parser.getDepth();
- final String tag = parser.getName();
- switch (tag) {
- case TAG_LAUNCHER: {
- ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
- parser, ATTR_VALUE);
- continue;
- }
- case PackageShortcuts.TAG_ROOT: {
- final PackageShortcuts shortcuts = PackageShortcuts.loadFromXml(parser, userId);
-
- // Don't use addShortcut(), we don't need to save the icon.
- ret.getPackages().put(shortcuts.mPackageName, shortcuts);
- continue;
- }
-
- case LauncherShortcuts.TAG_ROOT: {
- final LauncherShortcuts shortcuts =
- LauncherShortcuts.loadFromXml(parser, userId);
-
- ret.getLaunchers().put(shortcuts.mPackageName, shortcuts);
- continue;
- }
- }
- throw ShortcutService.throwForInvalidTag(depth, tag);
- }
- return ret;
- }
-
- public ComponentName getLauncherComponent() {
- return mLauncherComponent;
- }
-
- public void setLauncherComponent(ShortcutService s, ComponentName launcherComponent) {
- if (Objects.equal(mLauncherComponent, launcherComponent)) {
- return;
- }
- mLauncherComponent = launcherComponent;
- s.scheduleSaveUser(mUserId);
- }
-
- public void resetThrottling() {
- for (int i = mPackages.size() - 1; i >= 0; i--) {
- mPackages.valueAt(i).resetThrottling();
- }
- }
-
- public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
- pw.print(prefix);
- pw.print("User: ");
- pw.print(mUserId);
- pw.println();
-
- pw.print(prefix);
- pw.print(" ");
- pw.print("Default launcher: ");
- pw.print(mLauncherComponent);
- pw.println();
-
- for (int i = 0; i < mLaunchers.size(); i++) {
- mLaunchers.valueAt(i).dump(s, pw, prefix + " ");
- }
-
- for (int i = 0; i < mPackages.size(); i++) {
- mPackages.valueAt(i).dump(s, pw, prefix + " ");
- }
- }
-}
-
-class LauncherShortcuts {
- private static final String TAG = ShortcutService.TAG;
-
- static final String TAG_ROOT = "launcher-pins";
-
- private static final String TAG_PACKAGE = "package";
- private static final String TAG_PIN = "pin";
-
- private static final String ATTR_VALUE = "value";
- private static final String ATTR_PACKAGE_NAME = "package-name";
-
- @UserIdInt
- final int mUserId;
-
- @NonNull
- final String mPackageName;
-
- /**
- * Package name -> IDs.
- */
- final private ArrayMap<String, ArraySet<String>> mPinnedShortcuts = new ArrayMap<>();
-
- LauncherShortcuts(@UserIdInt int userId, @NonNull String packageName) {
- mUserId = userId;
- mPackageName = packageName;
- }
-
- public void pinShortcuts(@NonNull ShortcutService s, @NonNull String packageName,
- @NonNull List<String> ids) {
- final int idSize = ids.size();
- if (idSize == 0) {
- mPinnedShortcuts.remove(packageName);
- } else {
- final ArraySet<String> prevSet = mPinnedShortcuts.get(packageName);
-
- // Pin shortcuts. Make sure only pin the ones that were visible to the caller.
- // i.e. a non-dynamic, pinned shortcut by *other launchers* shouldn't be pinned here.
-
- final PackageShortcuts packageShortcuts =
- s.getPackageShortcutsLocked(packageName, mUserId);
- final ArraySet<String> newSet = new ArraySet<>();
-
- for (int i = 0; i < idSize; i++) {
- final String id = ids.get(i);
- final ShortcutInfo si = packageShortcuts.findShortcutById(id);
- if (si == null) {
- continue;
- }
- if (si.isDynamic() || (prevSet != null && prevSet.contains(id))) {
- newSet.add(id);
- }
- }
- mPinnedShortcuts.put(packageName, newSet);
- }
- s.getPackageShortcutsLocked(packageName, mUserId).refreshPinnedFlags(s);
- }
-
- /**
- * Return the pinned shortcut IDs for the publisher package.
- */
- public ArraySet<String> getPinnedShortcutIds(@NonNull String packageName) {
- return mPinnedShortcuts.get(packageName);
- }
-
- /**
- * Persist.
- */
- public void saveToXml(XmlSerializer out) throws IOException {
- out.startTag(null, TAG_ROOT);
- ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
- mPackageName);
-
- final int size = mPinnedShortcuts.size();
- for (int i = 0; i < size; i++) {
- out.startTag(null, TAG_PACKAGE);
- ShortcutService.writeAttr(out, ATTR_PACKAGE_NAME,
- mPinnedShortcuts.keyAt(i));
-
- final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
- final int idSize = ids.size();
- for (int j = 0; j < idSize; j++) {
- ShortcutService.writeTagValue(out, TAG_PIN, ids.valueAt(j));
- }
- out.endTag(null, TAG_PACKAGE);
- }
-
- out.endTag(null, TAG_ROOT);
- }
+ final ShortcutUser user = mUsers.get(userId);
+ if (user == null) return null;
- /**
- * Load.
- */
- public static LauncherShortcuts loadFromXml(XmlPullParser parser, int userId)
- throws IOException, XmlPullParserException {
- final String launcherPackageName = ShortcutService.parseStringAttribute(parser,
- ATTR_PACKAGE_NAME);
-
- final LauncherShortcuts ret = new LauncherShortcuts(userId, launcherPackageName);
-
- ArraySet<String> ids = null;
- final int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- final int depth = parser.getDepth();
- final String tag = parser.getName();
- switch (tag) {
- case TAG_PACKAGE: {
- final String packageName = ShortcutService.parseStringAttribute(parser,
- ATTR_PACKAGE_NAME);
- ids = new ArraySet<>();
- ret.mPinnedShortcuts.put(packageName, ids);
- continue;
- }
- case TAG_PIN: {
- ids.add(ShortcutService.parseStringAttribute(parser,
- ATTR_VALUE));
- continue;
- }
- }
- throw ShortcutService.throwForInvalidTag(depth, tag);
- }
- return ret;
- }
-
- public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
- pw.println();
-
- pw.print(prefix);
- pw.print("Launcher: ");
- pw.print(mPackageName);
- pw.println();
-
- final int size = mPinnedShortcuts.size();
- for (int i = 0; i < size; i++) {
- pw.println();
-
- pw.print(prefix);
- pw.print(" ");
- pw.print("Package: ");
- pw.println(mPinnedShortcuts.keyAt(i));
-
- final ArraySet<String> ids = mPinnedShortcuts.valueAt(i);
- final int idSize = ids.size();
-
- for (int j = 0; j < idSize; j++) {
- pw.print(prefix);
- pw.print(" ");
- pw.print(ids.valueAt(j));
- pw.println();
- }
- }
- }
-}
-
-/**
- * All the information relevant to shortcuts from a single package (per-user).
- */
-class PackageShortcuts {
- private static final String TAG = ShortcutService.TAG;
-
- static final String TAG_ROOT = "package";
- private static final String TAG_INTENT_EXTRAS = "intent-extras";
- private static final String TAG_EXTRAS = "extras";
- private static final String TAG_SHORTCUT = "shortcut";
-
- private static final String ATTR_NAME = "name";
- private static final String ATTR_DYNAMIC_COUNT = "dynamic-count";
- private static final String ATTR_CALL_COUNT = "call-count";
- private static final String ATTR_LAST_RESET = "last-reset";
- private static final String ATTR_ID = "id";
- private static final String ATTR_ACTIVITY = "activity";
- private static final String ATTR_TITLE = "title";
- private static final String ATTR_INTENT = "intent";
- private static final String ATTR_WEIGHT = "weight";
- private static final String ATTR_TIMESTAMP = "timestamp";
- private static final String ATTR_FLAGS = "flags";
- private static final String ATTR_ICON_RES = "icon-res";
- private static final String ATTR_BITMAP_PATH = "bitmap-path";
-
- @UserIdInt
- final int mUserId;
-
- @NonNull
- final String mPackageName;
-
- /**
- * All the shortcuts from the package, keyed on IDs.
- */
- final private ArrayMap<String, ShortcutInfo> mShortcuts = new ArrayMap<>();
-
- /**
- * # of dynamic shortcuts.
- */
- private int mDynamicShortcutCount = 0;
-
- /**
- * # of times the package has called rate-limited APIs.
- */
- private int mApiCallCount;
-
- /**
- * When {@link #mApiCallCount} was reset last time.
- */
- private long mLastResetTime;
-
- PackageShortcuts(int userId, String packageName) {
- mUserId = userId;
- mPackageName = packageName;
- }
-
- @Nullable
- public ShortcutInfo findShortcutById(String id) {
- return mShortcuts.get(id);
- }
-
- private ShortcutInfo deleteShortcut(@NonNull ShortcutService s,
- @NonNull String id) {
- final ShortcutInfo shortcut = mShortcuts.remove(id);
- if (shortcut != null) {
- s.removeIcon(mUserId, shortcut);
- shortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC | ShortcutInfo.FLAG_PINNED);
- }
- return shortcut;
- }
-
- void addShortcut(@NonNull ShortcutService s, @NonNull ShortcutInfo newShortcut) {
- deleteShortcut(s, newShortcut.getId());
- s.saveIconAndFixUpShortcut(mUserId, newShortcut);
- mShortcuts.put(newShortcut.getId(), newShortcut);
- }
-
- /**
- * Add a shortcut, or update one with the same ID, with taking over existing flags.
- *
- * It checks the max number of dynamic shortcuts.
- */
- public void addDynamicShortcut(@NonNull ShortcutService s,
- @NonNull ShortcutInfo newShortcut) {
- newShortcut.addFlags(ShortcutInfo.FLAG_DYNAMIC);
-
- final ShortcutInfo oldShortcut = mShortcuts.get(newShortcut.getId());
-
- final boolean wasPinned;
- final int newDynamicCount;
-
- if (oldShortcut == null) {
- wasPinned = false;
- newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
- } else {
- wasPinned = oldShortcut.isPinned();
- if (oldShortcut.isDynamic()) {
- newDynamicCount = mDynamicShortcutCount; // not adding a dynamic shortcut.
- } else {
- newDynamicCount = mDynamicShortcutCount + 1; // adding a dynamic shortcut.
- }
- }
-
- // Make sure there's still room.
- s.enforceMaxDynamicShortcuts(newDynamicCount);
-
- // Okay, make it dynamic and add.
- if (wasPinned) {
- newShortcut.addFlags(ShortcutInfo.FLAG_PINNED);
- }
-
- addShortcut(s, newShortcut);
- mDynamicShortcutCount = newDynamicCount;
- }
-
- /**
- * Remove all shortcuts that aren't pinned nor dynamic.
- */
- private void removeOrphans(@NonNull ShortcutService s) {
- ArrayList<String> removeList = null; // Lazily initialize.
-
- for (int i = mShortcuts.size() - 1; i >= 0; i--) {
- final ShortcutInfo si = mShortcuts.valueAt(i);
-
- if (si.isPinned() || si.isDynamic()) continue;
-
- if (removeList == null) {
- removeList = new ArrayList<>();
- }
- removeList.add(si.getId());
- }
- if (removeList != null) {
- for (int i = removeList.size() - 1 ; i >= 0; i--) {
- deleteShortcut(s, removeList.get(i));
- }
- }
- }
-
- /**
- * Remove all dynamic shortcuts.
- */
- public void deleteAllDynamicShortcuts(@NonNull ShortcutService s) {
- for (int i = mShortcuts.size() - 1; i >= 0; i--) {
- mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_DYNAMIC);
- }
- removeOrphans(s);
- mDynamicShortcutCount = 0;
- }
-
- /**
- * Remove a dynamic shortcut by ID.
- */
- public void deleteDynamicWithId(@NonNull ShortcutService s, @NonNull String shortcutId) {
- final ShortcutInfo oldShortcut = mShortcuts.get(shortcutId);
-
- if (oldShortcut == null) {
- return;
- }
- if (oldShortcut.isDynamic()) {
- mDynamicShortcutCount--;
- }
- if (oldShortcut.isPinned()) {
- oldShortcut.clearFlags(ShortcutInfo.FLAG_DYNAMIC);
- } else {
- deleteShortcut(s, shortcutId);
- }
- }
-
- /**
- * Called after a launcher updates the pinned set. For each shortcut in this package,
- * set FLAG_PINNED if any launcher has pinned it. Otherwise, clear it.
- *
- * <p>Then remove all shortcuts that are not dynamic and no longer pinned either.
- */
- public void refreshPinnedFlags(@NonNull ShortcutService s) {
- // First, un-pin all shortcuts
- for (int i = mShortcuts.size() - 1; i >= 0; i--) {
- mShortcuts.valueAt(i).clearFlags(ShortcutInfo.FLAG_PINNED);
- }
-
- // Then, for the pinned set for each launcher, set the pin flag one by one.
- final ArrayMap<String, LauncherShortcuts> launchers =
- s.getUserShortcutsLocked(mUserId).getLaunchers();
-
- for (int l = launchers.size() - 1; l >= 0; l--) {
- final LauncherShortcuts launcherShortcuts = launchers.valueAt(l);
- final ArraySet<String> pinned = launcherShortcuts.getPinnedShortcutIds(mPackageName);
-
- if (pinned == null || pinned.size() == 0) {
- continue;
- }
- for (int i = pinned.size() - 1; i >= 0; i--) {
- final ShortcutInfo si = mShortcuts.get(pinned.valueAt(i));
- if (si == null) {
- s.wtf("Shortcut not found");
- } else {
- si.addFlags(ShortcutInfo.FLAG_PINNED);
- }
- }
- }
-
- // Lastly, remove the ones that are no longer pinned nor dynamic.
- removeOrphans(s);
- }
-
- /**
- * Number of calls that the caller has made, since the last reset.
- */
- public int getApiCallCount(@NonNull ShortcutService s) {
- final long last = s.getLastResetTimeLocked();
-
- final long now = s.injectCurrentTimeMillis();
- if (ShortcutService.isClockValid(now) && mLastResetTime > now) {
- Slog.w(TAG, "Clock rewound");
- // Clock rewound.
- mLastResetTime = now;
- mApiCallCount = 0;
- return mApiCallCount;
- }
-
- // If not reset yet, then reset.
- if (mLastResetTime < last) {
- if (ShortcutService.DEBUG) {
- Slog.d(TAG, String.format("My last reset=%d, now=%d, last=%d: resetting",
- mLastResetTime, now, last));
- }
- mApiCallCount = 0;
- mLastResetTime = last;
- }
- return mApiCallCount;
- }
-
- /**
- * If the caller app hasn't been throttled yet, increment {@link #mApiCallCount}
- * and return true. Otherwise just return false.
- */
- public boolean tryApiCall(@NonNull ShortcutService s) {
- if (getApiCallCount(s) >= s.mMaxDailyUpdates) {
- return false;
- }
- mApiCallCount++;
- return true;
- }
-
- public void resetRateLimitingForCommandLine() {
- mApiCallCount = 0;
- mLastResetTime = 0;
- }
+ final ShortcutPackage pkg = user.getPackages().get(packageName);
+ if (pkg == null) return null;
- /**
- * Find all shortcuts that match {@code query}.
- */
- public void findAll(@NonNull ShortcutService s, @NonNull List<ShortcutInfo> result,
- @Nullable Predicate<ShortcutInfo> query, int cloneFlag,
- @Nullable String callingLauncher) {
-
- // Set of pinned shortcuts by the calling launcher.
- final ArraySet<String> pinnedByCallerSet = (callingLauncher == null) ? null
- : s.getLauncherShortcuts(callingLauncher, mUserId)
- .getPinnedShortcutIds(mPackageName);
-
- for (int i = 0; i < mShortcuts.size(); i++) {
- final ShortcutInfo si = mShortcuts.valueAt(i);
-
- // If it's called by non-launcher (i.e. publisher, always include -> true.
- // Otherwise, only include non-dynamic pinned one, if the calling launcher has pinned
- // it.
- final boolean isPinnedByCaller = (callingLauncher == null)
- || ((pinnedByCallerSet != null) && pinnedByCallerSet.contains(si.getId()));
- if (!si.isDynamic()) {
- if (!si.isPinned()) {
- s.wtf("Shortcut not pinned here");
- continue;
- }
- if (!isPinnedByCaller) {
- continue;
- }
- }
- final ShortcutInfo clone = si.clone(cloneFlag);
- // Fix up isPinned for the caller. Note we need to do it before the "test" callback,
- // since it may check isPinned.
- if (!isPinnedByCaller) {
- clone.clearFlags(ShortcutInfo.FLAG_PINNED);
- }
- if (query == null || query.test(clone)) {
- result.add(clone);
- }
- }
- }
-
- public void resetThrottling() {
- mApiCallCount = 0;
- }
-
- public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
- pw.println();
-
- pw.print(prefix);
- pw.print("Package: ");
- pw.print(mPackageName);
- pw.println();
-
- pw.print(prefix);
- pw.print(" ");
- pw.print("Calls: ");
- pw.print(getApiCallCount(s));
- pw.println();
-
- // This should be after getApiCallCount(), which may update it.
- pw.print(prefix);
- pw.print(" ");
- pw.print("Last reset: [");
- pw.print(mLastResetTime);
- pw.print("] ");
- pw.print(s.formatTime(mLastResetTime));
- pw.println();
-
- pw.println(" Shortcuts:");
- long totalBitmapSize = 0;
- final ArrayMap<String, ShortcutInfo> shortcuts = mShortcuts;
- final int size = shortcuts.size();
- for (int i = 0; i < size; i++) {
- final ShortcutInfo si = shortcuts.valueAt(i);
- pw.print(" ");
- pw.println(si.toInsecureString());
- if (si.getBitmapPath() != null) {
- final long len = new File(si.getBitmapPath()).length();
- pw.print(" ");
- pw.print("bitmap size=");
- pw.println(len);
-
- totalBitmapSize += len;
- }
- }
- pw.print(prefix);
- pw.print(" ");
- pw.print("Total bitmap size: ");
- pw.print(totalBitmapSize);
- pw.print(" (");
- pw.print(Formatter.formatFileSize(s.mContext, totalBitmapSize));
- pw.println(")");
- }
-
- public void saveToXml(@NonNull XmlSerializer out) throws IOException, XmlPullParserException {
- out.startTag(null, TAG_ROOT);
-
- ShortcutService.writeAttr(out, ATTR_NAME, mPackageName);
- ShortcutService.writeAttr(out, ATTR_DYNAMIC_COUNT, mDynamicShortcutCount);
- ShortcutService.writeAttr(out, ATTR_CALL_COUNT, mApiCallCount);
- ShortcutService.writeAttr(out, ATTR_LAST_RESET, mLastResetTime);
-
- final int size = mShortcuts.size();
- for (int j = 0; j < size; j++) {
- saveShortcut(out, mShortcuts.valueAt(j));
- }
-
- out.endTag(null, TAG_ROOT);
- }
-
- private static void saveShortcut(XmlSerializer out, ShortcutInfo si)
- throws IOException, XmlPullParserException {
- out.startTag(null, TAG_SHORTCUT);
- ShortcutService.writeAttr(out, ATTR_ID, si.getId());
- // writeAttr(out, "package", si.getPackageName()); // not needed
- ShortcutService.writeAttr(out, ATTR_ACTIVITY, si.getActivityComponent());
- // writeAttr(out, "icon", si.getIcon()); // We don't save it.
- ShortcutService.writeAttr(out, ATTR_TITLE, si.getTitle());
- ShortcutService.writeAttr(out, ATTR_INTENT, si.getIntentNoExtras());
- ShortcutService.writeAttr(out, ATTR_WEIGHT, si.getWeight());
- ShortcutService.writeAttr(out, ATTR_TIMESTAMP,
- si.getLastChangedTimestamp());
- ShortcutService.writeAttr(out, ATTR_FLAGS, si.getFlags());
- ShortcutService.writeAttr(out, ATTR_ICON_RES, si.getIconResourceId());
- ShortcutService.writeAttr(out, ATTR_BITMAP_PATH, si.getBitmapPath());
-
- ShortcutService.writeTagExtra(out, TAG_INTENT_EXTRAS,
- si.getIntentPersistableExtras());
- ShortcutService.writeTagExtra(out, TAG_EXTRAS, si.getExtras());
-
- out.endTag(null, TAG_SHORTCUT);
- }
-
- public static PackageShortcuts loadFromXml(XmlPullParser parser, int userId)
- throws IOException, XmlPullParserException {
-
- final String packageName = ShortcutService.parseStringAttribute(parser,
- ATTR_NAME);
-
- final PackageShortcuts ret = new PackageShortcuts(userId, packageName);
-
- ret.mDynamicShortcutCount =
- ShortcutService.parseIntAttribute(parser, ATTR_DYNAMIC_COUNT);
- ret.mApiCallCount =
- ShortcutService.parseIntAttribute(parser, ATTR_CALL_COUNT);
- ret.mLastResetTime =
- ShortcutService.parseLongAttribute(parser, ATTR_LAST_RESET);
-
- final int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- final int depth = parser.getDepth();
- final String tag = parser.getName();
- switch (tag) {
- case TAG_SHORTCUT:
- final ShortcutInfo si = parseShortcut(parser, packageName);
-
- // Don't use addShortcut(), we don't need to save the icon.
- ret.mShortcuts.put(si.getId(), si);
- continue;
- }
- throw ShortcutService.throwForInvalidTag(depth, tag);
- }
- return ret;
- }
-
- private static ShortcutInfo parseShortcut(XmlPullParser parser, String packageName)
- throws IOException, XmlPullParserException {
- String id;
- ComponentName activityComponent;
- // Icon icon;
- String title;
- Intent intent;
- PersistableBundle intentPersistableExtras = null;
- int weight;
- PersistableBundle extras = null;
- long lastChangedTimestamp;
- int flags;
- int iconRes;
- String bitmapPath;
-
- id = ShortcutService.parseStringAttribute(parser, ATTR_ID);
- activityComponent = ShortcutService.parseComponentNameAttribute(parser,
- ATTR_ACTIVITY);
- title = ShortcutService.parseStringAttribute(parser, ATTR_TITLE);
- intent = ShortcutService.parseIntentAttribute(parser, ATTR_INTENT);
- weight = (int) ShortcutService.parseLongAttribute(parser, ATTR_WEIGHT);
- lastChangedTimestamp = (int) ShortcutService.parseLongAttribute(parser,
- ATTR_TIMESTAMP);
- flags = (int) ShortcutService.parseLongAttribute(parser, ATTR_FLAGS);
- iconRes = (int) ShortcutService.parseLongAttribute(parser, ATTR_ICON_RES);
- bitmapPath = ShortcutService.parseStringAttribute(parser, ATTR_BITMAP_PATH);
-
- final int outerDepth = parser.getDepth();
- int type;
- while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
- && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
- if (type != XmlPullParser.START_TAG) {
- continue;
- }
- final int depth = parser.getDepth();
- final String tag = parser.getName();
- if (ShortcutService.DEBUG_LOAD) {
- Slog.d(TAG, String.format(" depth=%d type=%d name=%s",
- depth, type, tag));
- }
- switch (tag) {
- case TAG_INTENT_EXTRAS:
- intentPersistableExtras = PersistableBundle.restoreFromXml(parser);
- continue;
- case TAG_EXTRAS:
- extras = PersistableBundle.restoreFromXml(parser);
- continue;
- }
- throw ShortcutService.throwForInvalidTag(depth, tag);
+ return pkg.findShortcutById(shortcutId);
}
- return new ShortcutInfo(
- id, packageName, activityComponent, /* icon =*/ null, title, intent,
- intentPersistableExtras, weight, extras, lastChangedTimestamp, flags,
- iconRes, bitmapPath);
}
}
diff --git a/services/core/java/com/android/server/pm/ShortcutUser.java b/services/core/java/com/android/server/pm/ShortcutUser.java
new file mode 100644
index 000000000000..4a6b1e4d6bfc
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ShortcutUser.java
@@ -0,0 +1,179 @@
+/*
+ * 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.
+ */
+package com.android.server.pm;
+
+import android.annotation.NonNull;
+import android.annotation.UserIdInt;
+import android.content.ComponentName;
+import android.util.ArrayMap;
+
+import libcore.util.Objects;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+ * User information used by {@link ShortcutService}.
+ */
+class ShortcutUser {
+ private static final String TAG = ShortcutService.TAG;
+
+ static final String TAG_ROOT = "user";
+ private static final String TAG_LAUNCHER = "launcher";
+
+ private static final String ATTR_VALUE = "value";
+
+ @UserIdInt
+ final int mUserId;
+
+ private final ArrayMap<String, ShortcutPackage> mPackages = new ArrayMap<>();
+
+ private final ArrayMap<String, ShortcutLauncher> mLaunchers = new ArrayMap<>();
+
+ private ComponentName mLauncherComponent;
+
+ public ShortcutUser(int userId) {
+ mUserId = userId;
+ }
+
+ public ArrayMap<String, ShortcutPackage> getPackages() {
+ return mPackages;
+ }
+
+ public ArrayMap<String, ShortcutLauncher> getLaunchers() {
+ return mLaunchers;
+ }
+
+ public ShortcutPackage getPackageShortcuts(@NonNull String packageName) {
+ ShortcutPackage ret = mPackages.get(packageName);
+ if (ret == null) {
+ ret = new ShortcutPackage(mUserId, packageName);
+ mPackages.put(packageName, ret);
+ }
+ return ret;
+ }
+
+ public ShortcutLauncher getLauncherShortcuts(@NonNull String packageName) {
+ ShortcutLauncher ret = mLaunchers.get(packageName);
+ if (ret == null) {
+ ret = new ShortcutLauncher(mUserId, packageName);
+ mLaunchers.put(packageName, ret);
+ }
+ return ret;
+ }
+
+ public void saveToXml(XmlSerializer out) throws IOException, XmlPullParserException {
+ out.startTag(null, TAG_ROOT);
+
+ ShortcutService.writeTagValue(out, TAG_LAUNCHER,
+ mLauncherComponent);
+
+ final int lsize = mLaunchers.size();
+ for (int i = 0; i < lsize; i++) {
+ mLaunchers.valueAt(i).saveToXml(out);
+ }
+
+ final int psize = mPackages.size();
+ for (int i = 0; i < psize; i++) {
+ mPackages.valueAt(i).saveToXml(out);
+ }
+
+ out.endTag(null, TAG_ROOT);
+ }
+
+ public static ShortcutUser loadFromXml(XmlPullParser parser, int userId)
+ throws IOException, XmlPullParserException {
+ final ShortcutUser ret = new ShortcutUser(userId);
+
+ final int outerDepth = parser.getDepth();
+ int type;
+ while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+ && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+ if (type != XmlPullParser.START_TAG) {
+ continue;
+ }
+ final int depth = parser.getDepth();
+ final String tag = parser.getName();
+ switch (tag) {
+ case TAG_LAUNCHER: {
+ ret.mLauncherComponent = ShortcutService.parseComponentNameAttribute(
+ parser, ATTR_VALUE);
+ continue;
+ }
+ case ShortcutPackage.TAG_ROOT: {
+ final ShortcutPackage shortcuts = ShortcutPackage.loadFromXml(parser, userId);
+
+ // Don't use addShortcut(), we don't need to save the icon.
+ ret.getPackages().put(shortcuts.mPackageName, shortcuts);
+ continue;
+ }
+
+ case ShortcutLauncher.TAG_ROOT: {
+ final ShortcutLauncher shortcuts =
+ ShortcutLauncher.loadFromXml(parser, userId);
+
+ ret.getLaunchers().put(shortcuts.mPackageName, shortcuts);
+ continue;
+ }
+ }
+ throw ShortcutService.throwForInvalidTag(depth, tag);
+ }
+ return ret;
+ }
+
+ public ComponentName getLauncherComponent() {
+ return mLauncherComponent;
+ }
+
+ public void setLauncherComponent(ShortcutService s, ComponentName launcherComponent) {
+ if (Objects.equal(mLauncherComponent, launcherComponent)) {
+ return;
+ }
+ mLauncherComponent = launcherComponent;
+ s.scheduleSaveUser(mUserId);
+ }
+
+ public void resetThrottling() {
+ for (int i = mPackages.size() - 1; i >= 0; i--) {
+ mPackages.valueAt(i).resetThrottling();
+ }
+ }
+
+ public void dump(@NonNull ShortcutService s, @NonNull PrintWriter pw, @NonNull String prefix) {
+ pw.print(prefix);
+ pw.print("User: ");
+ pw.print(mUserId);
+ pw.println();
+
+ pw.print(prefix);
+ pw.print(" ");
+ pw.print("Default launcher: ");
+ pw.print(mLauncherComponent);
+ pw.println();
+
+ for (int i = 0; i < mLaunchers.size(); i++) {
+ mLaunchers.valueAt(i).dump(s, pw, prefix + " ");
+ }
+
+ for (int i = 0; i < mPackages.size(); i++) {
+ mPackages.valueAt(i).dump(s, pw, prefix + " ");
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index a3622b58cb4d..ac19e24ba010 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2011 The Android Open Source Project
*
@@ -457,7 +458,7 @@ public class UserManagerService extends IUserManager.Stub {
continue;
}
if (!excludeDying || !mRemovingUserIds.get(ui.id)) {
- users.add(ui);
+ users.add(userWithName(ui));
}
}
return users;
@@ -499,7 +500,7 @@ public class UserManagerService extends IUserManager.Stub {
if (mRemovingUserIds.get(profile.id)) {
continue;
}
- users.add(profile);
+ users.add(userWithName(profile));
}
return users;
}
@@ -650,18 +651,41 @@ public class UserManagerService extends IUserManager.Stub {
@Override
public UserInfo getUserInfo(int userId) {
+ checkManageUsersPermission("query user");
+ synchronized (mUsersLock) {
+ return userWithName(getUserInfoLU(userId));
+ }
+ }
+
+ /**
+ * Returns a UserInfo object with the name filled in, for Owner, or the original
+ * if the name is already set.
+ */
+ private UserInfo userWithName(UserInfo orig) {
+ if (orig != null && orig.name == null && orig.id == UserHandle.USER_SYSTEM) {
+ UserInfo withName = new UserInfo(orig);
+ withName.name = getOwnerName();
+ return withName;
+ } else {
+ return orig;
+ }
+ }
+
+ @Override
+ public boolean isManagedProfile(int userId) {
int callingUserId = UserHandle.getCallingUserId();
if (callingUserId != userId && !hasManageUsersPermission()) {
synchronized (mPackagesLock) {
if (!isSameProfileGroupLP(callingUserId, userId)) {
throw new SecurityException(
- "You need MANAGE_USERS permission to: query users outside profile" +
- " group");
+ "You need MANAGE_USERS permission to: check if specified user a " +
+ "managed profile outside your profile group");
}
}
}
synchronized (mUsersLock) {
- return getUserInfoLU(userId);
+ UserInfo userInfo = getUserInfoLU(userId);
+ return userInfo != null && userInfo.isManagedProfile();
}
}
@@ -1449,9 +1473,7 @@ public class UserManagerService extends IUserManager.Stub {
flags |= UserInfo.FLAG_ADMIN | UserInfo.FLAG_PRIMARY;
}
// Create the system user
- UserInfo system = new UserInfo(UserHandle.USER_SYSTEM,
- mContext.getResources().getString(com.android.internal.R.string.owner_name), null,
- flags);
+ UserInfo system = new UserInfo(UserHandle.USER_SYSTEM, null, null, flags);
UserData userData = new UserData();
userData.info = system;
synchronized (mUsersLock) {
@@ -1472,6 +1494,10 @@ public class UserManagerService extends IUserManager.Stub {
writeUserLP(userData);
}
+ private String getOwnerName() {
+ return mContext.getResources().getString(com.android.internal.R.string.owner_name);
+ }
+
private void scheduleWriteUser(UserData UserData) {
if (DBG) {
debug("scheduleWriteUser");
@@ -1541,9 +1567,11 @@ public class UserManagerService extends IUserManager.Stub {
serializer.attribute(null, ATTR_SEED_ACCOUNT_TYPE, userData.seedAccountType);
}
}
- serializer.startTag(null, TAG_NAME);
- serializer.text(userInfo.name);
- serializer.endTag(null, TAG_NAME);
+ if (userInfo.name != null) {
+ serializer.startTag(null, TAG_NAME);
+ serializer.text(userInfo.name);
+ serializer.endTag(null, TAG_NAME);
+ }
synchronized (mRestrictionsLock) {
UserRestrictionsUtils.writeRestrictions(serializer,
mBaseUserRestrictions.get(userInfo.id), TAG_RESTRICTIONS);
diff --git a/services/core/java/com/android/server/policy/ShortcutManager.java b/services/core/java/com/android/server/policy/ShortcutManager.java
index a47f250feea8..a14c6145c548 100644
--- a/services/core/java/com/android/server/policy/ShortcutManager.java
+++ b/services/core/java/com/android/server/policy/ShortcutManager.java
@@ -78,7 +78,7 @@ class ShortcutManager {
public Intent getIntent(KeyCharacterMap kcm, int keyCode, int metaState) {
ShortcutInfo shortcut = null;
- // If the Shift key is preesed, then search for the shift shortcuts.
+ // If the Shift key is pressed, then search for the shift shortcuts.
boolean isShiftOn = (metaState & KeyEvent.META_SHIFT_ON) == KeyEvent.META_SHIFT_ON;
SparseArray<ShortcutInfo> shortcutMap = isShiftOn ? mShiftShortcuts : mShortcuts;
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 3cf95900edde..fb9b1cec862a 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -20,6 +20,7 @@ import static android.app.WallpaperManager.FLAG_SET_SYSTEM;
import static android.app.WallpaperManager.FLAG_SET_LOCK;
import static android.os.ParcelFileDescriptor.*;
+import android.app.ActivityManager;
import android.app.ActivityManagerNative;
import android.app.AppGlobals;
import android.app.AppOpsManager;
@@ -875,12 +876,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
if (!isWallpaperSupported(callingPackage) || !isWallpaperSettingAllowed(callingPackage)) {
return;
}
- if (userId != UserHandle.getCallingUserId()) {
- // cross-user call
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- "WallpaperManagerService");
- }
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "clearWallpaper", null);
synchronized (mLock) {
clearWallpaperLocked(false, which, userId, null);
@@ -1103,12 +1100,8 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
@Override
public ParcelFileDescriptor getWallpaper(IWallpaperManagerCallback cb, final int which,
Bundle outParams, int wallpaperUserId) {
- if (wallpaperUserId != UserHandle.getCallingUserId()) {
- // cross-user call
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS_FULL,
- "WallpaperManagerService");
- }
+ wallpaperUserId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), wallpaperUserId, false, true, "getWallpaper", null);
if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
throw new IllegalArgumentException("Must specify exactly one kind of wallpaper to read");
@@ -1147,6 +1140,7 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
}
+ @Override
public WallpaperInfo getWallpaperInfo() {
int userId = UserHandle.getCallingUserId();
synchronized (mLock) {
@@ -1159,6 +1153,26 @@ public class WallpaperManagerService extends IWallpaperManager.Stub {
}
@Override
+ public int getWallpaperIdForUser(int which, int userId) {
+ userId = ActivityManager.handleIncomingUser(Binder.getCallingPid(),
+ Binder.getCallingUid(), userId, false, true, "getWallpaperIdForUser", null);
+
+ if (which != FLAG_SET_SYSTEM && which != FLAG_SET_LOCK) {
+ throw new IllegalArgumentException("Must specify exactly one kind of wallpaper");
+ }
+
+ final SparseArray<WallpaperData> map =
+ (which == FLAG_SET_LOCK) ? mLockWallpaperMap : mWallpaperMap;
+ synchronized (mLock) {
+ WallpaperData wallpaper = map.get(userId);
+ if (wallpaper != null) {
+ return wallpaper.wallpaperId;
+ }
+ }
+ return -1;
+ }
+
+ @Override
public boolean setLockWallpaperCallback(IWallpaperManagerCallback cb) {
checkPermission(android.Manifest.permission.INTERNAL_SYSTEM_WINDOW);
synchronized (mLock) {
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index a589f894e3bc..c0c1ed8e2d0c 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -195,8 +195,10 @@ final class Session extends IWindowSession.Stub
@Override
public void repositionChild(IWindow window, int left, int top, int right, int bottom,
- long deferTransactionUntilFrame, Rect outFrame) {
+ int requestedWidth, int requestedHeight,
+ long deferTransactionUntilFrame, Rect outFrame) {
mService.repositionChild(this, window, left, top, right, bottom,
+ requestedWidth, requestedHeight,
deferTransactionUntilFrame, outFrame);
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b84ed7be9ad4..14291caa4072 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2522,6 +2522,7 @@ public class WindowManagerService extends IWindowManager.Stub
void repositionChild(Session session, IWindow client,
int left, int top, int right, int bottom,
+ int requestedWidth, int requestedHeight,
long deferTransactionUntilFrame, Rect outFrame) {
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "repositionChild");
long origId = Binder.clearCallingIdentity();
@@ -2537,6 +2538,7 @@ public class WindowManagerService extends IWindowManager.Stub
"repositionChild called but window is not"
+ "attached to a parent win=" + win);
}
+ win.setRequestedSize(requestedWidth, requestedHeight);
win.mAttrs.x = left;
win.mAttrs.y = top;
@@ -2593,7 +2595,8 @@ public class WindowManagerService extends IWindowManager.Stub
== PackageManager.PERMISSION_GRANTED;
long origId = Binder.clearCallingIdentity();
-
+ final boolean preserveGeometry = (attrs != null) && (attrs.privateFlags &
+ WindowManager.LayoutParams.PRIVATE_FLAG_PRESERVE_GEOMETRY) != 0;
synchronized(mWindowMap) {
WindowState win = windowForClientLocked(session, client, false);
if (win == null) {
@@ -2601,7 +2604,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
WindowStateAnimator winAnimator = win.mWinAnimator;
- if (viewVisibility != View.GONE) {
+ if (!preserveGeometry && viewVisibility != View.GONE) {
win.setRequestedSize(requestedWidth, requestedHeight);
}
@@ -2650,7 +2653,9 @@ public class WindowManagerService extends IWindowManager.Stub
if ((attrChanges & WindowManager.LayoutParams.ALPHA_CHANGED) != 0) {
winAnimator.mAlpha = attrs.alpha;
}
- win.setWindowScale(requestedWidth, requestedHeight);
+ if (!preserveGeometry) {
+ win.setWindowScale(win.mRequestedWidth, win.mRequestedHeight);
+ }
boolean imMayMove = (flagChanges & (FLAG_ALT_FOCUSABLE_IM | FLAG_NOT_FOCUSABLE)) != 0;
final boolean isDefaultDisplay = win.isDefaultDisplay();
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 1695615fedda..9c0d737cc875 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -71,6 +71,7 @@ import static android.view.WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;
import static android.view.WindowManager.LayoutParams.FLAG_SCALED;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
import static android.view.WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
@@ -1883,6 +1884,13 @@ final class WindowState implements WindowManagerPolicy.WindowState {
}
private boolean shouldSaveSurface() {
+ if ((mAttrs.flags & FLAG_SECURE) != 0) {
+ // We don't save secure surfaces since their content shouldn't be shown while the app
+ // isn't on screen and content might leak through during the transition animation with
+ // saved surface.
+ return false;
+ }
+
if (ActivityManager.isLowRamDeviceStatic()) {
// Don't save surfaces on Svelte devices.
return false;
diff --git a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
index e2c71a1aa2f8..ae050429efed 100644
--- a/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
+++ b/services/core/jni/com_android_server_location_GnssLocationProvider.cpp
@@ -1108,7 +1108,7 @@ const char *const JavaMethodHelper<bool>::signature_ = "(Z)V";
} while (false)
static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
- static uint32_t discontinuity_count_to_handle_old_lock_type = 0;
+ static uint32_t discontinuity_count_to_handle_old_clock_type = 0;
JavaObject object(env, "android/location/GnssClock");
GpsClockFlags flags = clock->flags;
@@ -1137,7 +1137,7 @@ static jobject translate_gps_clock(JNIEnv* env, GpsClock* clock) {
clock->full_bias_ns = clock->time_ns;
clock->time_ns = 0;
SET(HardwareClockDiscontinuityCount,
- discontinuity_count_to_handle_old_lock_type++);
+ discontinuity_count_to_handle_old_clock_type++);
break;
}
@@ -1226,10 +1226,6 @@ static jobject translate_gps_measurement(JNIEnv* env,
static_cast<int32_t>(measurement->multipath_indicator));
SET_IF(GNSS_MEASUREMENT_HAS_SNR, SnrInDb, measurement->snr_db);
- SET_IF_NOT(GPS_MEASUREMENT_HAS_UNCORRECTED_PSEUDORANGE_RATE,
- PseudorangeRateCorrected,
- true);
-
return object.get();
}
diff --git a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
index 34f2e2e12594..8e11511127db 100644
--- a/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/ConnectivityServiceTest.java
@@ -1008,29 +1008,41 @@ public class ConnectivityServiceTest extends AndroidTestCase {
private class TestNetworkCallback extends NetworkCallback {
private final ConditionVariable mConditionVariable = new ConditionVariable();
private CallbackState mLastCallback = CallbackState.NONE;
+ private Network mLastNetwork;
public void onAvailable(Network network) {
assertEquals(CallbackState.NONE, mLastCallback);
mLastCallback = CallbackState.AVAILABLE;
+ mLastNetwork = network;
mConditionVariable.open();
}
public void onLosing(Network network, int maxMsToLive) {
assertEquals(CallbackState.NONE, mLastCallback);
mLastCallback = CallbackState.LOSING;
+ mLastNetwork = network;
mConditionVariable.open();
}
public void onLost(Network network) {
assertEquals(CallbackState.NONE, mLastCallback);
mLastCallback = CallbackState.LOST;
+ mLastNetwork = network;
mConditionVariable.open();
}
void expectCallback(CallbackState state) {
+ expectCallback(state, null);
+ }
+
+ void expectCallback(CallbackState state, MockNetworkAgent mockAgent) {
waitFor(mConditionVariable);
assertEquals(state, mLastCallback);
+ if (mockAgent != null) {
+ assertEquals(mockAgent.getNetwork(), mLastNetwork);
+ }
mLastCallback = CallbackState.NONE;
+ mLastNetwork = null;
mConditionVariable.close();
}
@@ -1389,6 +1401,55 @@ public class ConnectivityServiceTest extends AndroidTestCase {
execptionCalled);
}
+ @LargeTest
+ public void testRegisterDefaultNetworkCallback() throws Exception {
+ final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
+ mCm.registerDefaultNetworkCallback(defaultNetworkCallback);
+ defaultNetworkCallback.assertNoCallback();
+
+ // Create a TRANSPORT_CELLULAR request to keep the mobile interface up
+ // whenever Wi-Fi is up. Without this, the mobile network agent is
+ // reaped before any other activity can take place.
+ final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
+ final NetworkRequest cellRequest = new NetworkRequest.Builder()
+ .addTransportType(TRANSPORT_CELLULAR).build();
+ mCm.requestNetwork(cellRequest, cellNetworkCallback);
+ cellNetworkCallback.assertNoCallback();
+
+ // Bring up cell and expect CALLBACK_AVAILABLE.
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+
+ // Bring up wifi and expect CALLBACK_AVAILABLE.
+ mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+ mWiFiNetworkAgent.connect(true);
+ cellNetworkCallback.assertNoCallback();
+ defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mWiFiNetworkAgent);
+
+ // Bring down cell. Expect no default network callback, since it wasn't the default.
+ mCellNetworkAgent.disconnect();
+ cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ defaultNetworkCallback.assertNoCallback();
+
+ // Bring up cell. Expect no default network callback, since it won't be the default.
+ mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
+ mCellNetworkAgent.connect(true);
+ cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ defaultNetworkCallback.assertNoCallback();
+
+ // Bring down wifi. Expect the default network callback to notified of LOST wifi
+ // followed by AVAILABLE cell.
+ mWiFiNetworkAgent.disconnect();
+ cellNetworkCallback.assertNoCallback();
+ defaultNetworkCallback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+ defaultNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
+ mCellNetworkAgent.disconnect();
+ cellNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ defaultNetworkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
+ }
+
private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
index ad86fd08cea9..28966ca5a722 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest.java
@@ -22,6 +22,7 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
import android.annotation.NonNull;
import android.annotation.UserIdInt;
@@ -56,6 +57,7 @@ import android.os.UserManager;
import android.test.InstrumentationTestCase;
import android.test.mock.MockContext;
import android.test.suitebuilder.annotation.SmallTest;
+import android.util.ArraySet;
import android.util.Log;
import android.util.SparseArray;
@@ -124,6 +126,11 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
}
@Override
+ public String getSystemServiceName(Class<?> serviceClass) {
+ return getTestContext().getSystemServiceName(serviceClass);
+ }
+
+ @Override
public PackageManager getPackageManager() {
return mMockPackageManager;
}
@@ -231,7 +238,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
@Override
boolean injectIsLowRamDevice() {
- return mInjectdIsLowRamDevice;
+ return mInjectedIsLowRamDevice;
}
@Override
@@ -343,7 +350,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
private long mInjectedCurrentTimeLillis;
- private boolean mInjectdIsLowRamDevice;
+ private boolean mInjectedIsLowRamDevice;
private int mInjectedCallingUid;
private String mInjectedClientPackage;
@@ -657,6 +664,14 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
return new ComponentName(mClientContext, clazz);
}
+ private <T> Set<T> makeSet(T... values) {
+ final HashSet<T> ret = new HashSet<>();
+ for (T s : values) {
+ ret.add(s);
+ }
+ return ret;
+ }
+
@NonNull
private ShortcutInfo findById(List<ShortcutInfo> list, String id) {
for (ShortcutInfo s : list) {
@@ -841,6 +856,14 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
return mService.getPackageShortcutForTest(packageName, shortcutId, userId);
}
+ private void assertShortcutExists(String packageName, String shortcutId, int userId) {
+ assertTrue(getPackageShortcut(packageName, shortcutId, userId) != null);
+ }
+
+ private void assertShortcutNotExists(String packageName, String shortcutId, int userId) {
+ assertTrue(getPackageShortcut(packageName, shortcutId, userId) == null);
+ }
+
private ShortcutInfo getPackageShortcut(String packageName, String shortcutId) {
return getPackageShortcut(packageName, shortcutId, getCallingUserId());
}
@@ -849,6 +872,27 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
return getPackageShortcut(getCallingPackage(), shortcutId, getCallingUserId());
}
+ private List<ShortcutInfo> getLauncherShortcuts(String launcher, int userId, int queryFlags) {
+ final List<ShortcutInfo>[] ret = new List[1];
+ runWithCaller(launcher, userId, () -> {
+ final ShortcutQuery q = new ShortcutQuery();
+ q.setQueryFlags(queryFlags);
+ ret[0] = mLauncherApps.getShortcuts(q, UserHandle.of(userId));
+ });
+ return ret[0];
+ }
+
+ private List<ShortcutInfo> getLauncherPinnedShortcuts(String launcher, int userId) {
+ return getLauncherShortcuts(launcher, userId, ShortcutQuery.FLAG_GET_PINNED);
+ }
+
+ /**
+ * Wrap a set in an ArraySet just to get a better toString.
+ */
+ private <T> Set<T> set(Set<T> in) {
+ return new ArraySet<T>(in);
+ }
+
/**
* Test for the first launch path, no settings file available.
*/
@@ -857,7 +901,8 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
}
/**
- * Test for {@link ShortcutService#updateTimes()}
+ * Test for {@link ShortcutService#getLastResetTimeLocked()} and
+ * {@link ShortcutService#getNextResetTimeLocked()}.
*/
public void testUpdateAndGetNextResetTimeLocked() {
assertResetTimes(START_TIME, START_TIME + INTERVAL);
@@ -928,7 +973,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertEquals(CompressFormat.WEBP, mService.getIconPersistFormatForTest());
assertEquals(75, mService.getIconPersistQualityForTest());
- mInjectdIsLowRamDevice = true;
+ mInjectedIsLowRamDevice = true;
mService.updateConfigurationLocked(
ConfigConstants.KEY_MAX_ICON_DIMENSION_DP + "=100,"
+ ConfigConstants.KEY_MAX_ICON_DIMENSION_DP_LOWRAM + "=50,"
@@ -2205,6 +2250,8 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
// TODO Add "multi" version -- run the test with two launchers and make sure the callback
// argument only contains the ones that are actually visible to each launcher.
+ when(mMockUserManager.isUserRunning(eq(USER_0))).thenReturn(true);
+
LauncherApps.Callback c0 = mock(LauncherApps.Callback.class);
// Set listeners
@@ -2320,6 +2367,20 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
eq(UserHandle.of(USER_0))
);
assertEquals(0, shortcuts.getValue().size());
+
+ // Remove CALLING_PACKAGE_2
+ reset(c0);
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_0);
+
+ // Should get a callback with an empty list.
+ waitOnMainThread();
+ shortcuts = ArgumentCaptor.forClass(List.class);
+ verify(c0).onShortcutsChanged(
+ eq(CALLING_PACKAGE_2),
+ shortcuts.capture(),
+ eq(UserHandle.of(USER_0))
+ );
+ assertEquals(0, shortcuts.getValue().size());
}
// === Test for persisting ===
@@ -2436,7 +2497,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertEquals(0, mService.getShortcutsForTest().size());
// this will pre-load the per-user info.
- mService.onStartUserLocked(UserHandle.USER_SYSTEM);
+ mService.handleUnlockUser(UserHandle.USER_SYSTEM);
// Now it's loaded.
assertEquals(1, mService.getShortcutsForTest().size());
@@ -2462,7 +2523,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
.getLauncherComponent().getPackageName());
// Start another user
- mService.onStartUserLocked(USER_10);
+ mService.handleUnlockUser(USER_10);
// Now the size is 2.
assertEquals(2, mService.getShortcutsForTest().size());
@@ -2478,7 +2539,7 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
assertNull(mService.getShortcutsForTest().get(USER_10).getLauncherComponent());
// Try stopping the user
- mService.onCleanupUserLocked(USER_10);
+ mService.handleCleanupUser(USER_10);
// Now it's unloaded.
assertEquals(1, mService.getShortcutsForTest().size());
@@ -2486,6 +2547,248 @@ public class ShortcutManagerTest extends InstrumentationTestCase {
// TODO Check all other fields
}
+ public void testCleanupPackage() {
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+ makeShortcut("s0_1"))));
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+ makeShortcut("s0_2"))));
+ });
+ runWithCaller(LAUNCHER_1, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s0_1"),
+ UserHandle.of(USER_0));
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s0_2"),
+ UserHandle.of(USER_0));
+ });
+ runWithCaller(LAUNCHER_2, USER_0, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s0_1"),
+ UserHandle.of(USER_0));
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s0_2"),
+ UserHandle.of(USER_0));
+ });
+
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+ makeShortcut("s10_1"))));
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+ assertTrue(mManager.setDynamicShortcuts(Arrays.asList(
+ makeShortcut("s10_2"))));
+ });
+ runWithCaller(LAUNCHER_1, USER_10, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s10_1"),
+ UserHandle.of(USER_10));
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s10_2"),
+ UserHandle.of(USER_10));
+ });
+ runWithCaller(LAUNCHER_2, USER_10, () -> {
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_1, Arrays.asList("s10_1"),
+ UserHandle.of(USER_10));
+ mLauncherApps.pinShortcuts(CALLING_PACKAGE_2, Arrays.asList("s10_2"),
+ UserHandle.of(USER_10));
+ });
+
+ // Remove all dynamic shortcuts; now all shortcuts are just pinned.
+ runWithCaller(CALLING_PACKAGE_1, USER_0, () -> {
+ mManager.deleteAllDynamicShortcuts();
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_0, () -> {
+ mManager.deleteAllDynamicShortcuts();
+ });
+ runWithCaller(CALLING_PACKAGE_1, USER_10, () -> {
+ mManager.deleteAllDynamicShortcuts();
+ });
+ runWithCaller(CALLING_PACKAGE_2, USER_10, () -> {
+ mManager.deleteAllDynamicShortcuts();
+ });
+
+
+ final SparseArray<ShortcutUser> users = mService.getShortcutsForTest();
+ assertEquals(2, users.size());
+ assertEquals(USER_0, users.keyAt(0));
+ assertEquals(USER_10, users.keyAt(1));
+
+ final ShortcutUser user0 = users.get(USER_0);
+ final ShortcutUser user10 = users.get(USER_10);
+
+
+ // Check the registered packages.
+
+ assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ set(user0.getPackages().keySet()));
+ assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ set(user10.getPackages().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user0.getLaunchers().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user10.getLaunchers().keySet()));
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+ "s0_1", "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+ "s0_1", "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
+ "s10_1", "s10_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+ "s10_1", "s10_2");
+ assertShortcutExists(CALLING_PACKAGE_1, "s0_1", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
+ assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+
+ mService.saveDirtyInfo();
+
+ // Nonexistent package.
+ mService.cleanUpPackageLocked("abc", USER_0);
+
+ // No changes.
+ assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ set(user0.getPackages().keySet()));
+ assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ set(user10.getPackages().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user0.getLaunchers().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user10.getLaunchers().keySet()));
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+ "s0_1", "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+ "s0_1", "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
+ "s10_1", "s10_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+ "s10_1", "s10_2");
+ assertShortcutExists(CALLING_PACKAGE_1, "s0_1", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
+ assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+
+ mService.saveDirtyInfo();
+
+ // Remove a package.
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_0);
+
+ assertEquals(makeSet(CALLING_PACKAGE_2),
+ set(user0.getPackages().keySet()));
+ assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ set(user10.getPackages().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user0.getLaunchers().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user10.getLaunchers().keySet()));
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_10),
+ "s10_1", "s10_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+ "s10_1", "s10_2");
+ assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
+ assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+
+ mService.saveDirtyInfo();
+
+ // Remove a launcher.
+ mService.cleanUpPackageLocked(LAUNCHER_1, USER_10);
+
+ assertEquals(makeSet(CALLING_PACKAGE_2),
+ set(user0.getPackages().keySet()));
+ assertEquals(makeSet(CALLING_PACKAGE_1, CALLING_PACKAGE_2),
+ set(user10.getPackages().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user0.getLaunchers().keySet()));
+ assertEquals(makeSet(LAUNCHER_2),
+ set(user10.getLaunchers().keySet()));
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+ "s10_1", "s10_2");
+ assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
+ assertShortcutExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+
+ mService.saveDirtyInfo();
+
+ // Remove a package.
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_2, USER_10);
+
+ assertEquals(makeSet(CALLING_PACKAGE_2),
+ set(user0.getPackages().keySet()));
+ assertEquals(makeSet(CALLING_PACKAGE_1),
+ set(user10.getPackages().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user0.getLaunchers().keySet()));
+ assertEquals(makeSet(LAUNCHER_2),
+ set(user10.getLaunchers().keySet()));
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_10),
+ "s10_1");
+ assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_1, "s10_1", USER_10);
+ assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+
+ mService.saveDirtyInfo();
+
+ // Remove the other launcher from user 10 too.
+ mService.cleanUpPackageLocked(LAUNCHER_2, USER_10);
+
+ assertEquals(makeSet(CALLING_PACKAGE_2),
+ set(user0.getPackages().keySet()));
+ assertEquals(makeSet(CALLING_PACKAGE_1),
+ set(user10.getPackages().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user0.getLaunchers().keySet()));
+ assertEquals(makeSet(),
+ set(user10.getLaunchers().keySet()));
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+ "s0_2");
+
+ // Note the pinned shortcuts on user-10 no longer referred, so they should both be removed.
+ assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
+ assertShortcutNotExists(CALLING_PACKAGE_1, "s10_1", USER_10);
+ assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+
+ mService.saveDirtyInfo();
+
+ // More remove.
+ mService.cleanUpPackageLocked(CALLING_PACKAGE_1, USER_10);
+
+ assertEquals(makeSet(CALLING_PACKAGE_2),
+ set(user0.getPackages().keySet()));
+ assertEquals(makeSet(),
+ set(user10.getPackages().keySet()));
+ assertEquals(makeSet(LAUNCHER_1, LAUNCHER_2),
+ set(user0.getLaunchers().keySet()));
+ assertEquals(makeSet(),
+ set(user10.getLaunchers().keySet()));
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_1, USER_0),
+ "s0_2");
+ assertShortcutIds(getLauncherPinnedShortcuts(LAUNCHER_2, USER_0),
+ "s0_2");
+
+ // Note the pinned shortcuts on user-10 no longer referred, so they should both be removed.
+ assertShortcutNotExists(CALLING_PACKAGE_1, "s0_1", USER_0);
+ assertShortcutExists(CALLING_PACKAGE_2, "s0_2", USER_0);
+ assertShortcutNotExists(CALLING_PACKAGE_1, "s10_1", USER_10);
+ assertShortcutNotExists(CALLING_PACKAGE_2, "s10_2", USER_10);
+
+ mService.saveDirtyInfo();
+ }
+
// TODO Detailed test for hasShortcutPermissionInner().
// TODO Add tests for the command line functions too.
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 35a04644c836..5fe944cfa462 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -608,6 +608,7 @@ public class UsbDeviceManager {
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING
| Intent.FLAG_RECEIVER_FOREGROUND);
intent.putExtra(UsbManager.USB_CONNECTED, mConnected);
+ intent.putExtra(UsbManager.USB_HOST_CONNECTED, mHostConnected);
intent.putExtra(UsbManager.USB_CONFIGURED, mConfigured);
intent.putExtra(UsbManager.USB_DATA_UNLOCKED, isUsbTransferAllowed() && mUsbDataUnlocked);
@@ -717,6 +718,9 @@ public class UsbDeviceManager {
case MSG_UPDATE_HOST_STATE:
mHostConnected = (msg.arg1 == 1);
updateUsbNotification();
+ if (mBootCompleted) {
+ updateUsbStateBroadcastIfNeeded();
+ }
break;
case MSG_ENABLE_ADB:
setAdbEnabled(msg.arg1 == 1);
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index afb7d9394679..e26e54b058f5 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -813,6 +813,7 @@ public final class Call {
private String mRemainingPostDialSequence;
private VideoCallImpl mVideoCallImpl;
private Details mDetails;
+ private Bundle mExtras;
/**
* Obtains the post-dial sequence remaining to be emitted by this {@code Call}, if any.
@@ -988,6 +989,89 @@ public final class Call {
}
/**
+ * Adds some extras to this {@link Call}. Existing keys are replaced and new ones are
+ * added.
+ * <p>
+ * No assumptions should be made as to how an In-Call UI or service will handle these
+ * extras. Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
+ *
+ * @param extras The extras to add.
+ */
+ public final void putExtras(Bundle extras) {
+ if (extras == null) {
+ return;
+ }
+
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putAll(extras);
+ mInCallAdapter.putExtras(mTelecomCallId, extras);
+ }
+
+ /**
+ * Adds a boolean extra to this {@link Call}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, boolean value) {
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putBoolean(key, value);
+ mInCallAdapter.putExtra(mTelecomCallId, key, value);
+ }
+
+ /**
+ * Adds an integer extra to this {@code Connection}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, int value) {
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putInt(key, value);
+ mInCallAdapter.putExtra(mTelecomCallId, key, value);
+ }
+
+ /**
+ * Adds a string extra to this {@code Connection}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, String value) {
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putString(key, value);
+ mInCallAdapter.putExtra(mTelecomCallId, key, value);
+ }
+
+ /**
+ * Removes extras from this {@code Connection}.
+ *
+ * @param keys The keys of the extras to remove.
+ */
+ public final void removeExtras(List<String> keys) {
+ if (mExtras != null) {
+ for (String key : keys) {
+ mExtras.remove(key);
+ }
+ if (mExtras.size() == 0) {
+ mExtras = null;
+ }
+ }
+ mInCallAdapter.removeExtras(mTelecomCallId, keys);
+ }
+
+ /**
* Obtains the parent of this {@code Call} in a conference, if any.
*
* @return The parent {@code Call}, or {@code null} if this {@code Call} is not a
diff --git a/telecomm/java/android/telecom/Conference.java b/telecomm/java/android/telecom/Conference.java
index 1b70d651aabc..00e07afda4b1 100644
--- a/telecomm/java/android/telecom/Conference.java
+++ b/telecomm/java/android/telecom/Conference.java
@@ -16,10 +16,12 @@
package android.telecom;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.os.Bundle;
import android.telecom.Connection.VideoProvider;
+import android.util.ArraySet;
import java.util.ArrayList;
import java.util.Collections;
@@ -54,7 +56,8 @@ public abstract class Conference extends Conferenceable {
public void onVideoStateChanged(Conference c, int videoState) { }
public void onVideoProviderChanged(Conference c, Connection.VideoProvider videoProvider) {}
public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {}
- public void onExtrasChanged(Conference conference, Bundle extras) {}
+ public void onExtrasChanged(Conference c, Bundle extras) {}
+ public void onExtrasRemoved(Conference c, List<String> keys) {}
}
private final Set<Listener> mListeners = new CopyOnWriteArraySet<>();
@@ -75,6 +78,7 @@ public abstract class Conference extends Conferenceable {
private long mConnectTimeMillis = CONNECT_TIME_NOT_SPECIFIED;
private StatusHints mStatusHints;
private Bundle mExtras;
+ private Set<String> mPreviousExtraKeys;
private final Connection.Listener mConnectionDeathListener = new Connection.Listener() {
@Override
@@ -640,23 +644,171 @@ public abstract class Conference extends Conferenceable {
}
/**
- * Set some extras that can be associated with this {@code Conference}. No assumptions should
- * be made as to how an In-Call UI or service will handle these extras.
+ * Replaces all the extras associated with this {@code Conference}.
+ * <p>
+ * New or existing keys are replaced in the {@code Conference} extras. Keys which are no longer
+ * in the new extras, but were present the last time {@code setExtras} was called are removed.
+ * <p>
+ * No assumptions should be made as to how an In-Call UI or service will handle these extras.
* Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
*
- * @param extras The extras associated with this {@code Connection}.
+ * @param extras The extras associated with this {@code Conference}.
+ * @deprecated Use {@link #putExtras(Bundle)} to add extras. Use {@link #removeExtras(List)}
+ * to remove extras.
*/
public final void setExtras(@Nullable Bundle extras) {
- mExtras = extras;
+ // Add/replace any new or changed extras values.
+ putExtras(extras);
+
+ // If we have used "setExtras" in the past, compare the key set from the last invocation to
+ // the current one and remove any keys that went away.
+ if (mPreviousExtraKeys != null) {
+ List<String> toRemove = new ArrayList<String>();
+ for (String oldKey : mPreviousExtraKeys) {
+ if (!extras.containsKey(oldKey)) {
+ toRemove.add(oldKey);
+ }
+ }
+
+ if (!toRemove.isEmpty()) {
+ removeExtras(toRemove);
+ }
+ }
+
+ // Track the keys the last time set called setExtras. This way, the next time setExtras is
+ // called we can see if the caller has removed any extras values.
+ if (mPreviousExtraKeys == null) {
+ mPreviousExtraKeys = new ArraySet<String>();
+ }
+ mPreviousExtraKeys.clear();
+ mPreviousExtraKeys.addAll(extras.keySet());
+ }
+
+ /**
+ * Adds some extras to this {@link Conference}. Existing keys are replaced and new ones are
+ * added.
+ * <p>
+ * No assumptions should be made as to how an In-Call UI or service will handle these extras.
+ * Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
+ *
+ * @param extras The extras to add.
+ */
+ public final void putExtras(@NonNull Bundle extras) {
+ if (extras == null) {
+ return;
+ }
+
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putAll(extras);
+
for (Listener l : mListeners) {
l.onExtrasChanged(this, extras);
}
}
/**
- * @return The extras associated with this conference.
+ * Adds a boolean extra to this {@link Conference}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, boolean value) {
+ Bundle newExtras = new Bundle();
+ newExtras.putBoolean(key, value);
+ putExtras(newExtras);
+ }
+
+ /**
+ * Adds an integer extra to this {@link Conference}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, int value) {
+ Bundle newExtras = new Bundle();
+ newExtras.putInt(key, value);
+ putExtras(newExtras);
+ }
+
+ /**
+ * Adds a string extra to this {@link Conference}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, String value) {
+ Bundle newExtras = new Bundle();
+ newExtras.putString(key, value);
+ putExtras(newExtras);
+ }
+
+ /**
+ * Removes an extra from this {@link Conference}.
+ *
+ * @param keys The key of the extra key to remove.
+ */
+ public final void removeExtras(List<String> keys) {
+ if (keys == null || keys.isEmpty()) {
+ return;
+ }
+
+ if (mExtras != null) {
+ for (String key : keys) {
+ mExtras.remove(key);
+ }
+ if (mExtras.size() == 0) {
+ mExtras = null;
+ }
+ }
+
+ for (Listener l : mListeners) {
+ l.onExtrasRemoved(this, keys);
+ }
+ }
+
+ /**
+ * Returns the extras associated with this conference.
+ * <p>
+ * Extras should be updated using {@link #putExtras(Bundle)} and {@link #removeExtras(List)}.
+ * <p>
+ * Telecom or an {@link InCallService} can also update the extras via
+ * {@link android.telecom.Call#putExtras(Bundle)}, and
+ * {@link Call#removeExtras(List)}.
+ * <p>
+ * The conference is notified of changes to the extras made by Telecom or an
+ * {@link InCallService} by {@link #onExtrasChanged(Bundle)}.
+ *
+ * @return The extras associated with this connection.
*/
public final Bundle getExtras() {
return mExtras;
}
+
+ /**
+ * Notifies this {@link Conference} of a change to the extras made outside the
+ * {@link ConnectionService}.
+ * <p>
+ * These extras changes can originate from Telecom itself, or from an {@link InCallService} via
+ * {@link android.telecom.Call#putExtras(Bundle)}, and
+ * {@link Call#removeExtras(List)}.
+ *
+ * @param extras The new extras bundle.
+ */
+ public void onExtrasChanged(Bundle extras) {}
+
+ /**
+ * Handles a change to extras received from Telecom.
+ *
+ * @param extras The new extras.
+ * @hide
+ */
+ final void handleExtrasChanged(Bundle extras) {
+ mExtras = extras;
+ onExtrasChanged(mExtras);
+ }
}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 51a65882b802..3ea1c6a7663b 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -20,6 +20,7 @@ import com.android.internal.os.SomeArgs;
import com.android.internal.telecom.IVideoCallback;
import com.android.internal.telecom.IVideoProvider;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.hardware.camera2.CameraManager;
@@ -30,6 +31,7 @@ import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
+import android.util.ArraySet;
import android.view.Surface;
import java.util.ArrayList;
@@ -516,6 +518,7 @@ public abstract class Connection extends Conferenceable {
public void onConferenceStarted() {}
public void onConferenceMergeFailed(Connection c) {}
public void onExtrasChanged(Connection c, Bundle extras) {}
+ public void onExtrasRemoved(Connection c, List<String> keys) {}
public void onConnectionEvent(Connection c, String event, Bundle extras) {}
}
@@ -1183,6 +1186,13 @@ public abstract class Connection extends Conferenceable {
private Bundle mExtras;
/**
+ * Tracks the key set for the extras bundle provided on the last invocation of
+ * {@link #setExtras(Bundle)}. Used so that on subsequent invocations we can remove any extras
+ * keys which were set previously but are no longer present in the replacement Bundle.
+ */
+ private Set<String> mPreviousExtraKeys;
+
+ /**
* Create a new Connection.
*/
public Connection() {}
@@ -1318,6 +1328,17 @@ public abstract class Connection extends Conferenceable {
}
/**
+ * Returns the extras associated with this connection.
+ * <p>
+ * Extras should be updated using {@link #putExtras(Bundle)}.
+ * <p>
+ * Telecom or an {@link InCallService} can also update the extras via
+ * {@link android.telecom.Call#putExtras(Bundle)}, and
+ * {@link Call#removeExtras(List)}.
+ * <p>
+ * The connection is notified of changes to the extras made by Telecom or an
+ * {@link InCallService} by {@link #onExtrasChanged(Bundle)}.
+ *
* @return The extras associated with this connection.
*/
public final Bundle getExtras() {
@@ -1777,21 +1798,133 @@ public abstract class Connection extends Conferenceable {
}
/**
- * Set some extras that can be associated with this {@code Connection}. No assumptions should
- * be made as to how an In-Call UI or service will handle these extras.
+ * Set some extras that can be associated with this {@code Connection}.
+ * <p>
+ * New or existing keys are replaced in the {@code Connection} extras. Keys which are no longer
+ * in the new extras, but were present the last time {@code setExtras} was called are removed.
+ * <p>
+ * No assumptions should be made as to how an In-Call UI or service will handle these extras.
* Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
*
* @param extras The extras associated with this {@code Connection}.
+ * @deprecated Use {@link #putExtras(Bundle)} to add extras. Use {@link #removeExtras(List)}
+ * to remove extras.
*/
public final void setExtras(@Nullable Bundle extras) {
checkImmutable();
- mExtras = extras;
+
+ // Add/replace any new or changed extras values.
+ putExtras(extras);
+
+ // If we have used "setExtras" in the past, compare the key set from the last invocation to
+ // the current one and remove any keys that went away.
+ if (mPreviousExtraKeys != null) {
+ List<String> toRemove = new ArrayList<String>();
+ for (String oldKey : mPreviousExtraKeys) {
+ if (!extras.containsKey(oldKey)) {
+ toRemove.add(oldKey);
+ }
+ }
+ if (!toRemove.isEmpty()) {
+ removeExtras(toRemove);
+ }
+ }
+
+ // Track the keys the last time set called setExtras. This way, the next time setExtras is
+ // called we can see if the caller has removed any extras values.
+ if (mPreviousExtraKeys == null) {
+ mPreviousExtraKeys = new ArraySet<String>();
+ }
+ mPreviousExtraKeys.clear();
+ mPreviousExtraKeys.addAll(extras.keySet());
+ }
+
+ /**
+ * Adds some extras to this {@code Connection}. Existing keys are replaced and new ones are
+ * added.
+ * <p>
+ * No assumptions should be made as to how an In-Call UI or service will handle these extras.
+ * Keys should be fully qualified (e.g., com.example.MY_EXTRA) to avoid conflicts.
+ *
+ * @param extras The extras to add.
+ */
+ public final void putExtras(@NonNull Bundle extras) {
+ checkImmutable();
+ if (extras == null) {
+ return;
+ }
+
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putAll(extras);
+
for (Listener l : mListeners) {
l.onExtrasChanged(this, extras);
}
}
/**
+ * Adds a boolean extra to this {@code Connection}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, boolean value) {
+ Bundle newExtras = new Bundle();
+ newExtras.putBoolean(key, value);
+ putExtras(newExtras);
+ }
+
+ /**
+ * Adds an integer extra to this {@code Connection}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, int value) {
+ Bundle newExtras = new Bundle();
+ newExtras.putInt(key, value);
+ putExtras(newExtras);
+ }
+
+ /**
+ * Adds a string extra to this {@code Connection}.
+ *
+ * @param key The extra key.
+ * @param value The value.
+ * @hide
+ */
+ public final void putExtra(String key, String value) {
+ Bundle newExtras = new Bundle();
+ newExtras.putString(key, value);
+ putExtras(newExtras);
+ }
+
+ /**
+ * Removes an extra from this {@code Connection}.
+ *
+ * @param keys The key of the extra key to remove.
+ */
+ public final void removeExtras(List<String> keys) {
+ if (mExtras != null) {
+ for (String key : keys) {
+ mExtras.remove(key);
+ }
+
+ if (mExtras.size() == 0) {
+ mExtras = null;
+ }
+ }
+
+ for (Listener l : mListeners) {
+ l.onExtrasRemoved(this, keys);
+ }
+ }
+
+ /**
* Notifies this Connection that the {@link #getAudioState()} property has a new value.
*
* @param state The new connection audio state.
@@ -1928,6 +2061,18 @@ public abstract class Connection extends Conferenceable {
*/
public void onCallEvent(String event, Bundle extras) {}
+ /**
+ * Notifies this {@link Connection} of a change to the extras made outside the
+ * {@link ConnectionService}.
+ * <p>
+ * These extras changes can originate from Telecom itself, or from an {@link InCallService} via
+ * the {@link android.telecom.Call#putExtras(Bundle)} and
+ * {@link Call#removeExtras(List)}.
+ *
+ * @param extras The new extras bundle.
+ */
+ public void onExtrasChanged(Bundle extras) {}
+
static String toLogSafePhoneNumber(String number) {
// For unknown number, log empty string.
if (number == null) {
@@ -2048,6 +2193,17 @@ public abstract class Connection extends Conferenceable {
}
/**
+ * Handles a change to extras received from Telecom.
+ *
+ * @param extras The new extras.
+ * @hide
+ */
+ final void handleExtrasChanged(Bundle extras) {
+ mExtras = extras;
+ onExtrasChanged(mExtras);
+ }
+
+ /**
* Notifies listeners that the merge request failed.
*
* @hide
diff --git a/telecomm/java/android/telecom/ConnectionService.java b/telecomm/java/android/telecom/ConnectionService.java
index d18b31725aaa..e092095eaed3 100644
--- a/telecomm/java/android/telecom/ConnectionService.java
+++ b/telecomm/java/android/telecom/ConnectionService.java
@@ -105,6 +105,7 @@ public abstract class ConnectionService extends Service {
private static final int MSG_SILENCE = 21;
private static final int MSG_PULL_EXTERNAL_CALL = 22;
private static final int MSG_SEND_CALL_EVENT = 23;
+ private static final int MSG_ON_EXTRAS_CHANGED = 24;
private static Connection sNullConnection;
@@ -261,6 +262,14 @@ public abstract class ConnectionService extends Service {
args.arg3 = extras;
mHandler.obtainMessage(MSG_SEND_CALL_EVENT, args).sendToTarget();
}
+
+ @Override
+ public void onExtrasChanged(String callId, Bundle extras) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = callId;
+ args.arg2 = extras;
+ mHandler.obtainMessage(MSG_ON_EXTRAS_CHANGED, args).sendToTarget();
+ }
};
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@@ -414,6 +423,17 @@ public abstract class ConnectionService extends Service {
}
break;
}
+ case MSG_ON_EXTRAS_CHANGED: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ String callId = (String) args.arg1;
+ Bundle extras = (Bundle) args.arg2;
+ handleExtrasChanged(callId, extras);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
default:
break;
}
@@ -492,13 +512,25 @@ public abstract class ConnectionService extends Service {
@Override
public void onStatusHintsChanged(Conference conference, StatusHints statusHints) {
String id = mIdByConference.get(conference);
- mAdapter.setStatusHints(id, statusHints);
+ if (id != null) {
+ mAdapter.setStatusHints(id, statusHints);
+ }
}
@Override
- public void onExtrasChanged(Conference conference, Bundle extras) {
- String id = mIdByConference.get(conference);
- mAdapter.setExtras(id, extras);
+ public void onExtrasChanged(Conference c, Bundle extras) {
+ String id = mIdByConference.get(c);
+ if (id != null) {
+ mAdapter.putExtras(id, extras);
+ }
+ }
+
+ @Override
+ public void onExtrasRemoved(Conference c, List<String> keys) {
+ String id = mIdByConference.get(c);
+ if (id != null) {
+ mAdapter.removeExtras(id, keys);
+ }
}
};
@@ -639,13 +671,21 @@ public abstract class ConnectionService extends Service {
}
@Override
- public void onExtrasChanged(Connection connection, Bundle extras) {
- String id = mIdByConnection.get(connection);
+ public void onExtrasChanged(Connection c, Bundle extras) {
+ String id = mIdByConnection.get(c);
+ if (id != null) {
+ mAdapter.putExtras(id, extras);
+ }
+ }
+
+ public void onExtrasRemoved(Connection c, List<String> keys) {
+ String id = mIdByConnection.get(c);
if (id != null) {
- mAdapter.setExtras(id, extras);
+ mAdapter.removeExtras(id, keys);
}
}
+
@Override
public void onConnectionEvent(Connection connection, String event, Bundle extras) {
String id = mIdByConnection.get(connection);
@@ -929,6 +969,27 @@ public abstract class ConnectionService extends Service {
}
+ /**
+ * Notifies a {@link Connection} or {@link Conference} of a change to the extras from Telecom.
+ * <p>
+ * These extra changes can originate from Telecom itself, or from an {@link InCallService} via
+ * the {@link android.telecom.Call#putExtra(String, boolean)},
+ * {@link android.telecom.Call#putExtra(String, int)},
+ * {@link android.telecom.Call#putExtra(String, String)},
+ * {@link Call#removeExtras(List)}.
+ *
+ * @param callId The ID of the call receiving the event.
+ * @param extras The new extras bundle.
+ */
+ private void handleExtrasChanged(String callId, Bundle extras) {
+ Log.d(this, "handleExtrasChanged(%s, %s)", callId, extras);
+ if (mConnectionById.containsKey(callId)) {
+ findConnectionForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
+ } else if (mConferenceById.containsKey(callId)) {
+ findConferenceForAction(callId, "handleExtrasChanged").handleExtrasChanged(extras);
+ }
+ }
+
private void onPostDialContinue(String callId, boolean proceed) {
Log.d(this, "onPostDialContinue(%s)", callId);
findConnectionForAction(callId, "stopDtmfTone").onPostDialContinue(proceed);
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapter.java b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
index e91128f1f7bc..81e4c2271c14 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapter.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapter.java
@@ -398,16 +398,88 @@ final class ConnectionServiceAdapter implements DeathRecipient {
}
/**
- * Sets extras associated with a connection.
+ * Adds some extras associated with a {@code Connection}.
*
* @param callId The unique ID of the call.
- * @param extras The extras to associate with this call.
+ * @param extras The extras to add.
*/
- void setExtras(String callId, Bundle extras) {
- Log.v(this, "setExtras: %s", extras);
+ void putExtras(String callId, Bundle extras) {
+ Log.v(this, "putExtras: %s", callId);
for (IConnectionServiceAdapter adapter : mAdapters) {
try {
- adapter.setExtras(callId, extras);
+ adapter.putExtras(callId, extras);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ /**
+ * Adds an extra associated with a {@code Connection}.
+ *
+ * @param callId The unique ID of the call.
+ * @param key The extra key.
+ * @param value The extra value.
+ */
+ void putExtra(String callId, String key, boolean value) {
+ Log.v(this, "putExtra: %s %s=%b", callId, key, value);
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(key, value);
+ adapter.putExtras(callId, bundle);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ /**
+ * Adds an extra associated with a {@code Connection}.
+ *
+ * @param callId The unique ID of the call.
+ * @param key The extra key.
+ * @param value The extra value.
+ */
+ void putExtra(String callId, String key, int value) {
+ Log.v(this, "putExtra: %s %s=%d", callId, key, value);
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ Bundle bundle = new Bundle();
+ bundle.putInt(key, value);
+ adapter.putExtras(callId, bundle);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ /**
+ * Adds an extra associated with a {@code Connection}.
+ *
+ * @param callId The unique ID of the call.
+ * @param key The extra key.
+ * @param value The extra value.
+ */
+ void putExtra(String callId, String key, String value) {
+ Log.v(this, "putExtra: %s %s=%s", callId, key, value);
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ Bundle bundle = new Bundle();
+ bundle.putString(key, value);
+ adapter.putExtras(callId, bundle);
+ } catch (RemoteException ignored) {
+ }
+ }
+ }
+
+ /**
+ * Removes extras associated with a {@code Connection}.
+ * @param callId The unique ID of the call.
+ * @param keys The extra keys to remove.
+ */
+ void removeExtras(String callId, List<String> keys) {
+ Log.v(this, "removeExtras: %s %s", callId, keys);
+ for (IConnectionServiceAdapter adapter : mAdapters) {
+ try {
+ adapter.removeExtras(callId, keys);
} catch (RemoteException ignored) {
}
}
diff --git a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
index 4b15e541d0dc..3e465577e2f3 100644
--- a/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
+++ b/telecomm/java/android/telecom/ConnectionServiceAdapterServant.java
@@ -61,8 +61,9 @@ final class ConnectionServiceAdapterServant {
private static final int MSG_ADD_EXISTING_CONNECTION = 21;
private static final int MSG_ON_POST_DIAL_CHAR = 22;
private static final int MSG_SET_CONFERENCE_MERGE_FAILED = 23;
- private static final int MSG_SET_EXTRAS = 24;
- private static final int MSG_ON_CONNECTION_EVENT = 25;
+ private static final int MSG_PUT_EXTRAS = 24;
+ private static final int MSG_REMOVE_EXTRAS = 25;
+ private static final int MSG_ON_CONNECTION_EVENT = 26;
private final IConnectionServiceAdapter mDelegate;
@@ -233,10 +234,19 @@ final class ConnectionServiceAdapterServant {
}
break;
}
- case MSG_SET_EXTRAS: {
+ case MSG_PUT_EXTRAS: {
SomeArgs args = (SomeArgs) msg.obj;
try {
- mDelegate.setExtras((String) args.arg1, (Bundle) args.arg2);
+ mDelegate.putExtras((String) args.arg1, (Bundle) args.arg2);
+ } finally {
+ args.recycle();
+ }
+ break;
+ }
+ case MSG_REMOVE_EXTRAS: {
+ SomeArgs args = (SomeArgs) msg.obj;
+ try {
+ mDelegate.removeExtras((String) args.arg1, (List<String>) args.arg2);
} finally {
args.recycle();
}
@@ -425,11 +435,19 @@ final class ConnectionServiceAdapterServant {
}
@Override
- public final void setExtras(String connectionId, Bundle extras) {
+ public final void putExtras(String connectionId, Bundle extras) {
SomeArgs args = SomeArgs.obtain();
args.arg1 = connectionId;
args.arg2 = extras;
- mHandler.obtainMessage(MSG_SET_EXTRAS, args).sendToTarget();
+ mHandler.obtainMessage(MSG_PUT_EXTRAS, args).sendToTarget();
+ }
+
+ @Override
+ public final void removeExtras(String connectionId, List<String> keys) {
+ SomeArgs args = SomeArgs.obtain();
+ args.arg1 = connectionId;
+ args.arg2 = keys;
+ mHandler.obtainMessage(MSG_REMOVE_EXTRAS, args).sendToTarget();
}
@Override
diff --git a/telecomm/java/android/telecom/InCallAdapter.java b/telecomm/java/android/telecom/InCallAdapter.java
index 52ef4a705e05..3f270d9c5829 100644
--- a/telecomm/java/android/telecom/InCallAdapter.java
+++ b/telecomm/java/android/telecom/InCallAdapter.java
@@ -21,6 +21,8 @@ import android.os.RemoteException;
import com.android.internal.telecom.IInCallAdapter;
+import java.util.List;
+
/**
* Receives commands from {@link InCallService} implementations which should be executed by
* Telecom. When Telecom binds to a {@link InCallService}, an instance of this class is given to
@@ -278,6 +280,79 @@ public final class InCallAdapter {
}
/**
+ * Intructs Telecom to add extras to a call.
+ *
+ * @param callId The callId to add the extras to.
+ * @param extras The extras.
+ */
+ public void putExtras(String callId, Bundle extras) {
+ try {
+ mAdapter.putExtras(callId, extras);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Intructs Telecom to add an extra to a call.
+ *
+ * @param callId The callId to add the extras to.
+ * @param key The extra key.
+ * @param value The extra value.
+ */
+ public void putExtra(String callId, String key, boolean value) {
+ try {
+ Bundle bundle = new Bundle();
+ bundle.putBoolean(key, value);
+ mAdapter.putExtras(callId, bundle);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Intructs Telecom to add an extra to a call.
+ *
+ * @param callId The callId to add the extras to.
+ * @param key The extra key.
+ * @param value The extra value.
+ */
+ public void putExtra(String callId, String key, int value) {
+ try {
+ Bundle bundle = new Bundle();
+ bundle.putInt(key, value);
+ mAdapter.putExtras(callId, bundle);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Intructs Telecom to add an extra to a call.
+ *
+ * @param callId The callId to add the extras to.
+ * @param key The extra key.
+ * @param value The extra value.
+ */
+ public void putExtra(String callId, String key, String value) {
+ try {
+ Bundle bundle = new Bundle();
+ bundle.putString(key, value);
+ mAdapter.putExtras(callId, bundle);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
+ * Intructs Telecom to remove extras from a call.
+ * @param callId The callId to remove the extras from.
+ * @param keys The extra keys to remove.
+ */
+ public void removeExtras(String callId, List<String> keys) {
+ try {
+ mAdapter.removeExtras(callId, keys);
+ } catch (RemoteException ignored) {
+ }
+ }
+
+ /**
* Instructs Telecom to turn the proximity sensor on.
*/
public void turnProximitySensorOn() {
diff --git a/telecomm/java/android/telecom/RemoteConference.java b/telecomm/java/android/telecom/RemoteConference.java
index ae5cd464d72c..b03cb51277b5 100644
--- a/telecomm/java/android/telecom/RemoteConference.java
+++ b/telecomm/java/android/telecom/RemoteConference.java
@@ -279,15 +279,35 @@ public final class RemoteConference {
}
/** @hide */
- void setExtras(final Bundle extras) {
- mExtras = extras;
+ void putExtras(final Bundle extras) {
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putAll(extras);
+
+ notifyExtrasChanged();
+ }
+
+ /** @hide */
+ void removeExtras(List<String> keys) {
+ if (mExtras == null || keys == null || keys.isEmpty()) {
+ return;
+ }
+ for (String key : keys) {
+ mExtras.remove(key);
+ }
+
+ notifyExtrasChanged();
+ }
+
+ private void notifyExtrasChanged() {
for (CallbackRecord<Callback> record : mCallbackRecords) {
final RemoteConference conference = this;
final Callback callback = record.getCallback();
record.getHandler().post(new Runnable() {
@Override
public void run() {
- callback.onExtrasChanged(conference, extras);
+ callback.onExtrasChanged(conference, mExtras);
}
});
}
diff --git a/telecomm/java/android/telecom/RemoteConnection.java b/telecomm/java/android/telecom/RemoteConnection.java
index 5b602eb49dca..7df6678bd5d3 100644
--- a/telecomm/java/android/telecom/RemoteConnection.java
+++ b/telecomm/java/android/telecom/RemoteConnection.java
@@ -1302,15 +1302,35 @@ public final class RemoteConnection {
}
/** @hide */
- void setExtras(final Bundle extras) {
- mExtras = extras;
+ void putExtras(final Bundle extras) {
+ if (mExtras == null) {
+ mExtras = new Bundle();
+ }
+ mExtras.putAll(extras);
+
+ notifyExtrasChanged();
+ }
+
+ /** @hide */
+ void removeExtras(List<String> keys) {
+ if (mExtras == null || keys == null || keys.isEmpty()) {
+ return;
+ }
+ for (String key : keys) {
+ mExtras.remove(key);
+ }
+
+ notifyExtrasChanged();
+ }
+
+ private void notifyExtrasChanged() {
for (CallbackRecord record : mCallbackRecords) {
final RemoteConnection connection = this;
final Callback callback = record.getCallback();
record.getHandler().post(new Runnable() {
@Override
public void run() {
- callback.onExtrasChanged(connection, extras);
+ callback.onExtrasChanged(connection, mExtras);
}
});
}
diff --git a/telecomm/java/android/telecom/RemoteConnectionService.java b/telecomm/java/android/telecom/RemoteConnectionService.java
index fa7183acc350..d88d007e532e 100644
--- a/telecomm/java/android/telecom/RemoteConnectionService.java
+++ b/telecomm/java/android/telecom/RemoteConnectionService.java
@@ -321,13 +321,20 @@ final class RemoteConnectionService {
}
@Override
- public void setExtras(String callId, Bundle extras) {
- if (mConnectionById.containsKey(callId)) {
- findConnectionForAction(callId, "setExtras")
- .setExtras(extras);
+ public void putExtras(String callId, Bundle extras) {
+ if (hasConnection(callId)) {
+ findConnectionForAction(callId, "putExtras").putExtras(extras);
+ } else {
+ findConferenceForAction(callId, "putExtras").putExtras(extras);
+ }
+ }
+
+ @Override
+ public void removeExtras(String callId, List<String> keys) {
+ if (hasConnection(callId)) {
+ findConnectionForAction(callId, "removeExtra").removeExtras(keys);
} else {
- findConferenceForAction(callId, "setExtras")
- .setExtras(extras);
+ findConferenceForAction(callId, "removeExtra").removeExtras(keys);
}
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
index 3ee0e9f94443..a4c179820331 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionService.aidl
@@ -79,4 +79,6 @@ oneway interface IConnectionService {
void pullExternalCall(String callId);
void sendCallEvent(String callId, String event, in Bundle extras);
+
+ void onExtrasChanged(String callId, in Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
index dff1b1138741..680480500eea 100644
--- a/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IConnectionServiceAdapter.aidl
@@ -85,7 +85,9 @@ oneway interface IConnectionServiceAdapter {
void addExistingConnection(String callId, in ParcelableConnection connection);
- void setExtras(String callId, in Bundle extras);
+ void putExtras(String callId, in Bundle extras);
+
+ void removeExtras(String callId, in List<String> keys);
void onConnectionEvent(String callId, String event, in Bundle extras);
}
diff --git a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
index 0678fe2c0aa4..49f9b3b8af73 100644
--- a/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
+++ b/telecomm/java/com/android/internal/telecom/IInCallAdapter.aidl
@@ -65,4 +65,8 @@ oneway interface IInCallAdapter {
void pullExternalCall(String callId);
void sendCallEvent(String callId, String event, in Bundle extras);
+
+ void putExtras(String callId, in Bundle extras);
+
+ void removeExtras(String callId, in List<String> keys);
}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index ae130d4ac34f..bb2b4478433d 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -32,6 +32,7 @@ import android.telephony.PreciseDataConnectionState;
import com.android.internal.telephony.IPhoneStateListener;
import java.util.List;
+import java.lang.ref.WeakReference;
/**
* A listener class for monitoring changes in specific telephony states
@@ -533,84 +534,101 @@ public class PhoneStateListener {
/**
* The callback methods need to be called on the handler thread where
* this object was created. If the binder did that for us it'd be nice.
- */
- IPhoneStateListener callback = new IPhoneStateListener.Stub() {
+ *
+ * Using a static class and weak reference here to avoid memory leak caused by the
+ * IPhoneStateListener.Stub callback retaining references to the outside PhoneStateListeners:
+ * even caller has been destroyed and "un-registered" the PhoneStateListener, it is still not
+ * eligible for GC given the references coming from:
+ * Native Stack --> PhoneStateListener --> Context (Activity).
+ * memory of caller's context will be collected after GC from service side get triggered
+ */
+ private static class IPhoneStateListenerStub extends IPhoneStateListener.Stub {
+ private WeakReference<PhoneStateListener> mPhoneStateListenerWeakRef;
+
+ public IPhoneStateListenerStub(PhoneStateListener phoneStateListener) {
+ mPhoneStateListenerWeakRef = new WeakReference<PhoneStateListener>(phoneStateListener);
+ }
+
+ private void send(int what, int arg1, int arg2, Object obj) {
+ PhoneStateListener listener = mPhoneStateListenerWeakRef.get();
+ if (listener != null) {
+ Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
+ }
+ }
+
public void onServiceStateChanged(ServiceState serviceState) {
- Message.obtain(mHandler, LISTEN_SERVICE_STATE, 0, 0, serviceState).sendToTarget();
+ send(LISTEN_SERVICE_STATE, 0, 0, serviceState);
}
public void onSignalStrengthChanged(int asu) {
- Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTH, asu, 0, null).sendToTarget();
+ send(LISTEN_SIGNAL_STRENGTH, asu, 0, null);
}
public void onMessageWaitingIndicatorChanged(boolean mwi) {
- Message.obtain(mHandler, LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null)
- .sendToTarget();
+ send(LISTEN_MESSAGE_WAITING_INDICATOR, mwi ? 1 : 0, 0, null);
}
public void onCallForwardingIndicatorChanged(boolean cfi) {
- Message.obtain(mHandler, LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null)
- .sendToTarget();
+ send(LISTEN_CALL_FORWARDING_INDICATOR, cfi ? 1 : 0, 0, null);
}
public void onCellLocationChanged(Bundle bundle) {
CellLocation location = CellLocation.newFromBundle(bundle);
- Message.obtain(mHandler, LISTEN_CELL_LOCATION, 0, 0, location).sendToTarget();
+ send(LISTEN_CELL_LOCATION, 0, 0, location);
}
public void onCallStateChanged(int state, String incomingNumber) {
- Message.obtain(mHandler, LISTEN_CALL_STATE, state, 0, incomingNumber).sendToTarget();
+ send(LISTEN_CALL_STATE, state, 0, incomingNumber);
}
public void onDataConnectionStateChanged(int state, int networkType) {
- Message.obtain(mHandler, LISTEN_DATA_CONNECTION_STATE, state, networkType).
- sendToTarget();
+ send(LISTEN_DATA_CONNECTION_STATE, state, networkType, null);
}
public void onDataActivity(int direction) {
- Message.obtain(mHandler, LISTEN_DATA_ACTIVITY, direction, 0, null).sendToTarget();
+ send(LISTEN_DATA_ACTIVITY, direction, 0, null);
}
public void onSignalStrengthsChanged(SignalStrength signalStrength) {
- Message.obtain(mHandler, LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength).sendToTarget();
+ send(LISTEN_SIGNAL_STRENGTHS, 0, 0, signalStrength);
}
public void onOtaspChanged(int otaspMode) {
- Message.obtain(mHandler, LISTEN_OTASP_CHANGED, otaspMode, 0).sendToTarget();
+ send(LISTEN_OTASP_CHANGED, otaspMode, 0, null);
}
public void onCellInfoChanged(List<CellInfo> cellInfo) {
- Message.obtain(mHandler, LISTEN_CELL_INFO, 0, 0, cellInfo).sendToTarget();
+ send(LISTEN_CELL_INFO, 0, 0, cellInfo);
}
public void onPreciseCallStateChanged(PreciseCallState callState) {
- Message.obtain(mHandler, LISTEN_PRECISE_CALL_STATE, 0, 0, callState).sendToTarget();
+ send(LISTEN_PRECISE_CALL_STATE, 0, 0, callState);
}
public void onPreciseDataConnectionStateChanged(
PreciseDataConnectionState dataConnectionState) {
- Message.obtain(mHandler, LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0,
- dataConnectionState).sendToTarget();
+ send(LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0, dataConnectionState);
}
public void onDataConnectionRealTimeInfoChanged(
DataConnectionRealTimeInfo dcRtInfo) {
- Message.obtain(mHandler, LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0,
- dcRtInfo).sendToTarget();
+ send(LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0, dcRtInfo);
}
public void onVoLteServiceStateChanged(VoLteServiceState lteState) {
- Message.obtain(mHandler, LISTEN_VOLTE_STATE, 0, 0, lteState).sendToTarget();
+ send(LISTEN_VOLTE_STATE, 0, 0, lteState);
}
public void onOemHookRawEvent(byte[] rawData) {
- Message.obtain(mHandler, LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData).sendToTarget();
+ send(LISTEN_OEM_HOOK_RAW_EVENT, 0, 0, rawData);
}
public void onCarrierNetworkChange(boolean active) {
- Message.obtain(mHandler, LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active).sendToTarget();
+ send(LISTEN_CARRIER_NETWORK_CHANGE, 0, 0, active);
}
- };
+ }
+
+ IPhoneStateListener callback = new IPhoneStateListenerStub(this);
private void log(String s) {
Rlog.d(LOG_TAG, s);
diff --git a/telephony/java/com/android/ims/ImsExternalCallState.java b/telephony/java/com/android/ims/ImsExternalCallState.java
index edb6bfcf68c0..71c1837b6ff8 100644
--- a/telephony/java/com/android/ims/ImsExternalCallState.java
+++ b/telephony/java/com/android/ims/ImsExternalCallState.java
@@ -28,7 +28,7 @@ import android.telephony.Rlog;
*/
/**
- * Parcelable object to handle VICE Dialog Information
+ * Parcelable object to handle MultiEndpoint Dialog Information
* @hide
*/
public class ImsExternalCallState implements Parcelable {
@@ -39,19 +39,30 @@ public class ImsExternalCallState implements Parcelable {
public static final int CALL_STATE_CONFIRMED = 1;
public static final int CALL_STATE_TERMINATED = 2;
// Dialog Id
- public int mCallId;
+ private int mCallId;
// Number
- public Uri mAddress;
- public boolean mIsPullable;
+ private Uri mAddress;
+ private boolean mIsPullable;
// CALL_STATE_CONFIRMED / CALL_STATE_TERMINATED
- public int mCallState;
+ private int mCallState;
// ImsCallProfile#CALL_TYPE_*
- public int mCallType;
- public boolean mIsHeld;
+ private int mCallType;
+ private boolean mIsHeld;
public ImsExternalCallState() {
}
+ public ImsExternalCallState(int callId, Uri address, boolean isPullable, int callState,
+ int callType, boolean isCallheld) {
+ mCallId = callId;
+ mAddress = address;
+ mIsPullable = isPullable;
+ mCallState = callState;
+ mCallType = callType;
+ mIsHeld = isCallheld;
+ Rlog.d(TAG, "ImsExternalCallState = " + this);
+ }
+
public ImsExternalCallState(Parcel in) {
mCallId = in.readInt();
ClassLoader classLoader = ImsExternalCallState.class.getClassLoader();
@@ -60,12 +71,7 @@ public class ImsExternalCallState implements Parcelable {
mCallState = in.readInt();
mCallType = in.readInt();
mIsHeld = (in.readInt() != 0);
- Rlog.d(TAG, "ImsExternalCallState const = " +
- "callid = " + getCallId() +
- ", address = " + getAddress() +
- ", mCallState = " + getCallState() +
- ", calltype = " + getCallType() +
- ", isheld = " + isCallHeld());
+ Rlog.d(TAG, "ImsExternalCallState const = " + this);
}
@Override
@@ -81,6 +87,7 @@ public class ImsExternalCallState implements Parcelable {
out.writeInt(mCallState);
out.writeInt(mCallType);
out.writeInt(mIsHeld ? 1 : 0);
+ Rlog.d(TAG, "ImsExternalCallState writeToParcel = " + out.toString());
}
public static final Parcelable.Creator<ImsExternalCallState> CREATOR =
diff --git a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
index 70a474ec41da..27b8fa174171 100644
--- a/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
+++ b/telephony/java/com/android/ims/internal/IImsExternalCallStateListener.aidl
@@ -32,7 +32,7 @@ interface IImsExternalCallStateListener {
*
* @return void.
*/
- void notifyRefreshExternalCallState(in List<ImsExternalCallState> externalCallDialogs);
+ void onImsExternalCallStateUpdate(in List<ImsExternalCallState> externalCallDialogs);
}
diff --git a/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl b/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl
index 1bfb9b2b4d78..1374caae6549 100644
--- a/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl
+++ b/telephony/java/com/android/ims/internal/IImsMultiEndpoint.aidl
@@ -34,5 +34,5 @@ interface IImsMultiEndpoint {
* Query api to get the latest Dialog Event Package information
* Should be invoked only after setListener is done
*/
- void requestDialogEventPackageState();
+ void requestImsExternalCallStateInfo();
}
diff --git a/telephony/java/com/android/internal/telephony/TelephonyProperties.java b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
index ea3b5c97c4c9..6567ea764b50 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyProperties.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyProperties.java
@@ -218,11 +218,4 @@ public interface TelephonyProperties
*/
static final String PROPERTY_VIDEOCALL_AUDIO_OUTPUT = "persist.radio.call.audio.output";
- /**
- * For MultiEndpoint Feature
- * If true: Dial intent is for call pull functionality
- * if false: normal dial
- */
- static final String EXTRA_IS_CALL_PULL =
- "android.telephony.extra.IS_CALL_PULL";
}
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index de7b9c268c99..18fd98528855 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -347,6 +347,15 @@
</activity>
<activity
+ android:name="SingleFrameTextureViewTestActivity"
+ android:label="TextureView/SingleFrameTextureViewTest">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.hwui.TEST" />
+ </intent-filter>
+ </activity>
+
+ <activity
android:name="HardwareCanvasSurfaceViewActivity"
android:label="SurfaceView/HardwareCanvas">
<intent-filter>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java
new file mode 100644
index 000000000000..4d3826b68247
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/SingleFrameTextureViewTestActivity.java
@@ -0,0 +1,217 @@
+/*
+ * 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.
+ */
+
+package com.android.test.hwui;
+
+import static android.opengl.GLES20.GL_COLOR_BUFFER_BIT;
+import static android.opengl.GLES20.glClear;
+import static android.opengl.GLES20.glClearColor;
+
+import android.app.Activity;
+import android.graphics.Color;
+import android.graphics.SurfaceTexture;
+import android.opengl.GLUtils;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.TextureView;
+import android.view.TextureView.SurfaceTextureListener;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.FrameLayout;
+import android.widget.TextView;
+
+import javax.microedition.khronos.egl.EGL10;
+import javax.microedition.khronos.egl.EGLConfig;
+import javax.microedition.khronos.egl.EGLContext;
+import javax.microedition.khronos.egl.EGLDisplay;
+import javax.microedition.khronos.egl.EGLSurface;
+
+public class SingleFrameTextureViewTestActivity extends Activity implements SurfaceTextureListener {
+ private static final String LOG_TAG = "SingleFrameTest";
+
+ private View mPreview;
+ private TextureView mTextureView;
+ private Thread mGLThread;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ TextView preview = new TextView(this);
+ preview.setText("This is a preview");
+ preview.setBackgroundColor(Color.WHITE);
+ mPreview = preview;
+ mTextureView = new TextureView(this);
+ mTextureView.setSurfaceTextureListener(this);
+
+ FrameLayout content = new FrameLayout(this);
+ content.addView(mTextureView,
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+ content.addView(mPreview,
+ LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
+
+ setContentView(content);
+ }
+
+ private void stopGlThread() {
+ if (mGLThread != null) {
+ try {
+ mGLThread.join();
+ mGLThread = null;
+ } catch (InterruptedException e) { }
+ }
+ }
+
+ @Override
+ public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
+ Log.d(LOG_TAG, "onSurfaceAvailable");
+ mGLThread = new Thread() {
+ static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
+ static final int EGL_OPENGL_ES2_BIT = 4;
+
+ private EGL10 mEgl;
+ private EGLDisplay mEglDisplay;
+ private EGLConfig mEglConfig;
+ private EGLContext mEglContext;
+ private EGLSurface mEglSurface;
+
+ @Override
+ public void run() {
+ initGL();
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {}
+
+ for (int i = 0; i < 2; i++) {
+ if (i == 0) {
+ glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
+ } else {
+ glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+ Log.d(LOG_TAG, "eglSwapBuffers");
+ if (!mEgl.eglSwapBuffers(mEglDisplay, mEglSurface)) {
+ throw new RuntimeException("Cannot swap buffers");
+ }
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException e) {}
+ }
+
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {}
+
+ finishGL();
+ }
+
+ private void finishGL() {
+ mEgl.eglDestroyContext(mEglDisplay, mEglContext);
+ mEgl.eglDestroySurface(mEglDisplay, mEglSurface);
+ }
+
+ private void initGL() {
+ mEgl = (EGL10) EGLContext.getEGL();
+
+ mEglDisplay = mEgl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
+ if (mEglDisplay == EGL10.EGL_NO_DISPLAY) {
+ throw new RuntimeException("eglGetDisplay failed "
+ + GLUtils.getEGLErrorString(mEgl.eglGetError()));
+ }
+
+ int[] version = new int[2];
+ if (!mEgl.eglInitialize(mEglDisplay, version)) {
+ throw new RuntimeException("eglInitialize failed " +
+ GLUtils.getEGLErrorString(mEgl.eglGetError()));
+ }
+
+ mEglConfig = chooseEglConfig();
+ if (mEglConfig == null) {
+ throw new RuntimeException("eglConfig not initialized");
+ }
+
+ mEglContext = createContext(mEgl, mEglDisplay, mEglConfig);
+
+ mEglSurface = mEgl.eglCreateWindowSurface(mEglDisplay, mEglConfig, surface, null);
+
+ if (mEglSurface == null || mEglSurface == EGL10.EGL_NO_SURFACE) {
+ int error = mEgl.eglGetError();
+ if (error == EGL10.EGL_BAD_NATIVE_WINDOW) {
+ Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
+ return;
+ }
+ throw new RuntimeException("createWindowSurface failed "
+ + GLUtils.getEGLErrorString(error));
+ }
+
+ if (!mEgl.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
+ throw new RuntimeException("eglMakeCurrent failed "
+ + GLUtils.getEGLErrorString(mEgl.eglGetError()));
+ }
+ }
+
+
+ EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
+ int[] attrib_list = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };
+ return egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
+ }
+
+ private EGLConfig chooseEglConfig() {
+ int[] configsCount = new int[1];
+ EGLConfig[] configs = new EGLConfig[1];
+ int[] configSpec = getConfig();
+ if (!mEgl.eglChooseConfig(mEglDisplay, configSpec, configs, 1, configsCount)) {
+ throw new IllegalArgumentException("eglChooseConfig failed " +
+ GLUtils.getEGLErrorString(mEgl.eglGetError()));
+ } else if (configsCount[0] > 0) {
+ return configs[0];
+ }
+ return null;
+ }
+
+ private int[] getConfig() {
+ return new int[] {
+ EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL10.EGL_RED_SIZE, 8,
+ EGL10.EGL_GREEN_SIZE, 8,
+ EGL10.EGL_BLUE_SIZE, 8,
+ EGL10.EGL_ALPHA_SIZE, 8,
+ EGL10.EGL_DEPTH_SIZE, 0,
+ EGL10.EGL_STENCIL_SIZE, 0,
+ EGL10.EGL_NONE
+ };
+ }
+ };
+ mGLThread.start();
+ }
+
+ @Override
+ public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
+ Log.d(LOG_TAG, "onSurfaceTextureSizeChanged");
+ }
+
+ @Override
+ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
+ Log.d(LOG_TAG, "onSurfaceTextureDestroyed");
+ stopGlThread();
+ return true;
+ }
+
+ @Override
+ public void onSurfaceTextureUpdated(SurfaceTexture surface) {
+ Log.d(LOG_TAG, "onSurfaceTextureUpdated");
+ mPreview.setVisibility(View.GONE);
+ }
+}
diff --git a/tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml b/tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml
new file mode 100644
index 000000000000..5d23d36e1dbf
--- /dev/null
+++ b/tests/NetworkSecurityConfigTest/res/xml/domain_whitespace.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+ <domain-config>
+ <domain>android.com
+ </domain>
+ <domain> developer.android.com </domain>
+ <pin-set>
+ <pin digest="SHA-256"> 7HIpactkIAq2Y49orFOOQKurWxmmSFZhBCoQYcRhJ3Y= </pin>
+ </pin-set>
+ </domain-config>
+</network-security-config>
diff --git a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
index 10bcc18a0019..f7066a6f45f6 100644
--- a/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
+++ b/tests/NetworkSecurityConfigTest/src/android/security/net/config/XmlConfigTests.java
@@ -464,4 +464,16 @@ public class XmlConfigTests extends AndroidTestCase {
} catch (RuntimeException expected) {
}
}
+
+ public void testDomainWhitespaceTrimming() throws Exception {
+ XmlConfigSource source =
+ new XmlConfigSource(getContext(), R.xml.domain_whitespace, false);
+ ApplicationConfig appConfig = new ApplicationConfig(source);
+ NetworkSecurityConfig defaultConfig = appConfig.getConfigForHostname("");
+ MoreAsserts.assertNotEqual(defaultConfig, appConfig.getConfigForHostname("developer.android.com"));
+ MoreAsserts.assertNotEqual(defaultConfig, appConfig.getConfigForHostname("android.com"));
+ SSLContext context = TestUtils.getSSLContext(source);
+ TestUtils.assertConnectionSucceeds(context, "android.com", 443);
+ TestUtils.assertConnectionSucceeds(context, "developer.android.com", 443);
+ }
}
diff --git a/tools/fonts/fontchain_lint.py b/tools/fonts/fontchain_lint.py
index c16de7b3dfc3..a8483464ff47 100755
--- a/tools/fonts/fontchain_lint.py
+++ b/tools/fonts/fontchain_lint.py
@@ -255,8 +255,9 @@ def main():
ucd_path = sys.argv[2]
parse_ucd(ucd_path)
- check_emoji_availability()
- check_emoji_defaults()
+ # Temporarily disable emoji checks for Bug 27785690
+ # check_emoji_availability()
+ # check_emoji_defaults()
if __name__ == '__main__':
diff --git a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
deleted file mode 100644
index 34ae825baac8..000000000000
--- a/tools/layoutlib/bridge/src/android/graphics/AvoidXfermode_Delegate.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 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.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Composite;
-
-/**
- * Delegate implementing the native methods of android.graphics.AvoidXfermode
- *
- * Through the layoutlib_create tool, the original native methods of AvoidXfermode have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original AvoidXfermode class.
- *
- * Because this extends {@link Xfermode_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
- * {@link Xfermode_Delegate}.
- *
- */
-public class AvoidXfermode_Delegate extends Xfermode_Delegate {
-
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Composite getComposite(int alpha) {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Avoid Xfermodes are not supported in Layout Preview mode.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(int opColor, int tolerance, int nativeMode) {
- AvoidXfermode_Delegate newDelegate = new AvoidXfermode_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
index 08f0cb491882..f5938cfa37a5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Path_Delegate.java
@@ -167,13 +167,13 @@ public final class Path_Delegate {
}
@LayoutlibDelegate
- /*package*/ static void native_setFillType(long nPath, int ft) {
+ public static void native_setFillType(long nPath, int ft) {
Path_Delegate pathDelegate = sManager.getDelegate(nPath);
if (pathDelegate == null) {
return;
}
- pathDelegate.mFillType = Path.sFillTypeArray[ft];
+ pathDelegate.setFillType(Path.sFillTypeArray[ft]);
}
@LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
deleted file mode 100644
index f27144f45448..000000000000
--- a/tools/layoutlib/bridge/src/android/graphics/PixelXorXfermode_Delegate.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 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.graphics;
-
-import com.android.layoutlib.bridge.impl.DelegateManager;
-import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
-
-import java.awt.Composite;
-
-/**
- * Delegate implementing the native methods of android.graphics.PixelXorXfermode
- *
- * Through the layoutlib_create tool, the original native methods of PixelXorXfermode have been
- * replaced by calls to methods of the same name in this delegate class.
- *
- * This class behaves like the original native implementation, but in Java, keeping previously
- * native data into its own objects and mapping them to int that are sent back and forth between
- * it and the original PixelXorXfermode class.
- *
- * Because this extends {@link Xfermode_Delegate}, there's no need to use a
- * {@link DelegateManager}, as all the PathEffect classes will be added to the manager owned by
- * {@link Xfermode_Delegate}.
- *
- * @see Xfermode_Delegate
- */
-public class PixelXorXfermode_Delegate extends Xfermode_Delegate {
- // ---- delegate data ----
-
- // ---- Public Helper methods ----
-
- @Override
- public Composite getComposite(int alpha) {
- // FIXME
- return null;
- }
-
- @Override
- public boolean isSupported() {
- return false;
- }
-
- @Override
- public String getSupportMessage() {
- return "Pixel XOR Xfermodes are not supported in Layout Preview mode.";
- }
-
- // ---- native methods ----
-
- @LayoutlibDelegate
- /*package*/ static long nativeCreate(int opColor) {
- PixelXorXfermode_Delegate newDelegate = new PixelXorXfermode_Delegate();
- return sManager.addNewDelegate(newDelegate);
- }
-
- // ---- Private delegate/helper methods ----
-}
diff --git a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
index 1ca94dc7fa84..ff3f19f3f742 100644
--- a/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/PorterDuffColorFilter_Delegate.java
@@ -48,7 +48,7 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
// ---- delegate data ----
- private final int mSrcColor;
+ private final java.awt.Color mSrcColor;
private final Mode mMode;
@@ -66,9 +66,9 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
@Override
public void applyFilter(Graphics2D g, int width, int height) {
- BufferedImage image = createFilterImage(width, height);
g.setComposite(getComposite(mMode, 0xFF));
- g.drawImage(image, 0, 0, null);
+ g.setColor(mSrcColor);
+ g.fillRect(0, 0, width, height);
}
// ---- native methods ----
@@ -84,22 +84,10 @@ public class PorterDuffColorFilter_Delegate extends ColorFilter_Delegate {
// ---- Private delegate/helper methods ----
private PorterDuffColorFilter_Delegate(int srcColor, int mode) {
- mSrcColor = srcColor;
+ mSrcColor = new java.awt.Color(srcColor, true /* hasAlpha */);
mMode = getCompatibleMode(getPorterDuffMode(mode));
}
- private BufferedImage createFilterImage(int width, int height) {
- BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
- Graphics2D graphics = image.createGraphics();
- try {
- graphics.setColor(new java.awt.Color(mSrcColor, true /* hasAlpha */));
- graphics.fillRect(0, 0, width, height);
- } finally {
- graphics.dispose();
- }
- return image;
- }
-
// For filtering the colors, the src image should contain the "color" only for pixel values
// which are not transparent in the target image. But, we are using a simple rectangular image
// completely filled with color. Hence some Composite rules do not apply as intended. However,
diff --git a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
index 90b84f830e76..d8ff57bf0b7a 100644
--- a/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/drawable/VectorDrawable_Delegate.java
@@ -178,6 +178,7 @@ public class VectorDrawable_Delegate {
properties.putInt(VFullPath_Delegate.STROKE_LINE_JOIN_INDEX * 4, path.getStrokeLineJoin());
properties.putFloat(VFullPath_Delegate.STROKE_MITER_LIMIT_INDEX * 4,
path.getStrokeMiterlimit());
+ properties.putInt(VFullPath_Delegate.FILL_TYPE_INDEX * 4, path.getFillType());
return true;
}
@@ -186,7 +187,7 @@ public class VectorDrawable_Delegate {
static void nUpdateFullPathProperties(long pathPtr, float strokeWidth,
int strokeColor, float strokeAlpha, int fillColor, float fillAlpha, float trimPathStart,
float trimPathEnd, float trimPathOffset, float strokeMiterLimit, int strokeLineCap,
- int strokeLineJoin) {
+ int strokeLineJoin, int fillType) {
VFullPath_Delegate path = VNativeObject.getDelegate(pathPtr);
path.setStrokeWidth(strokeWidth);
@@ -200,6 +201,7 @@ public class VectorDrawable_Delegate {
path.setStrokeMiterlimit(strokeMiterLimit);
path.setStrokeLineCap(strokeLineCap);
path.setStrokeLineJoin(strokeLineJoin);
+ path.setFillType(fillType);
}
@LayoutlibDelegate
@@ -530,6 +532,7 @@ public class VectorDrawable_Delegate {
private static final int STROKE_LINE_CAP_INDEX = 8;
private static final int STROKE_LINE_JOIN_INDEX = 9;
private static final int STROKE_MITER_LIMIT_INDEX = 10;
+ private static final int FILL_TYPE_INDEX = 11;
private static final int LINECAP_BUTT = 0;
private static final int LINECAP_ROUND = 1;
@@ -590,6 +593,8 @@ public class VectorDrawable_Delegate {
Join mStrokeLineJoin = MITER;
float mStrokeMiterlimit = 4;
+ int mFillType = 0; // WINDING(0) is the default value. See Path.FillType
+
private VFullPath_Delegate() {
// Empty constructor.
}
@@ -612,6 +617,7 @@ public class VectorDrawable_Delegate {
mStrokeGradient = copy.mStrokeGradient;
mFillGradient = copy.mFillGradient;
+ mFillType = copy.mFillType;
}
private int getStrokeLineCap() {
@@ -755,6 +761,14 @@ public class VectorDrawable_Delegate {
private void setFillGradient(long gradientPtr) {
mFillGradient = gradientPtr;
}
+
+ private void setFillType(int fillType) {
+ mFillType = fillType;
+ }
+
+ private int getFillType() {
+ return mFillType;
+ }
}
static class VGroup_Delegate implements VNativeObject {
@@ -1124,6 +1138,7 @@ public class VectorDrawable_Delegate {
assert fillPaintDelegate != null;
fillPaintDelegate.setColorFilter(filterPtr);
fillPaintDelegate.setShader(fullPath.mFillGradient);
+ Path_Delegate.native_setFillType(mRenderPath.mNativePath, fullPath.mFillType);
Canvas_Delegate.native_drawPath(canvasPtr, mRenderPath.mNativePath, fillPaint
.getNativeInstance());
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
index fe05b0e91e83..53adb41af0cb 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java
@@ -96,7 +96,8 @@ public final class BridgeWindowSession implements IWindowSession {
}
@Override
- public void repositionChild(IWindow childWindow, int x, int y, int width, int height,
+ public void repositionChild(IWindow window, int left, int top, int right, int bottom,
+ int requestedWidth, int requestedHeight,
long deferTransactionUntilFrame, Rect outFrame) {
// pass for now.
return;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
index b98f96f27c91..bd17a2fe6ca2 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/RenderParamsFlags.java
@@ -16,6 +16,7 @@
package com.android.layoutlib.bridge.android;
+import com.android.ide.common.rendering.api.LayoutlibCallback;
import com.android.ide.common.rendering.api.RenderParams;
import com.android.ide.common.rendering.api.SessionParams.Key;
@@ -42,11 +43,16 @@ public final class RenderParamsFlags {
public static final Key<Boolean> FLAG_KEY_RECYCLER_VIEW_SUPPORT =
new Key<Boolean>("recyclerViewSupport", Boolean.class);
/**
- * The application package name. Used via
- * {@link com.android.ide.common.rendering.api.LayoutlibCallback#getFlag(Key)}
+ * The application package name. Used via {@link LayoutlibCallback#getFlag(Key)}
*/
public static final Key<String> FLAG_KEY_APPLICATION_PACKAGE =
new Key<String>("applicationPackage", String.class);
+ /**
+ * To tell LayoutLib that IDE supports providing XML Parser for a file (useful for getting in
+ * memory contents of the file). Used via {@link LayoutlibCallback#getFlag(Key)}
+ */
+ public static final Key<Boolean> FLAG_KEY_XML_FILE_PARSER_SUPPORT =
+ new Key<Boolean>("xmlFileParser", Boolean.class);
// Disallow instances.
private RenderParamsFlags() {}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 494b3d2492f9..a21de56066cb 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -25,6 +25,7 @@ import com.android.internal.util.XmlUtils;
import com.android.layoutlib.bridge.Bridge;
import com.android.layoutlib.bridge.android.BridgeContext;
import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
+import com.android.layoutlib.bridge.android.RenderParamsFlags;
import com.android.ninepatch.NinePatch;
import com.android.ninepatch.NinePatchChunk;
import com.android.resources.Density;
@@ -142,8 +143,13 @@ public final class ResourceHelper {
return null;
}
+ XmlPullParser parser = null;
// first check if the value is a file (xml most likely)
- XmlPullParser parser = context.getLayoutlibCallback().getXmlFileParser(value);
+ Boolean psiParserSupport = context.getLayoutlibCallback().getFlag(
+ RenderParamsFlags.FLAG_KEY_XML_FILE_PARSER_SUPPORT);
+ if (psiParserSupport != null && psiParserSupport) {
+ parser = context.getLayoutlibCallback().getXmlFileParser(value);
+ }
if (parser == null) {
File f = new File(value);
if (f.isFile()) {
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
index 47cb04238e0c..55d6a20949a2 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/golden/vector_drawable.png
Binary files differ
diff --git a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
index 5c19b082904e..32e6e732bb5a 100644
--- a/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
+++ b/tools/layoutlib/bridge/tests/res/testApp/MyApplication/src/main/res/drawable/multi_path.xml
@@ -63,6 +63,25 @@
android:fillColor="@color/gradient"
android:pathData="M-20,-20 l0, 10 l10, 0 l0, -10 l-10,0 "
/>
+
+ <!--
+ Draw squares with different fill types
+ -->
+ <path
+ android:fillType="evenOdd"
+ android:strokeWidth="1"
+ android:strokeColor="#AABBCC"
+ android:fillColor="#AAEFCC"
+ android:pathData="M-20,-40 l0, 10 l10, 0 l0, -10 l-10,0 m5,0 l0, 10 l10, 0 l0, -10 l-10,0"
+ />
+
+ <path
+ android:fillType="nonZero"
+ android:strokeWidth="1"
+ android:strokeColor="#AABBCC"
+ android:fillColor="#AAEFCC"
+ android:pathData="M0,-40 l0, 10 l10, 0 l0, -10 l-10,0 m5,0 l0, 10 l10, 0 l0, -10 l-10,0"
+ />
</group>
</vector> \ No newline at end of file
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
index 48544cac16ab..11d4c81c6dc7 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/AsmAnalyzer.java
@@ -438,7 +438,8 @@ public class AsmAnalyzer {
try {
// exclude classes that are part of the default JRE (the one executing this program)
- if (getClass().getClassLoader().loadClass(className) != null) {
+ if (className.startsWith("java.") ||
+ getClass().getClassLoader().loadClass(className) != null) {
return;
}
} catch (ClassNotFoundException e) {
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index bd376654e60f..f32bb7667c7b 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -256,7 +256,6 @@ public final class CreateInfo implements ICreateInfo {
*/
public final static String[] DELEGATE_CLASS_NATIVES = new String[] {
"android.animation.PropertyValuesHolder",
- "android.graphics.AvoidXfermode",
"android.graphics.Bitmap",
"android.graphics.BitmapFactory",
"android.graphics.BitmapShader",
@@ -284,7 +283,6 @@ public final class CreateInfo implements ICreateInfo {
"android.graphics.PathDashPathEffect",
"android.graphics.PathEffect",
"android.graphics.PathMeasure",
- "android.graphics.PixelXorXfermode",
"android.graphics.PorterDuffColorFilter",
"android.graphics.PorterDuffXfermode",
"android.graphics.RadialGradient",
diff --git a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
index 58e876130e0c..9e15d6009e72 100644
--- a/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
+++ b/wifi/java/android/net/wifi/WifiEnterpriseConfig.java
@@ -1047,7 +1047,7 @@ public class WifiEnterpriseConfig implements Parcelable {
StringBuffer sb = new StringBuffer();
for (String key : mFields.keySet()) {
// Don't display password in toString().
- String value = (key == PASSWORD_KEY) ? "<removed>" : mFields.get(key);
+ String value = PASSWORD_KEY.equals(key) ? "<removed>" : mFields.get(key);
sb.append(key).append(" ").append(value).append("\n");
}
return sb.toString();
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 823fd26c7904..8c1fbc3a6def 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -671,9 +671,7 @@ public class WifiManager {
private AsyncChannel mAsyncChannel;
private CountDownLatch mConnected;
-
- /* TODO(b/27432949): Use a common connectivity thread for this. */
- private HandlerThread mHandlerThread;
+ private Looper mLooper;
/**
* Create a new WifiManager instance.
@@ -685,11 +683,11 @@ public class WifiManager {
* @hide - hide this because it takes in a parameter of type IWifiManager, which
* is a system private class.
*/
- public WifiManager(Context context, IWifiManager service) {
+ public WifiManager(Context context, IWifiManager service, Looper looper) {
mContext = context;
mService = service;
+ mLooper = looper;
mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
- init();
}
/**
@@ -1478,8 +1476,7 @@ public class WifiManager {
* @hide for CTS test only
*/
public void getTxPacketCount(TxPacketCountListener listener) {
- validateChannel();
- mAsyncChannel.sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener));
+ getChannel().sendMessage(RSSI_PKTCNT_FETCH, 0, putListener(listener));
}
/**
@@ -1972,30 +1969,26 @@ public class WifiManager {
}
}
- private void init() {
- Messenger messenger = getWifiServiceMessenger();
- if (messenger == null) {
- mAsyncChannel = null;
- return;
- }
+ private synchronized AsyncChannel getChannel() {
+ if (mAsyncChannel == null) {
+ Messenger messenger = getWifiServiceMessenger();
+ if (messenger == null) {
+ throw new IllegalStateException(
+ "getWifiServiceMessenger() returned null! This is invalid.");
+ }
- mHandlerThread = new HandlerThread("WifiManager");
- mAsyncChannel = new AsyncChannel();
- mConnected = new CountDownLatch(1);
+ mAsyncChannel = new AsyncChannel();
+ mConnected = new CountDownLatch(1);
- mHandlerThread.start();
- Handler handler = new ServiceHandler(mHandlerThread.getLooper());
- mAsyncChannel.connect(mContext, handler, messenger);
- try {
- mConnected.await();
- } catch (InterruptedException e) {
- Log.e(TAG, "interrupted wait at init");
+ Handler handler = new ServiceHandler(mLooper);
+ mAsyncChannel.connect(mContext, handler, messenger);
+ try {
+ mConnected.await();
+ } catch (InterruptedException e) {
+ Log.e(TAG, "interrupted wait at init");
+ }
}
- }
-
- private void validateChannel() {
- if (mAsyncChannel == null) throw new IllegalStateException(
- "No permission to access and change wifi or a bad initialization");
+ return mAsyncChannel;
}
/**
@@ -2016,10 +2009,9 @@ public class WifiManager {
*/
public void connect(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
- validateChannel();
// Use INVALID_NETWORK_ID for arg1 when passing a config object
// arg1 is used to pass network id when the network already exists
- mAsyncChannel.sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
+ getChannel().sendMessage(CONNECT_NETWORK, WifiConfiguration.INVALID_NETWORK_ID,
putListener(listener), config);
}
@@ -2038,8 +2030,7 @@ public class WifiManager {
*/
public void connect(int networkId, ActionListener listener) {
if (networkId < 0) throw new IllegalArgumentException("Network id cannot be negative");
- validateChannel();
- mAsyncChannel.sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
+ getChannel().sendMessage(CONNECT_NETWORK, networkId, putListener(listener));
}
/**
@@ -2062,8 +2053,7 @@ public class WifiManager {
*/
public void save(WifiConfiguration config, ActionListener listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
- validateChannel();
- mAsyncChannel.sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
+ getChannel().sendMessage(SAVE_NETWORK, 0, putListener(listener), config);
}
/**
@@ -2081,8 +2071,7 @@ public class WifiManager {
*/
public void forget(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
- validateChannel();
- mAsyncChannel.sendMessage(FORGET_NETWORK, netId, putListener(listener));
+ getChannel().sendMessage(FORGET_NETWORK, netId, putListener(listener));
}
/**
@@ -2096,8 +2085,7 @@ public class WifiManager {
*/
public void disable(int netId, ActionListener listener) {
if (netId < 0) throw new IllegalArgumentException("Network id cannot be negative");
- validateChannel();
- mAsyncChannel.sendMessage(DISABLE_NETWORK, netId, putListener(listener));
+ getChannel().sendMessage(DISABLE_NETWORK, netId, putListener(listener));
}
/**
@@ -2125,8 +2113,7 @@ public class WifiManager {
*/
public void startWps(WpsInfo config, WpsCallback listener) {
if (config == null) throw new IllegalArgumentException("config cannot be null");
- validateChannel();
- mAsyncChannel.sendMessage(START_WPS, 0, putListener(listener), config);
+ getChannel().sendMessage(START_WPS, 0, putListener(listener), config);
}
/**
@@ -2137,8 +2124,7 @@ public class WifiManager {
* initialized again
*/
public void cancelWps(WpsCallback listener) {
- validateChannel();
- mAsyncChannel.sendMessage(CANCEL_WPS, 0, putListener(listener));
+ getChannel().sendMessage(CANCEL_WPS, 0, putListener(listener));
}
/**
@@ -2153,8 +2139,6 @@ public class WifiManager {
return mService.getWifiServiceMessenger();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
- } catch (SecurityException e) {
- return null;
}
}