summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.mk3
-rw-r--r--api/current.txt70
-rw-r--r--core/java/android/animation/ValueAnimator.java2
-rw-r--r--core/java/android/app/ActivityManager.java7
-rw-r--r--core/java/android/app/ActivityManagerNative.java15
-rw-r--r--core/java/android/app/ActivityThread.java11
-rw-r--r--core/java/android/app/AppOpsManager.java26
-rw-r--r--core/java/android/app/ApplicationPackageManager.java2
-rw-r--r--core/java/android/app/ApplicationThreadNative.java6
-rw-r--r--core/java/android/app/ContextImpl.java36
-rw-r--r--core/java/android/app/IActivityManager.java6
-rw-r--r--core/java/android/app/IApplicationThread.java4
-rw-r--r--core/java/android/app/NotificationManager.java4
-rw-r--r--core/java/android/app/Service.java13
-rw-r--r--core/java/android/content/ClipboardManager.java12
-rw-r--r--core/java/android/content/ContentProvider.java65
-rw-r--r--core/java/android/content/ContentProviderClient.java5
-rw-r--r--core/java/android/content/ContentResolver.java15
-rw-r--r--core/java/android/content/Context.java17
-rw-r--r--core/java/android/content/ContextWrapper.java6
-rw-r--r--core/java/android/content/Intent.java42
-rw-r--r--core/java/android/content/pm/PackageParser.java5
-rw-r--r--core/java/android/content/pm/ServiceInfo.java8
-rw-r--r--core/java/android/database/MatrixCursor.java4
-rw-r--r--core/java/android/hardware/ConsumerIrManager.java153
-rw-r--r--core/java/android/hardware/IConsumerIrService.aidl26
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java4
-rw-r--r--core/java/android/net/ConnectivityManager.java16
-rw-r--r--core/java/android/net/IConnectivityManager.aidl8
-rw-r--r--core/java/android/nfc/cardemulation/ApduServiceInfo.java44
-rw-r--r--core/java/android/nfc/cardemulation/CardEmulationManager.java347
-rw-r--r--core/java/android/nfc/cardemulation/HostApduService.java49
-rw-r--r--core/java/android/os/INetworkManagementService.aidl6
-rw-r--r--core/java/android/os/PowerManager.java2
-rw-r--r--core/java/android/os/SystemVibrator.java2
-rw-r--r--core/java/android/preference/PreferenceActivity.java7
-rw-r--r--core/java/android/preference/TwoStatePreference.java7
-rw-r--r--core/java/android/printservice/PrintService.java6
-rw-r--r--core/java/android/printservice/PrintServiceInfo.java8
-rw-r--r--core/java/android/provider/CallLog.java14
-rw-r--r--core/java/android/provider/DocumentsContract.java24
-rw-r--r--core/java/android/provider/DocumentsProvider.java15
-rw-r--r--core/java/android/provider/Settings.java17
-rw-r--r--core/java/android/speech/RecognizerIntent.java5
-rw-r--r--core/java/android/speech/SpeechRecognizer.java10
-rw-r--r--core/java/android/speech/hotword/HotwordRecognitionListener.java60
-rw-r--r--core/java/android/speech/hotword/HotwordRecognitionService.java255
-rw-r--r--core/java/android/speech/hotword/HotwordRecognizer.java395
-rw-r--r--core/java/android/speech/hotword/IHotwordRecognitionListener.aidl61
-rw-r--r--core/java/android/speech/hotword/IHotwordRecognitionService.aidl47
-rw-r--r--core/java/android/transition/TextChange.java4
-rw-r--r--core/java/android/transition/Transition.java60
-rw-r--r--core/java/android/view/HardwareRenderer.java114
-rw-r--r--core/java/android/view/IApplicationToken.aidl2
-rw-r--r--core/java/android/view/InputDevice.java13
-rw-r--r--core/java/android/view/ScaleGestureDetector.java17
-rw-r--r--core/java/android/view/Surface.java23
-rw-r--r--core/java/android/view/SurfaceControl.java16
-rw-r--r--core/java/android/view/SurfaceView.java94
-rw-r--r--core/java/android/view/View.java15
-rw-r--r--core/java/android/view/ViewDebug.java39
-rw-r--r--core/java/android/view/ViewPropertyAnimator.java35
-rw-r--r--core/java/android/view/ViewRootImpl.java117
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java44
-rw-r--r--core/java/android/view/accessibility/CaptioningManager.java8
-rw-r--r--core/java/android/widget/AbsListView.java16
-rw-r--r--core/java/android/widget/FastScroller.java95
-rw-r--r--core/java/android/widget/ListView.java5
-rw-r--r--core/java/android/widget/Spinner.java24
-rw-r--r--core/java/android/widget/VideoView.java162
-rw-r--r--core/java/com/android/internal/app/ProcessStats.java261
-rw-r--r--core/java/com/android/internal/os/RuntimeInit.java10
-rw-r--r--core/java/com/android/internal/transition/ActionBarTransition.java47
-rw-r--r--core/java/com/android/internal/view/menu/ActionMenuPresenter.java37
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java139
-rw-r--r--core/java/com/android/internal/widget/AutoScrollHelper.java4
-rw-r--r--core/java/com/android/internal/widget/SubtitleView.java4
-rw-r--r--core/jni/AndroidRuntime.cpp2
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp8
-rw-r--r--core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp125
-rw-r--r--core/jni/android/graphics/Graphics.cpp47
-rw-r--r--core/jni/android/graphics/GraphicsJNI.h11
-rw-r--r--core/jni/android/graphics/SurfaceTexture.cpp2
-rw-r--r--core/res/AndroidManifest.xml20
-rw-r--r--core/res/res/drawable-hdpi/activity_picker_bg_activated.9.pngbin326 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/activity_picker_bg_focused.9.pngbin263 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/activity_picker_bg_activated.9.pngbin284 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/activity_picker_bg_focused.9.pngbin242 -> 0 bytes
-rw-r--r--core/res/res/drawable-nodpi/view_accessibility_focused.9.pngbin862 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/activity_picker_bg_activated.9.pngbin413 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/activity_picker_bg_focused.9.pngbin324 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/activity_picker_bg_activated.9.pngbin1343 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/activity_picker_bg_focused.9.pngbin1269 -> 0 bytes
-rw-r--r--core/res/res/drawable/activity_picker_bg.xml30
-rw-r--r--core/res/res/drawable/view_accessibility_focused.xml25
-rw-r--r--core/res/res/layout/action_bar_title_item.xml45
-rw-r--r--core/res/res/layout/resolve_list_item.xml2
-rw-r--r--core/res/res/values-af/strings.xml4
-rw-r--r--core/res/res/values-am/strings.xml18
-rw-r--r--core/res/res/values-ar/strings.xml2
-rw-r--r--core/res/res/values-az-rAZ/strings.xml2
-rw-r--r--core/res/res/values-be/strings.xml4
-rw-r--r--core/res/res/values-bg/strings.xml4
-rw-r--r--core/res/res/values-ca/strings.xml18
-rw-r--r--core/res/res/values-cs/strings.xml4
-rw-r--r--core/res/res/values-da/strings.xml4
-rw-r--r--core/res/res/values-de/strings.xml4
-rw-r--r--core/res/res/values-el/strings.xml4
-rw-r--r--core/res/res/values-en-rGB/strings.xml4
-rw-r--r--core/res/res/values-en-rIN/strings.xml4
-rw-r--r--core/res/res/values-es-rUS/strings.xml6
-rw-r--r--core/res/res/values-es/strings.xml8
-rw-r--r--core/res/res/values-et-rEE/strings.xml4
-rw-r--r--core/res/res/values-fa/strings.xml4
-rw-r--r--core/res/res/values-fi/strings.xml4
-rw-r--r--core/res/res/values-fr-rCA/strings.xml8
-rw-r--r--core/res/res/values-fr/strings.xml8
-rw-r--r--core/res/res/values-hi/strings.xml56
-rw-r--r--core/res/res/values-hr/strings.xml4
-rw-r--r--core/res/res/values-hu/strings.xml4
-rw-r--r--core/res/res/values-hy-rAM/strings.xml4
-rw-r--r--core/res/res/values-in/strings.xml4
-rw-r--r--core/res/res/values-it/strings.xml4
-rw-r--r--core/res/res/values-iw/strings.xml2
-rw-r--r--core/res/res/values-ja/strings.xml4
-rw-r--r--core/res/res/values-ka-rGE/strings.xml6
-rw-r--r--core/res/res/values-km-rKH/strings.xml2
-rw-r--r--core/res/res/values-ko/strings.xml4
-rw-r--r--core/res/res/values-lo-rLA/strings.xml4
-rw-r--r--core/res/res/values-lt/strings.xml4
-rw-r--r--core/res/res/values-lv/strings.xml4
-rw-r--r--core/res/res/values-mn-rMN/strings.xml2
-rw-r--r--core/res/res/values-ms-rMY/strings.xml8
-rw-r--r--core/res/res/values-nb/strings.xml4
-rw-r--r--core/res/res/values-ne-rNP/strings.xml12
-rw-r--r--core/res/res/values-nl/strings.xml4
-rw-r--r--core/res/res/values-pl/strings.xml4
-rw-r--r--core/res/res/values-pt-rPT/strings.xml4
-rw-r--r--core/res/res/values-pt/strings.xml4
-rw-r--r--core/res/res/values-rm/strings.xml4
-rw-r--r--core/res/res/values-ro/strings.xml4
-rw-r--r--core/res/res/values-ru/strings.xml4
-rw-r--r--core/res/res/values-si-rLK/strings.xml6
-rw-r--r--core/res/res/values-sk/strings.xml8
-rw-r--r--core/res/res/values-sl/strings.xml4
-rw-r--r--core/res/res/values-sr/strings.xml4
-rw-r--r--core/res/res/values-sv/strings.xml4
-rw-r--r--core/res/res/values-sw/strings.xml4
-rw-r--r--core/res/res/values-th/strings.xml4
-rw-r--r--core/res/res/values-tl/strings.xml4
-rw-r--r--core/res/res/values-tr/strings.xml4
-rw-r--r--core/res/res/values-uk/strings.xml8
-rw-r--r--core/res/res/values-vi/strings.xml4
-rw-r--r--core/res/res/values-zh-rCN/strings.xml4
-rw-r--r--core/res/res/values-zh-rHK/strings.xml4
-rw-r--r--core/res/res/values-zh-rTW/strings.xml4
-rw-r--r--core/res/res/values-zu/strings.xml2
-rw-r--r--core/res/res/values/attrs.xml4
-rw-r--r--core/res/res/values/attrs_manifest.xml3
-rw-r--r--core/res/res/values/colors.xml2
-rw-r--r--core/res/res/values/public.xml2
-rw-r--r--core/res/res/values/strings.xml15
-rw-r--r--core/tests/ConnectivityManagerTest/AndroidManifest.xml3
-rw-r--r--core/tests/coretests/src/android/database/MatrixCursorTest.java16
-rw-r--r--data/fonts/fallback_fonts.xml6
-rw-r--r--docs/html/guide/topics/ui/how-android-draws.jd115
-rw-r--r--docs/html/training/id-auth/authenticate.jd2
-rw-r--r--graphics/java/android/graphics/BitmapFactory.java57
-rw-r--r--graphics/java/android/graphics/PixelFormat.java19
-rw-r--r--graphics/java/android/graphics/SurfaceTexture.java21
-rw-r--r--graphics/java/android/renderscript/Allocation.java5
-rw-r--r--graphics/jni/android_renderscript_RenderScript.cpp2
-rw-r--r--libs/androidfw/ZipFileRO.cpp194
-rw-r--r--libs/hwui/FontRenderer.cpp2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp6
-rw-r--r--location/java/android/location/LocationManager.java18
-rw-r--r--media/java/android/media/AudioManager.java26
-rw-r--r--media/java/android/media/AudioTrack.java27
-rw-r--r--media/java/android/media/MediaFormat.java22
-rw-r--r--media/java/android/media/MediaMuxer.java36
-rw-r--r--media/java/android/media/MediaPlayer.java26
-rw-r--r--media/java/android/media/SubtitleController.java26
-rw-r--r--media/java/android/media/SubtitleTrack.java77
-rw-r--r--media/java/android/media/WebVttRenderer.java810
-rw-r--r--media/jni/android_media_ImageReader.cpp21
-rw-r--r--media/jni/android_media_MediaMuxer.cpp15
-rw-r--r--packages/DocumentsUI/res/drawable/item_background.xml24
-rw-r--r--packages/DocumentsUI/res/layout/fragment_directory.xml12
-rw-r--r--packages/DocumentsUI/res/layout/item_doc_grid.xml32
-rw-r--r--packages/DocumentsUI/res/layout/item_doc_list.xml32
-rw-r--r--packages/DocumentsUI/res/layout/item_loading_grid.xml34
-rw-r--r--packages/DocumentsUI/res/layout/item_loading_list.xml (renamed from packages/DocumentsUI/res/layout/item_loading.xml)0
-rw-r--r--packages/DocumentsUI/res/layout/item_message_grid.xml62
-rw-r--r--packages/DocumentsUI/res/layout/item_message_list.xml8
-rw-r--r--packages/DocumentsUI/res/layout/item_root.xml8
-rw-r--r--packages/DocumentsUI/res/layout/item_root_header.xml14
-rw-r--r--packages/DocumentsUI/res/layout/item_title.xml4
-rw-r--r--packages/DocumentsUI/res/menu/mode_directory.xml4
-rw-r--r--packages/DocumentsUI/res/values-ro/strings.xml2
-rw-r--r--packages/DocumentsUI/res/values-ru/strings.xml2
-rw-r--r--packages/DocumentsUI/res/values-sr/strings.xml2
-rw-r--r--packages/DocumentsUI/res/values-zh-rCN/strings.xml2
-rw-r--r--packages/DocumentsUI/res/values/strings.xml37
-rw-r--r--packages/DocumentsUI/res/values/styles.xml29
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java2
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java393
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java101
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java208
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java8
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java126
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java12
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java30
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java44
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java174
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsCache.java23
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java3
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java117
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java28
-rw-r--r--packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java131
-rw-r--r--packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java2
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java35
-rw-r--r--packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java29
-rw-r--r--packages/Keyguard/AndroidManifest.xml2
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java174
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java4
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java53
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.pngbin1283 -> 1061 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.pngbin1460 -> 1085 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.pngbin1471 -> 1055 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.pngbin1695 -> 960 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_signal_in.pngbin0 -> 492 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_signal_inout.pngbin0 -> 615 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_signal_out.pngbin0 -> 471 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.pngbin2309 -> 2045 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.pngbin2454 -> 2157 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.pngbin2607 -> 2212 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.pngbin2621 -> 1956 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_in.pngbin0 -> 492 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_inout.pngbin0 -> 615 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.pngbin0 -> 471 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.pngbin600 -> 590 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.pngbin1168 -> 1167 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.pngbin1180 -> 1178 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.pngbin1188 -> 1186 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.pngbin1207 -> 1203 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.pngbin1578 -> 1575 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.pngbin1584 -> 1579 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.pngbin1617 -> 1596 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.pngbin1603 -> 1605 bytes
-rw-r--r--packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.pngbin397 -> 409 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_in.pngbin0 -> 571 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_inout.pngbin0 -> 719 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_out.pngbin0 -> 538 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_1.pngbin2966 -> 2973 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_2.pngbin2982 -> 2987 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_3.pngbin3000 -> 2998 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_4.pngbin2997 -> 3015 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_in.pngbin0 -> 503 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_inout.pngbin0 -> 552 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_out.pngbin0 -> 501 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_1.pngbin2923 -> 2923 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_2.pngbin2933 -> 2935 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_3.pngbin2948 -> 2946 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_4.pngbin2951 -> 2958 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_in.pngbin0 -> 689 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_inout.pngbin0 -> 835 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_out.pngbin0 -> 675 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_1.pngbin3017 -> 3021 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_2.pngbin3033 -> 3034 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_3.pngbin3047 -> 3048 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_4.pngbin3062 -> 3061 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_in.pngbin0 -> 1372 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_inout.pngbin0 -> 1474 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_out.pngbin0 -> 1361 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_1.pngbin3136 -> 3143 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_2.pngbin3168 -> 3165 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_3.pngbin3181 -> 3178 bytes
-rw-r--r--packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_4.pngbin3192 -> 3182 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.pngbin980 -> 882 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.pngbin1077 -> 891 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.pngbin1092 -> 895 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.pngbin1125 -> 798 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_signal_in.pngbin0 -> 425 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_signal_inout.pngbin0 -> 486 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_signal_out.pngbin0 -> 424 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.pngbin1429 -> 1351 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.pngbin1498 -> 1451 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.pngbin1623 -> 1515 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.pngbin1501 -> 1267 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_in.pngbin0 -> 425 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_inout.pngbin0 -> 486 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.pngbin0 -> 424 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.pngbin526 -> 528 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.pngbin1111 -> 1110 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.pngbin1118 -> 1116 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.pngbin1122 -> 1121 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.pngbin1144 -> 1138 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.pngbin1356 -> 1358 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.pngbin1382 -> 1379 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.pngbin1418 -> 1424 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.pngbin1390 -> 1382 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.pngbin299 -> 359 bytes
-rw-r--r--packages/SystemUI/res/drawable-nodpi/lightning.pngbin2896 -> 0 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.pngbin1763 -> 1302 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.pngbin1890 -> 1304 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.pngbin2054 -> 1279 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.pngbin2121 -> 1222 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_in.pngbin0 -> 550 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_inout.pngbin0 -> 721 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_out.pngbin0 -> 539 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.pngbin3400 -> 2806 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.pngbin3518 -> 2912 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.pngbin3761 -> 3043 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.pngbin3777 -> 2679 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_in.pngbin0 -> 550 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_inout.pngbin0 -> 721 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.pngbin0 -> 539 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.pngbin722 -> 715 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.pngbin1232 -> 1213 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.pngbin1229 -> 1230 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.pngbin1250 -> 1238 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.pngbin1256 -> 1250 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.pngbin1755 -> 1747 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.pngbin1791 -> 1773 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.pngbin1823 -> 1835 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.pngbin1853 -> 1853 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.pngbin461 -> 523 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_1.pngbin2147 -> 1685 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_2.pngbin2228 -> 1704 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_3.pngbin2339 -> 1707 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_4.pngbin2423 -> 1634 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_in.pngbin0 -> 1212 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_inout.pngbin0 -> 1339 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_out.pngbin0 -> 1186 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_1.pngbin3462 -> 3434 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_2.pngbin3634 -> 3382 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_3.pngbin3737 -> 3386 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_4.pngbin3952 -> 3348 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_in.pngbin0 -> 1212 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_inout.pngbin0 -> 1339 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_out.pngbin0 -> 1186 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.pngbin1275 -> 1268 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.pngbin1367 -> 1387 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.pngbin1377 -> 1371 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.pngbin1382 -> 1380 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.pngbin1395 -> 1405 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_1.pngbin2183 -> 2172 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_2.pngbin2230 -> 2214 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_3.pngbin2307 -> 2276 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_4.pngbin2365 -> 2343 bytes
-rw-r--r--packages/SystemUI/res/layout/quick_settings_tile_rssi.xml31
-rw-r--r--packages/SystemUI/res/layout/quick_settings_tile_wifi.xml57
-rw-r--r--packages/SystemUI/res/values/arrays.xml15
-rwxr-xr-xpackages/SystemUI/src/com/android/systemui/BatteryMeterView.java113
-rw-r--r--packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java30
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java16
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java35
-rw-r--r--packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java16
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java4
-rw-r--r--preloaded-classes33
-rw-r--r--services/input/InputDispatcher.cpp4
-rw-r--r--services/input/InputDispatcher.h4
-rw-r--r--services/input/tests/InputDispatcher_test.cpp3
-rw-r--r--services/java/com/android/server/ConnectivityService.java25
-rw-r--r--services/java/com/android/server/ConsumerIrService.java130
-rw-r--r--services/java/com/android/server/LocationManagerService.java4
-rw-r--r--services/java/com/android/server/NetworkManagementService.java79
-rw-r--r--services/java/com/android/server/SystemServer.java5
-rw-r--r--services/java/com/android/server/am/ActivityManagerService.java165
-rw-r--r--services/java/com/android/server/am/ActivityRecord.java8
-rw-r--r--services/java/com/android/server/am/ActivityStack.java14
-rw-r--r--services/java/com/android/server/am/ProcessRecord.java77
-rw-r--r--services/java/com/android/server/am/ProcessStatsService.java6
-rw-r--r--services/java/com/android/server/am/ServiceRecord.java1
-rw-r--r--services/java/com/android/server/connectivity/Tethering.java13
-rw-r--r--services/java/com/android/server/input/InputManagerService.java7
-rw-r--r--services/java/com/android/server/location/FlpHardwareProvider.java8
-rw-r--r--services/java/com/android/server/net/NetworkStatsRecorder.java9
-rw-r--r--services/java/com/android/server/net/NetworkStatsService.java5
-rw-r--r--services/java/com/android/server/pm/Settings.java5
-rw-r--r--services/java/com/android/server/power/ElectronBeam.java7
-rw-r--r--services/java/com/android/server/power/WirelessChargerDetector.java18
-rw-r--r--services/java/com/android/server/print/PrintManagerService.java23
-rw-r--r--services/java/com/android/server/print/RemotePrintService.java14
-rw-r--r--services/java/com/android/server/print/RemotePrintSpooler.java25
-rw-r--r--services/java/com/android/server/print/UserState.java102
-rw-r--r--services/java/com/android/server/wm/BlackFrame.java5
-rw-r--r--services/java/com/android/server/wm/DisplayMagnifier.java6
-rw-r--r--services/java/com/android/server/wm/FocusedStackFrame.java9
-rw-r--r--services/java/com/android/server/wm/InputMonitor.java17
-rw-r--r--services/java/com/android/server/wm/ScreenRotationAnimation.java11
-rw-r--r--services/java/com/android/server/wm/StrictModeFlash.java3
-rw-r--r--services/java/com/android/server/wm/Watermark.java8
-rw-r--r--services/java/com/android/server/wm/WindowManagerService.java22
-rw-r--r--services/java/com/android/server/wm/WindowStateAnimator.java5
-rw-r--r--services/jni/Android.mk1
-rw-r--r--services/jni/com_android_server_ConsumerIrService.cpp114
-rw-r--r--services/jni/com_android_server_input_InputManagerService.cpp12
-rw-r--r--services/jni/com_android_server_location_FlpHardwareProvider.cpp2
-rw-r--r--services/jni/onload.cpp3
-rw-r--r--services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java8
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java2
-rw-r--r--test-runner/src/android/test/mock/MockContext.java6
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java11
-rw-r--r--tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java91
-rw-r--r--tools/layoutlib/bridge/src/android/webkit/WebView.java16
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java6
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java4
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java3
-rw-r--r--wifi/java/android/net/wifi/WifiStateMachine.java6
-rw-r--r--wifi/java/android/net/wifi/p2p/WifiP2pService.java14
414 files changed, 5687 insertions, 3485 deletions
diff --git a/Android.mk b/Android.mk
index 30b17f5ac2c8..dea3d4859796 100644
--- a/Android.mk
+++ b/Android.mk
@@ -120,6 +120,7 @@ LOCAL_SRC_FILES += \
core/java/android/hardware/ICameraServiceListener.aidl \
core/java/android/hardware/ICamera.aidl \
core/java/android/hardware/ICameraClient.aidl \
+ core/java/android/hardware/IConsumerIrService.aidl \
core/java/android/hardware/IProCameraUser.aidl \
core/java/android/hardware/IProCameraCallbacks.aidl \
core/java/android/hardware/camera2/ICameraDeviceUser.aidl \
@@ -195,8 +196,6 @@ LOCAL_SRC_FILES += \
core/java/android/view/IWindowSession.aidl \
core/java/android/speech/IRecognitionListener.aidl \
core/java/android/speech/IRecognitionService.aidl \
- core/java/android/speech/hotword/IHotwordRecognitionListener.aidl \
- core/java/android/speech/hotword/IHotwordRecognitionService.aidl \
core/java/android/speech/tts/ITextToSpeechCallback.aidl \
core/java/android/speech/tts/ITextToSpeechService.aidl \
core/java/com/android/internal/app/IAppOpsCallback.aidl \
diff --git a/api/current.txt b/api/current.txt
index c7b3ed990b67..b5930ec056d0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -20,6 +20,7 @@ package android {
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
+ field public static final java.lang.String BIND_CALL_SERVICE = "android.permission.BIND_CALL_SERVICE";
field public static final java.lang.String BIND_DEVICE_ADMIN = "android.permission.BIND_DEVICE_ADMIN";
field public static final java.lang.String BIND_INPUT_METHOD = "android.permission.BIND_INPUT_METHOD";
field public static final java.lang.String BIND_NFC_SERVICE = "android.permission.BIND_NFC_SERVICE";
@@ -129,6 +130,7 @@ package android {
field public static final java.lang.String SUBSCRIBED_FEEDS_READ = "android.permission.SUBSCRIBED_FEEDS_READ";
field public static final java.lang.String SUBSCRIBED_FEEDS_WRITE = "android.permission.SUBSCRIBED_FEEDS_WRITE";
field public static final java.lang.String SYSTEM_ALERT_WINDOW = "android.permission.SYSTEM_ALERT_WINDOW";
+ field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS";
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
@@ -289,14 +291,14 @@ package android {
field public static final deprecated int animationResolution = 16843546; // 0x101031a
field public static final int antialias = 16843034; // 0x101011a
field public static final int anyDensity = 16843372; // 0x101026c
- field public static final int apduServiceBanner = 16843758; // 0x10103ee
+ field public static final int apduServiceBanner = 16843757; // 0x10103ed
field public static final int apiKey = 16843281; // 0x1010211
field public static final int author = 16843444; // 0x10102b4
field public static final int authorities = 16842776; // 0x1010018
field public static final int autoAdvanceViewId = 16843535; // 0x101030f
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
field public static final int autoLink = 16842928; // 0x10100b0
- field public static final int autoMirrored = 16843755; // 0x10103eb
+ field public static final int autoMirrored = 16843754; // 0x10103ea
field public static final int autoStart = 16843445; // 0x10102b5
field public static final deprecated int autoText = 16843114; // 0x101016a
field public static final int autoUrlDetect = 16843404; // 0x101028c
@@ -393,7 +395,6 @@ package android {
field public static final int cropToPadding = 16843043; // 0x1010123
field public static final int cursorVisible = 16843090; // 0x1010152
field public static final int customNavigationLayout = 16843474; // 0x10102d2
- field public static final int customRoots = 16843754; // 0x10103ea
field public static final int customTokens = 16843579; // 0x101033b
field public static final int cycles = 16843220; // 0x10101d4
field public static final int dashGap = 16843175; // 0x10101a7
@@ -846,7 +847,6 @@ package android {
field public static final int prompt = 16843131; // 0x101017b
field public static final int propertyName = 16843489; // 0x10102e1
field public static final int protectionLevel = 16842761; // 0x1010009
- field public static final int provideAssistData = 16843759; // 0x10103ef
field public static final int publicKey = 16843686; // 0x10103a6
field public static final int queryActionMsg = 16843227; // 0x10101db
field public static final int queryAfterZeroResults = 16843394; // 0x1010282
@@ -871,7 +871,7 @@ package android {
field public static final int reqKeyboardType = 16843304; // 0x1010228
field public static final int reqNavigation = 16843306; // 0x101022a
field public static final int reqTouchScreen = 16843303; // 0x1010227
- field public static final int requireDeviceUnlock = 16843757; // 0x10103ed
+ field public static final int requireDeviceUnlock = 16843756; // 0x10103ec
field public static final int required = 16843406; // 0x101028e
field public static final int requiredAccountType = 16843734; // 0x10103d6
field public static final int requiredForAllUsers = 16843728; // 0x10103d0
@@ -1020,7 +1020,7 @@ package android {
field public static final int summaryOff = 16843248; // 0x10101f0
field public static final int summaryOn = 16843247; // 0x10101ef
field public static final int supportsRtl = 16843695; // 0x10103af
- field public static final int supportsSwitchingToNextInputMethod = 16843756; // 0x10103ec
+ field public static final int supportsSwitchingToNextInputMethod = 16843755; // 0x10103eb
field public static final int supportsUploading = 16843419; // 0x101029b
field public static final int switchMinWidth = 16843632; // 0x1010370
field public static final int switchPadding = 16843633; // 0x1010371
@@ -4247,7 +4247,6 @@ package android.app {
method public void onCreate();
method public void onDestroy();
method public void onLowMemory();
- method public void onProvideAssistData(android.os.Bundle);
method public void onRebind(android.content.Intent);
method public deprecated void onStart(android.content.Intent, int);
method public int onStartCommand(android.content.Intent, int, int);
@@ -5971,6 +5970,7 @@ package android.content {
field public static final java.lang.String CAPTIONING_SERVICE = "captioning";
field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard";
field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity";
+ field public static final java.lang.String CONSUMER_IR_SERVICE = "consumer_ir";
field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2
field public static final int CONTEXT_INCLUDE_CODE = 1; // 0x1
field public static final int CONTEXT_RESTRICTED = 4; // 0x4
@@ -6407,7 +6407,6 @@ package android.content {
field public static final java.lang.String ACTION_USER_INITIALIZE = "android.intent.action.USER_INITIALIZE";
field public static final java.lang.String ACTION_USER_PRESENT = "android.intent.action.USER_PRESENT";
field public static final java.lang.String ACTION_VIEW = "android.intent.action.VIEW";
- field public static final java.lang.String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
field public static final java.lang.String ACTION_VOICE_COMMAND = "android.intent.action.VOICE_COMMAND";
field public static final deprecated java.lang.String ACTION_WALLPAPER_CHANGED = "android.intent.action.WALLPAPER_CHANGED";
field public static final java.lang.String ACTION_WEB_SEARCH = "android.intent.action.WEB_SEARCH";
@@ -6449,8 +6448,6 @@ package android.content {
field public static final deprecated java.lang.String EXTRA_ALLOW_REPLACE = "android.intent.extra.ALLOW_REPLACE";
field public static final java.lang.String EXTRA_ASSIST_CONTEXT = "android.intent.extra.ASSIST_CONTEXT";
field public static final java.lang.String EXTRA_ASSIST_PACKAGE = "android.intent.extra.ASSIST_PACKAGE";
- field public static final java.lang.String EXTRA_ASSIST_SERVICES_CONTEXTS = "android.intent.extra.ASSIST_SERVICES_CONTEXTS";
- field public static final java.lang.String EXTRA_ASSIST_SERVICES_PACKAGES = "android.intent.extra.ASSIST_SERVICES_PACKAGES";
field public static final java.lang.String EXTRA_BCC = "android.intent.extra.BCC";
field public static final java.lang.String EXTRA_BUG_REPORT = "android.intent.extra.BUG_REPORT";
field public static final java.lang.String EXTRA_CC = "android.intent.extra.CC";
@@ -7450,7 +7447,6 @@ package android.content.pm {
method public void dump(android.util.Printer, java.lang.String);
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int FLAG_ISOLATED_PROCESS = 2; // 0x2
- field public static final int FLAG_PROVIDE_ASSIST_DATA = 4; // 0x4
field public static final int FLAG_SINGLE_USER = 1073741824; // 0x40000000
field public static final int FLAG_STOP_WITH_TASK = 1; // 0x1
field public int flags;
@@ -8140,7 +8136,7 @@ package android.database {
public class MatrixCursor.RowBuilder {
method public android.database.MatrixCursor.RowBuilder add(java.lang.Object);
- method public android.database.MatrixCursor.RowBuilder offer(java.lang.String, java.lang.Object);
+ method public android.database.MatrixCursor.RowBuilder add(java.lang.String, java.lang.Object);
}
public class MergeCursor extends android.database.AbstractCursor {
@@ -9926,7 +9922,7 @@ package android.graphics {
method public abstract void onFrameAvailable(android.graphics.SurfaceTexture);
}
- public static class SurfaceTexture.OutOfResourcesException extends java.lang.Exception {
+ public static deprecated class SurfaceTexture.OutOfResourcesException extends java.lang.Exception {
ctor public SurfaceTexture.OutOfResourcesException();
ctor public SurfaceTexture.OutOfResourcesException(java.lang.String);
}
@@ -10629,6 +10625,18 @@ package android.hardware {
field public int width;
}
+ public final class ConsumerIrManager {
+ method public android.hardware.ConsumerIrManager.CarrierFrequencyRange[] getCarrierFrequencies();
+ method public boolean hasIrEmitter();
+ method public void transmit(int, int[]);
+ }
+
+ public final class ConsumerIrManager.CarrierFrequencyRange {
+ ctor public ConsumerIrManager.CarrierFrequencyRange(int, int);
+ method public int getMaxFrequency();
+ method public int getMinFrequency();
+ }
+
public abstract interface FlushCompleteListener {
method public abstract void onFlushCompleted(android.hardware.Sensor);
}
@@ -12173,7 +12181,7 @@ package android.media {
method public int getSampleRate();
method public int getState();
method public int getStreamType();
- method public android.media.AudioTimestamp getTimestamp(android.media.AudioTimestamp);
+ method public boolean getTimestamp(android.media.AudioTimestamp);
method public void pause() throws java.lang.IllegalStateException;
method public void play() throws java.lang.IllegalStateException;
method public void release();
@@ -12791,6 +12799,7 @@ package android.media {
ctor public MediaMuxer(java.lang.String, int) throws java.io.IOException;
method public int addTrack(android.media.MediaFormat);
method public void release();
+ method public void setLocation(float, float);
method public void setOrientationHint(int);
method public void start();
method public void stop();
@@ -15267,7 +15276,7 @@ package android.nfc.cardemulation {
method public final void notifyUnhandled();
method public final android.os.IBinder onBind(android.content.Intent);
method public abstract void onDeactivated(int);
- method public byte[] processCommandApdu(byte[], android.os.Bundle);
+ method public abstract byte[] processCommandApdu(byte[], android.os.Bundle);
method public final void sendResponseApdu(byte[]);
field public static final int DEACTIVATION_DESELECTED = 1; // 0x1
field public static final int DEACTIVATION_LINK_LOSS = 0; // 0x0
@@ -20774,7 +20783,6 @@ package android.provider {
method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String);
method public static android.net.Uri buildRootsUri(java.lang.String);
method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String);
- method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
method public static java.lang.String getDocumentId(android.net.Uri);
method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
@@ -20796,6 +20804,7 @@ package android.provider {
field public static final java.lang.String COLUMN_SIZE = "_size";
field public static final java.lang.String COLUMN_SUMMARY = "summary";
field public static final int FLAG_DIR_PREFERS_GRID = 32; // 0x20
+ field public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 64; // 0x40
field public static final int FLAG_DIR_SUPPORTS_CREATE = 8; // 0x8
field public static final int FLAG_DIR_SUPPORTS_SEARCH = 16; // 0x10
field public static final int FLAG_SUPPORTS_DELETE = 4; // 0x4
@@ -22811,26 +22820,6 @@ package android.speech {
}
-package android.speech.hotword {
-
- public abstract class HotwordRecognitionService extends android.app.Service {
- ctor public HotwordRecognitionService();
- method public android.os.IBinder onBind(android.content.Intent);
- method public abstract void onStartHotwordRecognition(android.speech.hotword.HotwordRecognitionService.Callback);
- method public abstract void onStopHotwordRecognition();
- field public static final java.lang.String SERVICE_INTERFACE = "android.speech.hotword.HotwordRecognitionService";
- }
-
- public static class HotwordRecognitionService.Callback {
- method public void onError(int) throws android.os.RemoteException;
- method public void onHotwordEvent(int, android.os.Bundle) throws android.os.RemoteException;
- method public void onHotwordRecognitionStarted() throws android.os.RemoteException;
- method public void onHotwordRecognitionStopped() throws android.os.RemoteException;
- method public void onHotwordRecognized(android.content.Intent) throws android.os.RemoteException;
- }
-
-}
-
package android.speech.tts {
public abstract interface SynthesisCallback {
@@ -27301,7 +27290,7 @@ package android.view {
field public static final int ROTATION_90 = 1; // 0x1
}
- public static class Surface.OutOfResourcesException extends java.lang.Exception {
+ public static class Surface.OutOfResourcesException extends java.lang.RuntimeException {
ctor public Surface.OutOfResourcesException();
ctor public Surface.OutOfResourcesException(java.lang.String);
}
@@ -28371,6 +28360,7 @@ package android.view {
method public android.view.ViewPropertyAnimator setInterpolator(android.animation.TimeInterpolator);
method public android.view.ViewPropertyAnimator setListener(android.animation.Animator.AnimatorListener);
method public android.view.ViewPropertyAnimator setStartDelay(long);
+ method public android.view.ViewPropertyAnimator setUpdateListener(android.animation.ValueAnimator.AnimatorUpdateListener);
method public void start();
method public android.view.ViewPropertyAnimator translationX(float);
method public android.view.ViewPropertyAnimator translationXBy(float);
@@ -29052,12 +29042,12 @@ package android.view.accessibility {
}
public class CaptioningManager {
- method public void addCaptioningStateChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
+ method public void addCaptioningChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
method public final float getFontScale();
method public final java.util.Locale getLocale();
method public android.view.accessibility.CaptioningManager.CaptionStyle getUserStyle();
method public final boolean isEnabled();
- method public void removeCaptioningStateChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
+ method public void removeCaptioningChangeListener(android.view.accessibility.CaptioningManager.CaptioningChangeListener);
}
public static final class CaptioningManager.CaptionStyle {
@@ -29071,7 +29061,7 @@ package android.view.accessibility {
field public final int foregroundColor;
}
- public abstract class CaptioningManager.CaptioningChangeListener {
+ public static abstract class CaptioningManager.CaptioningChangeListener {
ctor public CaptioningManager.CaptioningChangeListener();
method public void onEnabledChanged(boolean);
method public void onFontScaleChanged(float);
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 63942996c3e9..86da67383a27 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -1027,6 +1027,8 @@ public class ValueAnimator extends Animator {
long currentPlayTime = currentTime - mStartTime;
long timeLeft = mDuration - currentPlayTime;
mStartTime = currentTime - timeLeft;
+ } else if (mStarted) {
+ end();
} else {
start(true);
}
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index 7c40bb15ac18..2d28280fe71b 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2106,7 +2106,12 @@ public class ActivityManager {
}
// If the target is not exported, then nobody else can get to it.
if (!exported) {
- Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid);
+ /*
+ RuntimeException here = new RuntimeException("here");
+ here.fillInStackTrace();
+ Slog.w(TAG, "Permission denied: checkComponentPermission() owningUid=" + owningUid,
+ here);
+ */
return PackageManager.PERMISSION_DENIED;
}
if (permission == null) {
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 6d7211486fef..370db3117663 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -1917,7 +1917,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
int pid = data.readInt();
boolean aboveSystem = data.readInt() != 0;
- long res = inputDispatchingTimedOut(pid, aboveSystem);
+ String reason = data.readString();
+ long res = inputDispatchingTimedOut(pid, aboveSystem, reason);
reply.writeNoException();
reply.writeLong(res);
return true;
@@ -1936,8 +1937,7 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
Bundle extras = data.readBundle();
- int index = data.readInt();
- reportAssistContextExtras(token, extras, index);
+ reportAssistContextExtras(token, extras);
reply.writeNoException();
return true;
}
@@ -3377,7 +3377,7 @@ class ActivityManagerProxy implements IActivityManager
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeString(packageName);
- data.writeStrongBinder(observer.asBinder());
+ data.writeStrongBinder((observer != null) ? observer.asBinder() : null);
data.writeInt(userId);
mRemote.transact(CLEAR_APP_DATA_TRANSACTION, data, reply, 0);
reply.readException();
@@ -4462,12 +4462,14 @@ class ActivityManagerProxy implements IActivityManager
reply.recycle();
}
- public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException {
+ public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason)
+ throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeInt(pid);
data.writeInt(aboveSystem ? 1 : 0);
+ data.writeString(reason);
mRemote.transact(INPUT_DISPATCHING_TIMED_OUT_TRANSACTION, data, reply, 0);
reply.readException();
long res = reply.readInt();
@@ -4489,14 +4491,13 @@ class ActivityManagerProxy implements IActivityManager
return res;
}
- public void reportAssistContextExtras(IBinder token, Bundle extras, int index)
+ public void reportAssistContextExtras(IBinder token, Bundle extras)
throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
data.writeBundle(extras);
- data.writeInt(index);
mRemote.transact(REPORT_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 018fbe01decb..209514aebdc8 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -528,7 +528,6 @@ public final class ActivityThread {
IBinder activityToken;
IBinder requestToken;
int requestType;
- int index;
}
private native void dumpGraphicsInfo(FileDescriptor fd);
@@ -1194,12 +1193,11 @@ public final class ActivityThread {
@Override
public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
- int requestType, int index) {
+ int requestType) {
RequestAssistContextExtras cmd = new RequestAssistContextExtras();
cmd.activityToken = activityToken;
cmd.requestToken = requestToken;
cmd.requestType = requestType;
- cmd.index = index;
queueOrSendMessage(H.REQUEST_ASSIST_CONTEXT_EXTRAS, cmd);
}
@@ -2278,18 +2276,13 @@ public final class ActivityThread {
if (r != null) {
r.activity.getApplication().dispatchOnProvideAssistData(r.activity, data);
r.activity.onProvideAssistData(data);
- } else {
- Service service = mServices.get(cmd.activityToken);
- if (service != null) {
- service.onProvideAssistData(data);
- }
}
if (data.isEmpty()) {
data = null;
}
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
- mgr.reportAssistContextExtras(cmd.requestToken, data, cmd.index);
+ mgr.reportAssistContextExtras(cmd.requestToken, data);
} catch (RemoteException e) {
}
}
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index 19a028d39ae7..3e4795c08957 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -185,11 +185,11 @@ public class AppOpsManager {
OP_CALL_PHONE,
OP_READ_SMS,
OP_WRITE_SMS,
- OP_READ_SMS,
- OP_READ_SMS,
- OP_READ_SMS,
- OP_READ_SMS,
- OP_WRITE_SMS,
+ OP_RECEIVE_SMS,
+ OP_RECEIVE_SMS,
+ OP_RECEIVE_SMS,
+ OP_RECEIVE_SMS,
+ OP_SEND_SMS,
OP_READ_SMS,
OP_WRITE_SMS,
OP_WRITE_SETTINGS,
@@ -575,6 +575,10 @@ public class AppOpsManager {
}
}
+ private String buildSecurityExceptionMsg(int op, int uid, String packageName) {
+ return packageName + " from uid " + uid + " not allowed to perform " + sOpNames[op];
+ }
+
/**
* Do a quick check for whether an application might be able to perform an operation.
* This is <em>not</em> a security check; you must use {@link #noteOp(int, int, String)}
@@ -595,7 +599,7 @@ public class AppOpsManager {
try {
int mode = mService.checkOperation(op, uid, packageName);
if (mode == MODE_ERRORED) {
- throw new SecurityException("Operation not allowed");
+ throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
@@ -650,7 +654,7 @@ public class AppOpsManager {
try {
int mode = mService.noteOperation(op, uid, packageName);
if (mode == MODE_ERRORED) {
- throw new SecurityException("Operation not allowed");
+ throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
@@ -672,7 +676,7 @@ public class AppOpsManager {
/** @hide */
public int noteOp(int op) {
- return noteOp(op, Process.myUid(), mContext.getBasePackageName());
+ return noteOp(op, Process.myUid(), mContext.getOpPackageName());
}
/** @hide */
@@ -710,7 +714,7 @@ public class AppOpsManager {
try {
int mode = mService.startOperation(getToken(mService), op, uid, packageName);
if (mode == MODE_ERRORED) {
- throw new SecurityException("Operation not allowed");
+ throw new SecurityException(buildSecurityExceptionMsg(op, uid, packageName));
}
return mode;
} catch (RemoteException e) {
@@ -732,7 +736,7 @@ public class AppOpsManager {
/** @hide */
public int startOp(int op) {
- return startOp(op, Process.myUid(), mContext.getBasePackageName());
+ return startOp(op, Process.myUid(), mContext.getOpPackageName());
}
/**
@@ -749,6 +753,6 @@ public class AppOpsManager {
}
public void finishOp(int op) {
- finishOp(op, Process.myUid(), mContext.getBasePackageName());
+ finishOp(op, Process.myUid(), mContext.getOpPackageName());
}
}
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index ab2739d411ac..e522b7881eb8 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1275,7 +1275,7 @@ final class ApplicationPackageManager extends PackageManager {
int newState, int flags) {
try {
mPM.setApplicationEnabledSetting(packageName, newState, flags,
- mContext.getUserId(), mContext.getBasePackageName());
+ mContext.getUserId(), mContext.getOpPackageName());
} catch (RemoteException e) {
// Should never happen!
}
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index c0080beb69a3..a4e80e515003 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -606,8 +606,7 @@ public abstract class ApplicationThreadNative extends Binder
IBinder activityToken = data.readStrongBinder();
IBinder requestToken = data.readStrongBinder();
int requestType = data.readInt();
- int index = data.readInt();
- requestAssistContextExtras(activityToken, requestToken, requestType, index);
+ requestAssistContextExtras(activityToken, requestToken, requestType);
reply.writeNoException();
return true;
}
@@ -1243,13 +1242,12 @@ class ApplicationThreadProxy implements IApplicationThread {
@Override
public void requestAssistContextExtras(IBinder activityToken, IBinder requestToken,
- int requestType, int index) throws RemoteException {
+ int requestType) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(activityToken);
data.writeStrongBinder(requestToken);
data.writeInt(requestType);
- data.writeInt(index);
mRemote.transact(REQUEST_ASSIST_CONTEXT_EXTRAS_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index e776a98a029b..8e9f3bbc6e53 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -47,6 +47,7 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
+import android.hardware.ConsumerIrManager;
import android.hardware.ISerialManager;
import android.hardware.SerialManager;
import android.hardware.SystemSensorManager;
@@ -183,6 +184,7 @@ class ContextImpl extends Context {
/*package*/ LoadedApk mPackageInfo;
private String mBasePackageName;
+ private String mOpPackageName;
private Resources mResources;
/*package*/ ActivityThread mMainThread;
private Context mOuterContext;
@@ -579,6 +581,11 @@ class ContextImpl extends Context {
return new PrintManager(ctx.getOuterContext(), service, UserHandle.myUserId(),
UserHandle.getAppId(Process.myUid()));
}});
+
+ registerService(CONSUMER_IR_SERVICE, new ServiceFetcher() {
+ public Object createService(ContextImpl ctx) {
+ return new ConsumerIrManager(ctx);
+ }});
}
static ContextImpl getImpl(Context context) {
@@ -679,6 +686,12 @@ class ContextImpl extends Context {
return mBasePackageName != null ? mBasePackageName : getPackageName();
}
+ /** @hide */
+ @Override
+ public String getOpPackageName() {
+ return mOpPackageName != null ? mOpPackageName : getBasePackageName();
+ }
+
@Override
public ApplicationInfo getApplicationInfo() {
if (mPackageInfo != null) {
@@ -1827,6 +1840,11 @@ class ContextImpl extends Context {
message);
}
+ /**
+ * Logs a warning if the system process directly called a method such as
+ * {@link #startService(Intent)} instead of {@link #startServiceAsUser(Intent, UserHandle)}.
+ * The "AsUser" variants allow us to properly enforce the user's restrictions.
+ */
private void warnIfCallingFromSystemProcess() {
if (Process.myUid() == Process.SYSTEM_UID) {
Slog.w(TAG, "Calling a method in the system process without a qualified user: "
@@ -1956,6 +1974,7 @@ class ContextImpl extends Context {
public ContextImpl(ContextImpl context) {
mPackageInfo = context.mPackageInfo;
mBasePackageName = context.mBasePackageName;
+ mOpPackageName = context.mOpPackageName;
mResources = context.mResources;
mMainThread = context.mMainThread;
mContentResolver = context.mContentResolver;
@@ -1972,7 +1991,21 @@ class ContextImpl extends Context {
final void init(LoadedApk packageInfo, IBinder activityToken, ActivityThread mainThread,
Resources container, String basePackageName, UserHandle user) {
mPackageInfo = packageInfo;
- mBasePackageName = basePackageName != null ? basePackageName : packageInfo.mPackageName;
+ if (basePackageName != null) {
+ mBasePackageName = mOpPackageName = basePackageName;
+ } else {
+ mBasePackageName = packageInfo.mPackageName;
+ ApplicationInfo ainfo = packageInfo.getApplicationInfo();
+ if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {
+ // Special case: system components allow themselves to be loaded in to other
+ // processes. For purposes of app ops, we must then consider the context as
+ // belonging to the package of this process, not the system itself, otherwise
+ // the package+uid verifications in app ops will fail.
+ mOpPackageName = ActivityThread.currentPackageName();
+ } else {
+ mOpPackageName = mBasePackageName;
+ }
+ }
mResources = mPackageInfo.getResources(mainThread);
mResourcesManager = ResourcesManager.getInstance();
@@ -2006,6 +2039,7 @@ class ContextImpl extends Context {
final void init(Resources resources, ActivityThread mainThread, UserHandle user) {
mPackageInfo = null;
mBasePackageName = null;
+ mOpPackageName = null;
mResources = resources;
mMainThread = mainThread;
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index af9a245c19e7..b2ae298944f4 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -384,12 +384,12 @@ public interface IActivityManager extends IInterface {
public void requestBugReport() throws RemoteException;
- public long inputDispatchingTimedOut(int pid, boolean aboveSystem) throws RemoteException;
+ public long inputDispatchingTimedOut(int pid, boolean aboveSystem, String reason)
+ throws RemoteException;
public Bundle getAssistContextExtras(int requestType) throws RemoteException;
- public void reportAssistContextExtras(IBinder token, Bundle extras, int index)
- throws RemoteException;
+ public void reportAssistContextExtras(IBinder token, Bundle extras) throws RemoteException;
public void killUid(int uid, String reason) throws RemoteException;
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index 01a0a9122199..058b9758f8fd 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -133,8 +133,8 @@ public interface IApplicationThread extends IInterface {
void dumpGfxInfo(FileDescriptor fd, String[] args) throws RemoteException;
void dumpDbInfo(FileDescriptor fd, String[] args) throws RemoteException;
void unstableProviderDied(IBinder provider) throws RemoteException;
- void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, int requestType,
- int index) throws RemoteException;
+ void requestAssistContextExtras(IBinder activityToken, IBinder requestToken, int requestType)
+ throws RemoteException;
void scheduleTranslucentConversionComplete(IBinder token, boolean timeout)
throws RemoteException;
void setProcessState(int state) throws RemoteException;
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index dbafc7830a97..3ee430639ab1 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -133,7 +133,7 @@ public class NotificationManager
}
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
try {
- service.enqueueNotificationWithTag(pkg, mContext.getBasePackageName(), tag, id,
+ service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
notification, idOut, UserHandle.myUserId());
if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
@@ -158,7 +158,7 @@ public class NotificationManager
}
if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
try {
- service.enqueueNotificationWithTag(pkg, mContext.getBasePackageName(), tag, id,
+ service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
notification, idOut, user.getIdentifier());
if (id != idOut[0]) {
Log.w(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index 1254bac828e4..396774090515 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -23,7 +23,6 @@ import android.content.ContextWrapper;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Build;
-import android.os.Bundle;
import android.os.RemoteException;
import android.os.IBinder;
import android.util.Log;
@@ -308,18 +307,6 @@ public abstract class Service extends ContextWrapper implements ComponentCallbac
}
/**
- * This is called on foreground services when the user is requesting an assist, to build a
- * full {@link Intent#ACTION_ASSIST} Intent with all of the context of the current
- * running foreground services. You can override this method to place into the bundle
- * anything you would like to appear as an item in the
- * {@link Intent#EXTRA_ASSIST_SERVICES_CONTEXTS} part of the assist Intent.
- * This method will not be called if this service is not in the foreground.
- * The default implementation does nothing.
- */
- public void onProvideAssistData(Bundle data) {
- }
-
- /**
* @deprecated Implement {@link #onStartCommand(Intent, int, int)} instead.
*/
@Deprecated
diff --git a/core/java/android/content/ClipboardManager.java b/core/java/android/content/ClipboardManager.java
index 69f9d4a876b2..73e6fd0d8f8c 100644
--- a/core/java/android/content/ClipboardManager.java
+++ b/core/java/android/content/ClipboardManager.java
@@ -122,7 +122,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
if (clip != null) {
clip.prepareToLeaveProcess();
}
- getService().setPrimaryClip(clip, mContext.getBasePackageName());
+ getService().setPrimaryClip(clip, mContext.getOpPackageName());
} catch (RemoteException e) {
}
}
@@ -132,7 +132,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public ClipData getPrimaryClip() {
try {
- return getService().getPrimaryClip(mContext.getBasePackageName());
+ return getService().getPrimaryClip(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
@@ -144,7 +144,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public ClipDescription getPrimaryClipDescription() {
try {
- return getService().getPrimaryClipDescription(mContext.getBasePackageName());
+ return getService().getPrimaryClipDescription(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
@@ -155,7 +155,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public boolean hasPrimaryClip() {
try {
- return getService().hasPrimaryClip(mContext.getBasePackageName());
+ return getService().hasPrimaryClip(mContext.getOpPackageName());
} catch (RemoteException e) {
return false;
}
@@ -166,7 +166,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
if (mPrimaryClipChangedListeners.size() == 0) {
try {
getService().addPrimaryClipChangedListener(
- mPrimaryClipChangedServiceListener, mContext.getBasePackageName());
+ mPrimaryClipChangedServiceListener, mContext.getOpPackageName());
} catch (RemoteException e) {
}
}
@@ -213,7 +213,7 @@ public class ClipboardManager extends android.text.ClipboardManager {
*/
public boolean hasText() {
try {
- return getService().hasClipboardText(mContext.getBasePackageName());
+ return getService().hasClipboardText(mContext.getOpPackageName());
} catch (RemoteException e) {
return false;
}
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 65a3a07bea98..0a1d3f9afc5a 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -34,7 +34,6 @@ import android.os.ICancellationSignal;
import android.os.OperationCanceledException;
import android.os.ParcelFileDescriptor;
import android.os.Process;
-import android.os.RemoteException;
import android.os.UserHandle;
import android.util.Log;
@@ -196,13 +195,13 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.query(
uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal));
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -216,11 +215,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return rejectInsert(uri, initialValues);
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.insert(uri, initialValues);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -229,11 +228,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.bulkInsert(uri, initialValues);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -256,11 +255,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
}
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.applyBatch(operations);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -269,11 +268,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.delete(uri, selection, selectionArgs);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -283,11 +282,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return 0;
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.update(uri, values, selection, selectionArgs);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -296,12 +295,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, mode);
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -310,22 +309,22 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String callingPkg, Uri uri, String mode, ICancellationSignal cancellationSignal)
throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, mode);
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openAssetFile(
uri, mode, CancellationSignal.fromTransport(cancellationSignal));
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@Override
public Bundle call(String callingPkg, String method, String arg, Bundle extras) {
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.call(method, arg, extras);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -338,12 +337,12 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public AssetFileDescriptor openTypedAssetFile(String callingPkg, Uri uri, String mimeType,
Bundle opts, ICancellationSignal cancellationSignal) throws FileNotFoundException {
enforceFilePermission(callingPkg, uri, "r");
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.openTypedAssetFile(
uri, mimeType, opts, CancellationSignal.fromTransport(cancellationSignal));
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -357,11 +356,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return null;
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.canonicalize(uri);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -370,11 +369,11 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
return null;
}
- mCallingPackage.set(callingPkg);
+ final String original = setCallingPackage(callingPkg);
try {
return ContentProvider.this.uncanonicalize(uri);
} finally {
- mCallingPackage.set(null);
+ setCallingPackage(original);
}
}
@@ -540,6 +539,16 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
}
/**
+ * Set the calling package, returning the current value (or {@code null})
+ * which can be used later to restore the previous state.
+ */
+ private String setCallingPackage(String callingPackage) {
+ final String original = mCallingPackage.get();
+ mCallingPackage.set(callingPackage);
+ return original;
+ }
+
+ /**
* Return the package name of the caller that initiated the request being
* processed on the current thread. The returned package will have been
* verified to belong to the calling UID. Returns {@code null} if not
@@ -909,8 +918,10 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*
* @param url The Uri to remove any canonicalization from.
*
- * @return Return the non-canonical representation of <var>url</var>, or return
- * the <var>url</var> as-is if there is nothing to do. Never return null.
+ * @return Return the non-canonical representation of <var>url</var>, return
+ * the <var>url</var> as-is if there is nothing to do, or return null if
+ * the data identified by the canonical representation can not be found in
+ * the current environment.
*/
public Uri uncanonicalize(Uri url) {
return url;
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index e6d9b2483951..e83c72779e67 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -344,7 +344,10 @@ public class ContentProviderClient {
/** {@hide} */
public static void closeQuietly(ContentProviderClient client) {
if (client != null) {
- client.release();
+ try {
+ client.release();
+ } catch (Exception ignored) {
+ }
}
}
}
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 9f462aab54f9..f250029153f6 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -261,7 +261,7 @@ public abstract class ContentResolver {
public ContentResolver(Context context) {
mContext = context != null ? context : ActivityThread.currentApplication();
- mPackageName = mContext.getBasePackageName();
+ mPackageName = mContext.getOpPackageName();
}
/** @hide */
@@ -548,14 +548,16 @@ public abstract class ContentResolver {
* it to its local non-canonical form. This can be useful in some cases where
* you know that you will only be using the Uri in the current environment and
* want to avoid any possible overhead when using it with the content
- * provider.
+ * provider or want to verify that the referenced data exists at all in the
+ * new environment.
*
* @param url The canonical {@link Uri} that is to be convered back to its
* non-canonical form.
*
- * @return Returns the non-canonical representation of <var>url</var>. This
- * function never returns null; if there is no conversion to be done, it returns
- * the same Uri that was provided.
+ * @return Returns the non-canonical representation of <var>url</var>. This will
+ * return null if data identified by the canonical Uri can not be found in
+ * the current environment; callers must always check for null and deal with
+ * that by appropriately falling back to an alternative.
*
* @see #canonicalize
*/
@@ -1745,6 +1747,9 @@ public abstract class ContentResolver {
* @param extras any extras to pass to the SyncAdapter.
*/
public static void requestSync(Account account, String authority, Bundle extras) {
+ if (extras == null) {
+ throw new IllegalArgumentException("Must specify extras.");
+ }
SyncRequest request =
new SyncRequest.Builder()
.setSyncAdapter(account, authority)
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 8df5bee57b86..92a9c7c84ab1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -435,6 +435,13 @@ public abstract class Context {
/** @hide Return the name of the base context this context is derived from. */
public abstract String getBasePackageName();
+ /** @hide Return the package name that should be used for app ops calls from
+ * this context. This is the same as {@link #getBasePackageName()} except in
+ * cases where system components are loaded into other app processes, in which
+ * case this will be the name of the primary package in that process (so that app
+ * ops uid verification will work with the name). */
+ public abstract String getOpPackageName();
+
/** Return the full application info for this context's package. */
public abstract ApplicationInfo getApplicationInfo();
@@ -2394,6 +2401,16 @@ public abstract class Context {
public static final String PRINT_SERVICE = "print";
/**
+ * Use with {@link #getSystemService} to retrieve a
+ * {@link android.hardware.ConsumerIrManager} for transmitting infrared
+ * signals from the device.
+ *
+ * @see #getSystemService
+ * @see android.hardware.ConsumerIrManager
+ */
+ public static final String CONSUMER_IR_SERVICE = "consumer_ir";
+
+ /**
* Determine whether the given permission is allowed for a particular
* process and user ID running in the system.
*
diff --git a/core/java/android/content/ContextWrapper.java b/core/java/android/content/ContextWrapper.java
index e09d36743dcf..a708dad6bf3e 100644
--- a/core/java/android/content/ContextWrapper.java
+++ b/core/java/android/content/ContextWrapper.java
@@ -141,6 +141,12 @@ public class ContextWrapper extends Context {
return mBase.getBasePackageName();
}
+ /** @hide */
+ @Override
+ public String getOpPackageName() {
+ return mBase.getOpPackageName();
+ }
+
@Override
public ApplicationInfo getApplicationInfo() {
return mBase.getApplicationInfo();
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 2f2aae4ff063..7925123194e1 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1153,9 +1153,8 @@ public class Intent implements Parcelable, Cloneable {
/**
* Activity Action: Perform assist action.
* <p>
- * Input: {@link #EXTRA_ASSIST_PACKAGE}, {@link #EXTRA_ASSIST_CONTEXT},
- * {@link #EXTRA_ASSIST_SERVICES_PACKAGES}, and {@link #EXTRA_ASSIST_SERVICES_CONTEXTS} can
- * provide additional optional contextual information about where the user was when they
+ * Input: {@link #EXTRA_ASSIST_PACKAGE}, {@link #EXTRA_ASSIST_CONTEXT}, can provide
+ * additional optional contextual information about where the user was when they
* requested the assist.
* Output: nothing.
*/
@@ -1165,52 +1164,31 @@ public class Intent implements Parcelable, Cloneable {
/**
* Activity Action: Perform voice assist action.
* <p>
- * Input: {@link #EXTRA_ASSIST_PACKAGE}, {@link #EXTRA_ASSIST_CONTEXT},
- * {@link #EXTRA_ASSIST_SERVICES_PACKAGES}, and {@link #EXTRA_ASSIST_SERVICES_CONTEXTS} can
- * provide additional optional contextual information about where the user was when they
+ * Input: {@link #EXTRA_ASSIST_PACKAGE}, {@link #EXTRA_ASSIST_CONTEXT}, can provide
+ * additional optional contextual information about where the user was when they
* requested the voice assist.
* Output: nothing.
+ * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_VOICE_ASSIST = "android.intent.action.VOICE_ASSIST";
/**
- * An optional field on {@link #ACTION_ASSIST} and {@link #ACTION_VOICE_ASSIST}
- * containing the name of the current foreground application package at the time
- * the assist was invoked.
+ * An optional field on {@link #ACTION_ASSIST} containing the name of the current foreground
+ * application package at the time the assist was invoked.
*/
public static final String EXTRA_ASSIST_PACKAGE
= "android.intent.extra.ASSIST_PACKAGE";
/**
- * An optional field on {@link #ACTION_ASSIST} and {@link #ACTION_VOICE_ASSIST}
- * containing additional contextual information supplied by the current
- * foreground app at the time of the assist request. This is a {@link Bundle} of
- * additional data.
+ * An optional field on {@link #ACTION_ASSIST} and containing additional contextual
+ * information supplied by the current foreground app at the time of the assist request.
+ * This is a {@link Bundle} of additional data.
*/
public static final String EXTRA_ASSIST_CONTEXT
= "android.intent.extra.ASSIST_CONTEXT";
/**
- * An optional field on {@link #ACTION_ASSIST} and {@link #ACTION_VOICE_ASSIST}
- * containing the application package names of foreground services at the time
- * of the assist request. This is an array of {@link String}s, with one entry
- * per service.
- */
- public static final String EXTRA_ASSIST_SERVICES_PACKAGES
- = "android.intent.extra.ASSIST_SERVICES_PACKAGES";
-
- /**
- * An optional field on {@link #ACTION_ASSIST} and {@link #ACTION_VOICE_ASSIST}
- * containing additional contextual information supplied by the current
- * foreground services at the time of the assist request. This is an array
- * of {@link Bundle}s of additional data, with one {@link Bundle} per service.
- */
- public static final String EXTRA_ASSIST_SERVICES_CONTEXTS
- = "android.intent.extra.ASSIST_SERVICES_CONTEXTS";
-
-
- /**
* Activity Action: List all available applications
* <p>Input: Nothing.
* <p>Output: nothing.
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 6760f4917496..4494e691ccfa 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -3015,11 +3015,6 @@ public class PackageParser {
s.info.flags = 0;
if (sa.getBoolean(
- com.android.internal.R.styleable.AndroidManifestService_provideAssistData,
- false)) {
- s.info.flags |= ServiceInfo.FLAG_PROVIDE_ASSIST_DATA;
- }
- if (sa.getBoolean(
com.android.internal.R.styleable.AndroidManifestService_stopWithTask,
false)) {
s.info.flags |= ServiceInfo.FLAG_STOP_WITH_TASK;
diff --git a/core/java/android/content/pm/ServiceInfo.java b/core/java/android/content/pm/ServiceInfo.java
index 3dc8717c11d8..796c2a422921 100644
--- a/core/java/android/content/pm/ServiceInfo.java
+++ b/core/java/android/content/pm/ServiceInfo.java
@@ -49,14 +49,6 @@ public class ServiceInfo extends ComponentInfo
public static final int FLAG_ISOLATED_PROCESS = 0x0002;
/**
- * Bit in {@link #flags}: If set,
- * {@link android.app.Service#onProvideAssistData(android.os.Bundle)} will
- * be called on the service when it is running in the foreground. Set from
- * the {@link android.R.attr#provideAssistData} attribute.
- */
- public static final int FLAG_PROVIDE_ASSIST_DATA = 0x0004;
-
- /**
* Bit in {@link #flags}: If set, a single instance of the service will
* run for all users on the device. Set from the
* {@link android.R.attr#singleUser} attribute.
diff --git a/core/java/android/database/MatrixCursor.java b/core/java/android/database/MatrixCursor.java
index 2a0d9b9f2842..5e107f23d3d4 100644
--- a/core/java/android/database/MatrixCursor.java
+++ b/core/java/android/database/MatrixCursor.java
@@ -186,7 +186,7 @@ public class MatrixCursor extends AbstractCursor {
* column value at a time. This follows the same ordering as the column
* names specified at cursor construction time.
* <li>Column and value pairs can be offered for possible inclusion using
- * {@link #offer(String, Object)}. If the cursor includes the given column,
+ * {@link #add(String, Object)}. If the cursor includes the given column,
* the value will be set for that column, otherwise the value is ignored.
* This approach is useful when matching data to a custom projection.
* </ul>
@@ -227,7 +227,7 @@ public class MatrixCursor extends AbstractCursor {
*
* @return this builder to support chaining
*/
- public RowBuilder offer(String columnName, Object value) {
+ public RowBuilder add(String columnName, Object value) {
for (int i = 0; i < columnNames.length; i++) {
if (columnName.equals(columnNames[i])) {
data[(row * columnCount) + i] = value;
diff --git a/core/java/android/hardware/ConsumerIrManager.java b/core/java/android/hardware/ConsumerIrManager.java
new file mode 100644
index 000000000000..baa743c04cd2
--- /dev/null
+++ b/core/java/android/hardware/ConsumerIrManager.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2013 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.hardware;
+
+import android.content.Context;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * Class that operates consumer infrared on the device.
+ *
+ * <p>
+ * To obtain an instance of the system infrared transmitter, call
+ * {@link Context#getSystemService} with {@link Context#CONSUMER_IR} as the argument.
+ * </p>
+ */
+public final class ConsumerIrManager {
+ private static final String TAG = "ConsumerIr";
+
+ private final String mPackageName;
+ private final IConsumerIrService mService;
+
+ /**
+ * @hide to prevent subclassing from outside of the framework
+ */
+ public ConsumerIrManager(Context context) {
+ mPackageName = context.getPackageName();
+ mService = IConsumerIrService.Stub.asInterface(
+ ServiceManager.getService(Context.CONSUMER_IR_SERVICE));
+ }
+
+ /**
+ * Check whether the device has an infrared emitter.
+ *
+ * @return true if the device has an infrared emitter, else false.
+ */
+ public boolean hasIrEmitter() {
+ if (mService == null) {
+ Log.w(TAG, "no consumer ir service.");
+ return false;
+ }
+
+ try {
+ return mService.hasIrEmitter();
+ } catch (RemoteException e) {
+ }
+ return false;
+ }
+
+ /**
+ * Tansmit and infrared pattern
+ * <p>
+ * This method is synchronous; when it returns the pattern has
+ * been transmitted. Only patterns shorter than 2 seconds will
+ * be transmitted.
+ * </p>
+ *
+ * @param carrierFrequency The IR carrier frequency in Hertz.
+ * @param pattern The alternating on/off pattern in microseconds to transmit.
+ */
+ public void transmit(int carrierFrequency, int[] pattern) {
+ if (mService == null) {
+ Log.w(TAG, "failed to transmit; no consumer ir service.");
+ return;
+ }
+
+ try {
+ mService.transmit(mPackageName, carrierFrequency, pattern);
+ } catch (RemoteException e) {
+ Log.w(TAG, "failed to transmit.", e);
+ }
+ }
+
+ /**
+ * Represents a range of carrier frequencies (inclusive) on which the
+ * infrared transmitter can transmit
+ */
+ public final class CarrierFrequencyRange {
+ private final int mMinFrequency;
+ private final int mMaxFrequency;
+
+ /**
+ * Create a segment of a carrier frequency range.
+ *
+ * @param min The minimum transmittable frequency in this range segment.
+ * @param max The maximum transmittable frequency in this range segment.
+ */
+ public CarrierFrequencyRange(int min, int max) {
+ mMinFrequency = min;
+ mMaxFrequency = max;
+ }
+
+ /**
+ * Get the minimum (inclusive) frequency in this range segment.
+ */
+ public int getMinFrequency() {
+ return mMinFrequency;
+ }
+
+ /**
+ * Get the maximum (inclusive) frequency in this range segment.
+ */
+ public int getMaxFrequency() {
+ return mMaxFrequency;
+ }
+ };
+
+ /**
+ * Query the infrared transmitter's supported carrier frequencies
+ *
+ * @return an array of {@link #CarrierFreqRange} objects representing
+ * the ranges that the transmitter can support, or null if there was
+ * an error communicating with the Consumer IR Service.
+ */
+ public CarrierFrequencyRange[] getCarrierFrequencies() {
+ if (mService == null) {
+ Log.w(TAG, "no consumer ir service.");
+ return null;
+ }
+
+ try {
+ int[] freqs = mService.getCarrierFrequencies();
+ if (freqs.length % 2 != 0) {
+ Log.w(TAG, "consumer ir service returned an uneven number of frequencies.");
+ return null;
+ }
+ CarrierFrequencyRange[] range = new CarrierFrequencyRange[freqs.length / 2];
+
+ for (int i = 0; i < freqs.length; i += 2) {
+ range[i / 2] = new CarrierFrequencyRange(freqs[i], freqs[i+1]);
+ }
+ return range;
+ } catch (RemoteException e) {
+ }
+ return null;
+ }
+
+}
diff --git a/core/java/android/hardware/IConsumerIrService.aidl b/core/java/android/hardware/IConsumerIrService.aidl
new file mode 100644
index 000000000000..c79bd1958226
--- /dev/null
+++ b/core/java/android/hardware/IConsumerIrService.aidl
@@ -0,0 +1,26 @@
+/**
+ * Copyright (c) 2013, 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.hardware;
+
+/** {@hide} */
+interface IConsumerIrService
+{
+ boolean hasIrEmitter();
+ void transmit(String packageName, int carrierFrequency, in int[] pattern);
+ int[] getCarrierFrequencies();
+}
+
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 8903b4ac8ed9..ff9282ee109c 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -55,7 +55,7 @@ public final class CameraManager {
private final ICameraService mCameraService;
private ArrayList<String> mDeviceIdList;
- private HashSet<CameraListener> mListenerSet = new HashSet<CameraListener>();
+ private final HashSet<CameraListener> mListenerSet = new HashSet<CameraListener>();
private final Context mContext;
private final Object mLock = new Object();
@@ -332,7 +332,7 @@ public final class CameraManager {
Integer oldStatus = mDeviceStatus.put(id, status);
- if (oldStatus == status) {
+ if (oldStatus != null && oldStatus == status) {
Log.v(TAG, String.format(
"Device status changed to 0x%x, which is what it already was",
status));
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4cf38b6b39f7..c78a973ceeb0 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -1476,4 +1476,20 @@ public class ConnectivityManager {
} catch (RemoteException e) {
}
}
+
+ /**
+ * Set the value for enabling/disabling airplane mode
+ *
+ * @param enable whether to enable airplane mode or not
+ *
+ * <p>This method requires the call to hold the permission
+ * {@link android.Manifest.permission#CONNECTIVITY_INTERNAL}.
+ * @hide
+ */
+ public void setAirplaneMode(boolean enable) {
+ try {
+ mService.setAirplaneMode(enable);
+ } catch (RemoteException e) {
+ }
+ }
}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index a6f10ecbe4c4..c1da2e32aa00 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -93,12 +93,6 @@ interface IConnectivityManager
String[] getTetheredIfaces();
- /**
- * Return list of interface pairs that are actively tethered. Even indexes are
- * remote interface, and odd indexes are corresponding local interfaces.
- */
- String[] getTetheredIfacePairs();
-
String[] getTetheringErroredIfaces();
String[] getTetherableUsbRegexs();
@@ -156,4 +150,6 @@ interface IConnectivityManager
LinkQualityInfo[] getAllLinkQualityInfo();
void setProvisioningNotificationVisible(boolean visible, int networkType, in String extraInfo, in String url);
+
+ void setAirplaneMode(boolean enable);
}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index 41c66034c1a8..40a3612efe5a 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -22,6 +22,7 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
+import android.content.res.Resources.NotFoundException;
import android.content.res.TypedArray;
import android.content.res.XmlResourceParser;
import android.graphics.drawable.Drawable;
@@ -80,10 +81,15 @@ public final class ApduServiceInfo implements Parcelable {
final boolean mRequiresDeviceUnlock;
/**
+ * The id of the service banner specified in XML.
+ */
+ final int mBannerResourceId;
+
+ /**
* @hide
*/
public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
- ArrayList<AidGroup> aidGroups, boolean requiresUnlock) {
+ ArrayList<AidGroup> aidGroups, boolean requiresUnlock, int bannerResource) {
this.mService = info;
this.mDescription = description;
this.mAidGroups = aidGroups;
@@ -95,6 +101,7 @@ public final class ApduServiceInfo implements Parcelable {
this.mCategoryToGroup.put(aidGroup.category, aidGroup);
this.mAids.addAll(aidGroup.aids);
}
+ this.mBannerResourceId = bannerResource;
}
public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost)
@@ -105,12 +112,8 @@ public final class ApduServiceInfo implements Parcelable {
if (onHost) {
parser = si.loadXmlMetaData(pm, HostApduService.SERVICE_META_DATA);
if (parser == null) {
- Log.d(TAG, "Didn't find service meta-data, trying legacy.");
- parser = si.loadXmlMetaData(pm, HostApduService.OLD_SERVICE_META_DATA);
- if (parser == null) {
- throw new XmlPullParserException("No " + HostApduService.SERVICE_META_DATA +
- " meta-data");
- }
+ throw new XmlPullParserException("No " + HostApduService.SERVICE_META_DATA +
+ " meta-data");
}
} else {
parser = si.loadXmlMetaData(pm, OffHostApduService.SERVICE_META_DATA);
@@ -145,6 +148,9 @@ public final class ApduServiceInfo implements Parcelable {
mRequiresDeviceUnlock = sa.getBoolean(
com.android.internal.R.styleable.HostApduService_requireDeviceUnlock,
false);
+ mBannerResourceId = sa.getResourceId(
+ com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
+ sa.recycle();
} else {
TypedArray sa = res.obtainAttributes(attrs,
com.android.internal.R.styleable.OffHostApduService);
@@ -152,6 +158,9 @@ public final class ApduServiceInfo implements Parcelable {
mDescription = sa.getString(
com.android.internal.R.styleable.OffHostApduService_description);
mRequiresDeviceUnlock = false;
+ mBannerResourceId = sa.getResourceId(
+ com.android.internal.R.styleable.HostApduService_apduServiceBanner, -1);
+ sa.recycle();
}
mAidGroups = new ArrayList<AidGroup>();
@@ -187,6 +196,7 @@ public final class ApduServiceInfo implements Parcelable {
} else {
currentGroup = new AidGroup(groupCategory, groupDescription);
}
+ groupAttrs.recycle();
} else if (eventType == XmlPullParser.END_TAG && "aid-group".equals(tagName) &&
currentGroup != null) {
if (currentGroup.aids.size() > 0) {
@@ -210,6 +220,7 @@ public final class ApduServiceInfo implements Parcelable {
} else {
Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
}
+ a.recycle();
}
}
} catch (NameNotFoundException e) {
@@ -252,6 +263,21 @@ public final class ApduServiceInfo implements Parcelable {
return mService.loadIcon(pm);
}
+ public Drawable loadBanner(PackageManager pm) {
+ Resources res;
+ try {
+ res = pm.getResourcesForApplication(mService.serviceInfo.packageName);
+ Drawable banner = res.getDrawable(mBannerResourceId);
+ return banner;
+ } catch (NotFoundException e) {
+ Log.e(TAG, "Could not load banner.");
+ return null;
+ } catch (NameNotFoundException e) {
+ Log.e(TAG, "Could not load banner.");
+ return null;
+ }
+ }
+
static boolean isValidAid(String aid) {
if (aid == null)
return false;
@@ -306,6 +332,7 @@ public final class ApduServiceInfo implements Parcelable {
dest.writeTypedList(mAidGroups);
}
dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
+ dest.writeInt(mBannerResourceId);
};
public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
@@ -321,7 +348,8 @@ public final class ApduServiceInfo implements Parcelable {
source.readTypedList(aidGroups, AidGroup.CREATOR);
}
boolean requiresUnlock = (source.readInt() != 0) ? true : false;
- return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock);
+ int bannerResource = source.readInt();
+ return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock, bannerResource);
}
@Override
diff --git a/core/java/android/nfc/cardemulation/CardEmulationManager.java b/core/java/android/nfc/cardemulation/CardEmulationManager.java
deleted file mode 100644
index 124ea1c331c5..000000000000
--- a/core/java/android/nfc/cardemulation/CardEmulationManager.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2013 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.nfc.cardemulation;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.app.ActivityThread;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.nfc.INfcCardEmulation;
-import android.nfc.NfcAdapter;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.Log;
-
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * TODO Remove when calling .apks are upgraded
- * @hide
- */
-public final class CardEmulationManager {
- static final String TAG = "CardEmulationManager";
-
- /**
- * Activity action: ask the user to change the default
- * card emulation service for a certain category. This will
- * show a dialog that asks the user whether he wants to
- * replace the current default service with the service
- * identified with the ComponentName specified in
- * {@link #EXTRA_SERVICE_COMPONENT}, for the category
- * specified in {@link #EXTRA_CATEGORY}
- */
- @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
- public static final String ACTION_CHANGE_DEFAULT =
- "android.nfc.cardemulation.ACTION_CHANGE_DEFAULT";
-
- /**
- * The category extra for {@link #ACTION_CHANGE_DEFAULT}
- *
- * @see #ACTION_CHANGE_DEFAULT
- */
- public static final String EXTRA_CATEGORY = "category";
-
- /**
- * The ComponentName object passed in as a parcelable
- * extra for {@link #ACTION_CHANGE_DEFAULT}
- *
- * @see #ACTION_CHANGE_DEFAULT
- */
- public static final String EXTRA_SERVICE_COMPONENT = "component";
-
- /**
- * The payment category can be used to indicate that an AID
- * represents a payment application.
- */
- public static final String CATEGORY_PAYMENT = "payment";
-
- /**
- * If an AID group does not contain a category, or the
- * specified category is not defined by the platform version
- * that is parsing the AID group, all AIDs in the group will
- * automatically be categorized under the {@link #CATEGORY_OTHER}
- * category.
- */
- public static final String CATEGORY_OTHER = "other";
-
- /**
- * Return value for {@link #getSelectionModeForCategory(String)}.
- *
- * <p>In this mode, the user has set a default service for this
- * AID category. If a remote reader selects any of the AIDs
- * that the default service has registered in this category,
- * that service will automatically be bound to to handle
- * the transaction.
- *
- * <p>There are still cases where a service that is
- * not the default for a category can selected:
- * <p>
- * If a remote reader selects an AID in this category
- * that is not handled by the default service, and there is a set
- * of other services {S} that do handle this AID, the
- * user is asked if he wants to use any of the services in
- * {S} instead.
- * <p>
- * As a special case, if the size of {S} is one, containing a single service X,
- * and all AIDs X has registered in this category are not
- * registered by any other service, then X will be
- * selected automatically without asking the user.
- * <p>Example:
- * <ul>
- * <li>Service A registers AIDs "1", "2" and "3" in the category
- * <li>Service B registers AIDs "3" and "4" in the category
- * <li>Service C registers AIDs "5" and "6" in the category
- * </ul>
- * In this case, the following will happen when service A
- * is the default:
- * <ul>
- * <li>Reader selects AID "1", "2" or "3": service A is invoked automatically
- * <li>Reader selects AID "4": the user is asked to confirm he
- * wants to use service B, because its AIDs overlap with service A.
- * <li>Reader selects AID "5" or "6": service C is invoked automatically,
- * because all AIDs it has asked for are only registered by C,
- * and there is no overlap.
- * </ul>
- *
- */
- public static final int SELECTION_MODE_PREFER_DEFAULT = 0;
-
- /**
- * Return value for {@link #getSelectionModeForCategory(String)}.
- *
- * <p>In this mode, whenever an AID of this category is selected,
- * the user is asked which service he wants to use to handle
- * the transaction, even if there is only one matching service.
- */
- public static final int SELECTION_MODE_ALWAYS_ASK = 1;
-
- /**
- * Return value for {@link #getSelectionModeForCategory(String)}.
- *
- * <p>In this mode, the user will only be asked to select a service
- * if the selected AID has been registered by multiple applications.
- */
- public static final int SELECTION_MODE_ASK_IF_CONFLICT = 2;
-
- static boolean sIsInitialized = false;
- static HashMap<Context, CardEmulationManager> sCardEmuManagers = new HashMap();
- static INfcCardEmulation sService;
-
- final Context mContext;
-
- private CardEmulationManager(Context context, INfcCardEmulation service) {
- mContext = context.getApplicationContext();
- sService = service;
- }
-
- public static synchronized CardEmulationManager getInstance(NfcAdapter adapter) {
- if (adapter == null) throw new NullPointerException("NfcAdapter is null");
- Context context = adapter.getContext();
- if (context == null) {
- Log.e(TAG, "NfcAdapter context is null.");
- throw new UnsupportedOperationException();
- }
- if (!sIsInitialized) {
- IPackageManager pm = ActivityThread.getPackageManager();
- if (pm == null) {
- Log.e(TAG, "Cannot get PackageManager");
- throw new UnsupportedOperationException();
- }
- try {
- if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC_HOST_CARD_EMULATION)) {
- Log.e(TAG, "This device does not support card emulation");
- throw new UnsupportedOperationException();
- }
- } catch (RemoteException e) {
- Log.e(TAG, "PackageManager query failed.");
- throw new UnsupportedOperationException();
- }
- sIsInitialized = true;
- }
- CardEmulationManager manager = sCardEmuManagers.get(context);
- if (manager == null) {
- // Get card emu service
- INfcCardEmulation service = adapter.getCardEmulationService();
- manager = new CardEmulationManager(context, service);
- sCardEmuManagers.put(context, manager);
- }
- return manager;
- }
-
- /**
- * Allows an application to query whether a service is currently
- * the default service to handle a card emulation category.
- *
- * <p>Note that if {@link #getSelectionModeForCategory(String)}
- * returns {@link #SELECTION_MODE_ALWAYS_ASK}, this method will always
- * return false.
- *
- * @param service The ComponentName of the service
- * @param category The category
- * @return whether service is currently the default service for the category.
- */
- public boolean isDefaultServiceForCategory(ComponentName service, String category) {
- try {
- return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service, category);
- } catch (RemoteException e) {
- // Try one more time
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover CardEmulationService.");
- return false;
- }
- try {
- return sService.isDefaultServiceForCategory(UserHandle.myUserId(), service,
- category);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to recover CardEmulationService.");
- return false;
- }
- }
- }
-
- /**
- *
- * Allows an application to query whether a service is currently
- * the default handler for a specified ISO7816-4 Application ID.
- *
- * @param service The ComponentName of the service
- * @param aid The ISO7816-4 Application ID
- * @return
- */
- public boolean isDefaultServiceForAid(ComponentName service, String aid) {
- try {
- return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid);
- } catch (RemoteException e) {
- // Try one more time
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover CardEmulationService.");
- return false;
- }
- try {
- return sService.isDefaultServiceForAid(UserHandle.myUserId(), service, aid);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach CardEmulationService.");
- return false;
- }
- }
- }
-
- /**
- * Returns the application selection mode for the passed in category.
- * Valid return values are:
- * <p>{@link #SELECTION_MODE_PREFER_DEFAULT} the user has requested a default
- * application for this category, which will be preferred.
- * <p>{@link #SELECTION_MODE_ALWAYS_ASK} the user has requested to be asked
- * every time what app he would like to use in this category.
- * <p>{@link #SELECTION_MODE_ASK_IF_CONFLICT} the user will only be asked
- * to pick a service if there is a conflict.
- * @param category The category, for example {@link #CATEGORY_PAYMENT}
- * @return
- */
- public int getSelectionModeForCategory(String category) {
- if (CATEGORY_PAYMENT.equals(category)) {
- String defaultComponent = Settings.Secure.getString(mContext.getContentResolver(),
- Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT);
- if (defaultComponent != null) {
- return SELECTION_MODE_PREFER_DEFAULT;
- } else {
- return SELECTION_MODE_ALWAYS_ASK;
- }
- } else {
- // All other categories are in "only ask if conflict" mode
- return SELECTION_MODE_ASK_IF_CONFLICT;
- }
- }
-
- /**
- * @hide
- */
- public boolean setDefaultServiceForCategory(ComponentName service, String category) {
- try {
- return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service, category);
- } catch (RemoteException e) {
- // Try one more time
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover CardEmulationService.");
- return false;
- }
- try {
- return sService.setDefaultServiceForCategory(UserHandle.myUserId(), service,
- category);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach CardEmulationService.");
- return false;
- }
- }
- }
-
- /**
- * @hide
- */
- public boolean setDefaultForNextTap(ComponentName service) {
- try {
- return sService.setDefaultForNextTap(UserHandle.myUserId(), service);
- } catch (RemoteException e) {
- // Try one more time
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover CardEmulationService.");
- return false;
- }
- try {
- return sService.setDefaultForNextTap(UserHandle.myUserId(), service);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach CardEmulationService.");
- return false;
- }
- }
- }
- /**
- * @hide
- */
- public List<ApduServiceInfo> getServices(String category) {
- try {
- return sService.getServices(UserHandle.myUserId(), category);
- } catch (RemoteException e) {
- // Try one more time
- recoverService();
- if (sService == null) {
- Log.e(TAG, "Failed to recover CardEmulationService.");
- return null;
- }
- try {
- return sService.getServices(UserHandle.myUserId(), category);
- } catch (RemoteException ee) {
- Log.e(TAG, "Failed to reach CardEmulationService.");
- return null;
- }
- }
- }
-
- void recoverService() {
- NfcAdapter adapter = NfcAdapter.getDefaultAdapter(mContext);
- sService = adapter.getCardEmulationService();
- }
-}
diff --git a/core/java/android/nfc/cardemulation/HostApduService.java b/core/java/android/nfc/cardemulation/HostApduService.java
index 174acc0b92de..e2c3ca6c5735 100644
--- a/core/java/android/nfc/cardemulation/HostApduService.java
+++ b/core/java/android/nfc/cardemulation/HostApduService.java
@@ -50,23 +50,6 @@ public abstract class HostApduService extends Service {
"android.nfc.cardemulation.host_apdu_service";
/**
- * The {@link Intent} that must be declared as handled by the service.
- * TODO Remove
- * @hide
- */
- public static final String OLD_SERVICE_INTERFACE =
- "android.nfc.HostApduService";
-
- /**
- * The name of the meta-data element that contains
- * more information about this service.
- *
- * TODO Remove
- * @hide
- */
- public static final String OLD_SERVICE_META_DATA = "android.nfc.HostApduService";
-
- /**
* Reason for {@link #onDeactivated(int)}.
* Indicates deactivation was due to the NFC link
* being lost.
@@ -282,37 +265,7 @@ public abstract class HostApduService extends Service {
* @return a byte-array containing the response APDU, or null if no
* response APDU can be sent at this point.
*/
- public byte[] processCommandApdu(byte[] commandApdu, Bundle extras) {
- // TODO make this abstract
- return processCommandApdu(commandApdu, 0);
- }
-
- /**
- * <p>This method will be called when a command APDU has been received
- * from a remote device. A response APDU can be provided directly
- * by returning a byte-array in this method. Note that in general
- * response APDUs must be sent as quickly as possible, given the fact
- * that the user is likely holding his device over an NFC reader
- * when this method is called.
- *
- * <p class="note">If there are multiple services that have registered for the same
- * AIDs in their meta-data entry, you will only get called if the user has
- * explicitly selected your service, either as a default or just for the next tap.
- *
- * <p class="note">This method is running on the main thread of your application.
- * If you cannot return a response APDU immediately, return null
- * and use the {@link #sendResponseApdu(byte[])} method later.
- *
- * @deprecated use {@link #processCommandApdu(byte[], Bundle)}
- * @param commandApdu
- * @param flags
- * @return a byte-array containing the response APDU, or null if no
- * response APDU can be sent at this point.
- * @hide
- */
- public byte[] processCommandApdu(byte[] commandApdu, int flags) {
- return null;
- }
+ public abstract byte[] processCommandApdu(byte[] commandApdu, Bundle extras);
/**
* This method will be called in two possible scenarios:
diff --git a/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 61e5a4ba5a54..21b8ae57e36a 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -260,11 +260,9 @@ interface INetworkManagementService
NetworkStats getNetworkStatsUidDetail(int uid);
/**
- * Return summary of network statistics for the requested pairs of
- * tethering interfaces. Even indexes are remote interface, and odd
- * indexes are corresponding local interfaces.
+ * Return summary of network statistics all tethering interfaces.
*/
- NetworkStats getNetworkStatsTethering(in String[] ifacePairs);
+ NetworkStats getNetworkStatsTethering();
/**
* Set quota for an interface.
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 52e5f38dc90f..5e0d48949c22 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -407,7 +407,7 @@ public final class PowerManager {
*/
public WakeLock newWakeLock(int levelAndFlags, String tag) {
validateWakeLockParameters(levelAndFlags, tag);
- return new WakeLock(levelAndFlags, tag, mContext.getBasePackageName());
+ return new WakeLock(levelAndFlags, tag, mContext.getOpPackageName());
}
/** @hide */
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index e66fb2854aa7..700f80d1991c 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -39,7 +39,7 @@ public class SystemVibrator extends Vibrator {
}
public SystemVibrator(Context context) {
- mPackageName = context.getBasePackageName();
+ mPackageName = context.getOpPackageName();
mService = IVibratorService.Stub.asInterface(
ServiceManager.getService("vibrator"));
}
diff --git a/core/java/android/preference/PreferenceActivity.java b/core/java/android/preference/PreferenceActivity.java
index 5d886a3374af..a99705bd12ae 100644
--- a/core/java/android/preference/PreferenceActivity.java
+++ b/core/java/android/preference/PreferenceActivity.java
@@ -894,14 +894,11 @@ public abstract class PreferenceActivity extends ListActivity implements
*/
protected boolean isValidFragment(String fragmentName) {
if (getApplicationInfo().targetSdkVersion >= android.os.Build.VERSION_CODES.KITKAT) {
- Log.w(TAG, "Subclasses of PreferenceActivity must override isValidFragment(String)"
+ throw new RuntimeException(
+ "Subclasses of PreferenceActivity must override isValidFragment(String)"
+ " to verify that the Fragment class is valid! " + this.getClass().getName()
+ " has not checked if fragment " + fragmentName + " is valid.");
- // Return true for now, but will eventually return false when all bundled apps
- // have been modified. TODO: change to return false
- return true;
} else {
- Log.i(TAG, "PreferenceActivity built on pre-KLP launching fragment: " + fragmentName);
return true;
}
}
diff --git a/core/java/android/preference/TwoStatePreference.java b/core/java/android/preference/TwoStatePreference.java
index c6498791997c..af8395334045 100644
--- a/core/java/android/preference/TwoStatePreference.java
+++ b/core/java/android/preference/TwoStatePreference.java
@@ -21,6 +21,7 @@ import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
@@ -215,17 +216,17 @@ public abstract class TwoStatePreference extends Preference {
TextView summaryView = (TextView) view.findViewById(com.android.internal.R.id.summary);
if (summaryView != null) {
boolean useDefaultSummary = true;
- if (mChecked && mSummaryOn != null) {
+ if (mChecked && !TextUtils.isEmpty(mSummaryOn)) {
summaryView.setText(mSummaryOn);
useDefaultSummary = false;
- } else if (!mChecked && mSummaryOff != null) {
+ } else if (!mChecked && !TextUtils.isEmpty(mSummaryOff)) {
summaryView.setText(mSummaryOff);
useDefaultSummary = false;
}
if (useDefaultSummary) {
final CharSequence summary = getSummary();
- if (summary != null) {
+ if (!TextUtils.isEmpty(summary)) {
summaryView.setText(summary);
useDefaultSummary = false;
}
diff --git a/core/java/android/printservice/PrintService.java b/core/java/android/printservice/PrintService.java
index 96552af92e64..0ffc40ab60d5 100644
--- a/core/java/android/printservice/PrintService.java
+++ b/core/java/android/printservice/PrintService.java
@@ -20,6 +20,7 @@ import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
+import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
@@ -155,6 +156,8 @@ public abstract class PrintService extends Service {
private static final String LOG_TAG = "PrintService";
+ private static final boolean DEBUG = false;
+
/**
* The {@link Intent} action that must be declared as handled by a service
* in its manifest for the system to recognize it as a print service.
@@ -433,6 +436,9 @@ public abstract class PrintService extends Service {
case MSG_ON_PRINTJOB_QUEUED: {
PrintJobInfo printJobInfo = (PrintJobInfo) message.obj;
+ if (DEBUG) {
+ Log.i(LOG_TAG, "Queued: " + printJobInfo);
+ }
onPrintJobQueued(new PrintJob(printJobInfo, mClient));
} break;
diff --git a/core/java/android/printservice/PrintServiceInfo.java b/core/java/android/printservice/PrintServiceInfo.java
index 128628d53072..8e9636c2b733 100644
--- a/core/java/android/printservice/PrintServiceInfo.java
+++ b/core/java/android/printservice/PrintServiceInfo.java
@@ -239,10 +239,10 @@ public final class PrintServiceInfo implements Parcelable {
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("PrintServiceInfo{");
- builder.append("id:").append(mId).append(", ");
- builder.append("resolveInfo:").append(mResolveInfo).append(", ");
- builder.append("settingsActivityName:").append(mSettingsActivityName);
- builder.append("addPrintersActivityName:").append(mAddPrintersActivityName);
+ builder.append("id=").append(mId);
+ builder.append(", resolveInfo=").append(mResolveInfo);
+ builder.append(", settingsActivityName=").append(mSettingsActivityName);
+ builder.append(", addPrintersActivityName=").append(mAddPrintersActivityName);
builder.append("}");
return builder.toString();
}
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 9d52c8385725..a6f23a853e2d 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -137,8 +137,18 @@ public class CallLog {
public static final String NUMBER = "number";
/**
- * The number presenting rules set by the network for "allowed",
- * "payphone", "restricted" or "unknown".
+ * The number presenting rules set by the network.
+ *
+ * <p>
+ * Allowed values:
+ * <ul>
+ * <li>{@link #PRESENTATION_ALLOWED}</li>
+ * <li>{@link #PRESENTATION_RESTRICTED}</li>
+ * <li>{@link #PRESENTATION_UNKNOWN}</li>
+ * <li>{@link #PRESENTATION_PAYPHONE}</li>
+ * </ul>
+ * </p>
+ *
* <P>Type: INTEGER</P>
*/
public static final String NUMBER_PRESENTATION = "presentation";
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index 5333a250ccdd..43120c4c8901 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -251,6 +251,15 @@ public final class DocumentsContract {
* @see #COLUMN_FLAGS
*/
public static final int FLAG_DIR_PREFERS_GRID = 1 << 5;
+
+ /**
+ * Flag indicating that a directory prefers its contents be sorted by
+ * {@link #COLUMN_LAST_MODIFIED}. Only valid when
+ * {@link #COLUMN_MIME_TYPE} is {@link #MIME_TYPE_DIR}.
+ *
+ * @see #COLUMN_FLAGS
+ */
+ public static final int FLAG_DIR_PREFERS_LAST_MODIFIED = 1 << 6;
}
/**
@@ -292,9 +301,6 @@ public final class DocumentsContract {
* @see #FLAG_LOCAL_ONLY
* @see #FLAG_SUPPORTS_CREATE
* @see #FLAG_ADVANCED
- * @see #FLAG_PROVIDES_AUDIO
- * @see #FLAG_PROVIDES_IMAGES
- * @see #FLAG_PROVIDES_VIDEO
*/
public static final String COLUMN_FLAGS = "flags";
@@ -453,6 +459,7 @@ public final class DocumentsContract {
private static final String PATH_SEARCH = "search";
private static final String PARAM_QUERY = "query";
+ private static final String PARAM_MANAGE = "manage";
/**
* Build Uri representing the roots of a document provider. When queried, a
@@ -577,6 +584,16 @@ public final class DocumentsContract {
return searchDocumentsUri.getQueryParameter(PARAM_QUERY);
}
+ /** {@hide} */
+ public static Uri setManageMode(Uri uri) {
+ return uri.buildUpon().appendQueryParameter(PARAM_MANAGE, "true").build();
+ }
+
+ /** {@hide} */
+ public static boolean isManageMode(Uri uri) {
+ return uri.getBooleanQueryParameter(PARAM_MANAGE, false);
+ }
+
/**
* Return list of all documents that the calling package has "open." These
* are Uris matching {@link DocumentsContract} to which persistent
@@ -688,6 +705,7 @@ public final class DocumentsContract {
* @param mimeType MIME type of new document
* @param displayName name of new document
* @return newly created document, or {@code null} if failed
+ * @hide
*/
public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri,
String mimeType, String displayName) {
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 1b0fc4d1f70d..d80182703bdf 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -167,6 +167,14 @@ public abstract class DocumentsProvider extends ContentProvider {
String parentDocumentId, String[] projection, String sortOrder)
throws FileNotFoundException;
+ /** {@hide} */
+ @SuppressWarnings("unused")
+ public Cursor queryChildDocumentsForManage(
+ String parentDocumentId, String[] projection, String sortOrder)
+ throws FileNotFoundException {
+ throw new UnsupportedOperationException("Manage not supported");
+ }
+
/**
* Return documents that that match the given query, starting the search at
* the given directory.
@@ -262,7 +270,12 @@ public abstract class DocumentsProvider extends ContentProvider {
case MATCH_DOCUMENT:
return queryDocument(getDocumentId(uri), projection);
case MATCH_CHILDREN:
- return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
+ if (DocumentsContract.isManageMode(uri)) {
+ return queryChildDocumentsForManage(
+ getDocumentId(uri), projection, sortOrder);
+ } else {
+ return queryChildDocuments(getDocumentId(uri), projection, sortOrder);
+ }
case MATCH_SEARCH:
return querySearchDocuments(
getDocumentId(uri), getSearchDocumentsQuery(uri), projection);
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 1a80818ff08f..025926eb484a 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2439,7 +2439,9 @@ public final class Settings {
SIP_CALL_OPTIONS,
SIP_RECEIVE_CALLS,
POINTER_SPEED,
- VIBRATE_WHEN_RINGING
+ VIBRATE_WHEN_RINGING,
+ RINGTONE,
+ NOTIFICATION_SOUND
};
// Settings moved to Settings.Secure
@@ -3333,7 +3335,9 @@ public final class Settings {
*/
public static final int LOCATION_MODE_SENSORS_ONLY = 1;
/**
- * Reduced power usage, such as limiting the number of GPS updates per hour.
+ * Reduced power usage, such as limiting the number of GPS updates per hour. Requests
+ * with {@link android.location.Criteria#POWER_HIGH} may be downgraded to
+ * {@link android.location.Criteria#POWER_MEDIUM}.
*/
public static final int LOCATION_MODE_BATTERY_SAVING = 2;
/**
@@ -4382,10 +4386,13 @@ public final class Settings {
/**
* Helper method for determining if a location provider is enabled.
+ *
* @param cr the content resolver to use
* @param provider the location provider to query
* @return true if the provider is enabled
- * @deprecated use {@link #getInt(ContentResolver, String)} and {@link #LOCATION_MODE}
+ *
+ * @deprecated use {@link #LOCATION_MODE} or
+ * {@link LocationManager#isProviderEnabled(String)}
*/
@Deprecated
public static final boolean isLocationProviderEnabled(ContentResolver cr, String provider) {
@@ -4398,8 +4405,8 @@ public final class Settings {
* @param provider the location provider to query
* @param userId the userId to query
* @return true if the provider is enabled
- * @deprecated use {@link #getIntForUser(ContentResolver, String, int, int)} and
- * {@link #LOCATION_MODE}
+ * @deprecated use {@link #LOCATION_MODE} or
+ * {@link LocationManager#isProviderEnabled(String)}
* @hide
*/
@Deprecated
diff --git a/core/java/android/speech/RecognizerIntent.java b/core/java/android/speech/RecognizerIntent.java
index 457e66c6dbdd..e991d84807c1 100644
--- a/core/java/android/speech/RecognizerIntent.java
+++ b/core/java/android/speech/RecognizerIntent.java
@@ -55,7 +55,10 @@ public class RecognizerIntent {
* <p>Starting this intent with just {@link Activity#startActivity(Intent)} is not supported.
* You must either use {@link Activity#startActivityForResult(Intent, int)}, or provide a
* PendingIntent, to receive recognition results.
- *
+ *
+ * <p>The implementation of this API is likely to stream audio to remote servers to perform
+ * speech recognition which can use a substantial amount of bandwidth.
+ *
* <p>Required extras:
* <ul>
* <li>{@link #EXTRA_LANGUAGE_MODEL}
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 8fee41d1bcb7..94aedbdf1d6a 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -39,8 +39,14 @@ import java.util.Queue;
* This class provides access to the speech recognition service. This service allows access to the
* speech recognizer. Do not instantiate this class directly, instead, call
* {@link SpeechRecognizer#createSpeechRecognizer(Context)}. This class's methods must be
- * invoked only from the main application thread. Please note that the application must have
- * {@link android.Manifest.permission#RECORD_AUDIO} permission to use this class.
+ * invoked only from the main application thread.
+ *
+ * <p>The implementation of this API is likely to stream audio to remote servers to perform speech
+ * recognition. As such this API is not intended to be used for continuous recognition, which would
+ * consume a significant amount of battery and bandwidth.
+ *
+ * <p>Please note that the application must have {@link android.Manifest.permission#RECORD_AUDIO}
+ * permission to use this class.
*/
public class SpeechRecognizer {
/** DEBUG value to enable verbose debug prints */
diff --git a/core/java/android/speech/hotword/HotwordRecognitionListener.java b/core/java/android/speech/hotword/HotwordRecognitionListener.java
deleted file mode 100644
index 8a32654c5bac..000000000000
--- a/core/java/android/speech/hotword/HotwordRecognitionListener.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (C) 2013 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.speech.hotword;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-/**
- * Used for receiving notifications from the HotwordRecognitionService when the
- * hotword recognition related events occur.
- * All the callbacks are executed on the application main thread.
- * {@hide}
- */
-public interface HotwordRecognitionListener {
- /**
- * Called when the service starts listening for hotword.
- */
- void onHotwordRecognitionStarted();
-
- /**
- * Called when the service stops listening for hotword.
- */
- void onHotwordRecognitionStopped();
-
- /**
- * Called on an event of interest to the client.
- *
- * @param eventType the event type.
- * @param eventBundle a Bundle containing the hotword event(s).
- */
- void onHotwordEvent(int eventType, Bundle eventBundle);
-
- /**
- * Called back when hotword is detected.
- *
- * @param intent for the activity to launch, post hotword detection.
- */
- void onHotwordRecognized(Intent intent);
-
- /**
- * Called when the HotwordRecognitionService encounters an error.
- *
- * @param errorCode the error code describing the error that was encountered.
- */
- void onHotwordError(int errorCode);
-} \ No newline at end of file
diff --git a/core/java/android/speech/hotword/HotwordRecognitionService.java b/core/java/android/speech/hotword/HotwordRecognitionService.java
deleted file mode 100644
index 7a26e0ce87ee..000000000000
--- a/core/java/android/speech/hotword/HotwordRecognitionService.java
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * Copyright (C) 2013 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.speech.hotword;
-
-import android.annotation.SdkConstant;
-import android.annotation.SdkConstant.SdkConstantType;
-import android.app.PendingIntent;
-import android.app.Service;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Message;
-import android.os.RemoteException;
-import android.util.Log;
-
-/**
- * This class provides a base class for hotword detection service implementations.
- * This class should be extended only if you wish to implement a new hotword recognizer.
- */
-public abstract class HotwordRecognitionService extends Service {
- /**
- * The {@link Intent} that must be declared as handled by the service.
- */
- @SdkConstant(SdkConstantType.SERVICE_ACTION)
- public static final String SERVICE_INTERFACE =
- "android.speech.hotword.HotwordRecognitionService";
-
- /** Log messages identifier */
- private static final String TAG = "HotwordRecognitionService";
-
- /** Debugging flag */
- private static final boolean DBG = false;
-
- private static final int MSG_START_RECOGNITION = 1;
- private static final int MSG_STOP_RECOGNITION = 2;
-
- /**
- * The current callback of an application that invoked the
- * {@link HotwordRecognitionService#onStartHotwordRecognition(Callback)} method
- */
- private Callback mCurrentCallback = null;
-
- // Handle the client dying.
- private final IBinder.DeathRecipient mCallbackDeathRecipient = new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- if (DBG) Log.i(TAG, "HotwordRecognitionService listener died");
- mCurrentCallback = null;
- }
- };
-
- private final Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START_RECOGNITION:
- dispatchStartRecognition((IHotwordRecognitionListener) msg.obj);
- break;
- case MSG_STOP_RECOGNITION:
- dispatchStopRecognition((IHotwordRecognitionListener) msg.obj);
- break;
- }
- }
- };
-
- /** Binder of the hotword recognition service */
- private RecognitionServiceBinder mBinder = new RecognitionServiceBinder(this);
-
- private void dispatchStartRecognition(IHotwordRecognitionListener listener) {
- if (mCurrentCallback == null) {
- if (DBG) Log.d(TAG, "created new mCurrentCallback, listener = " + listener.asBinder());
- try {
- listener.asBinder().linkToDeath(mCallbackDeathRecipient, 0);
- } catch (RemoteException e) {
- if (DBG) Log.d(TAG, "listener died before linkToDeath()");
- }
- mCurrentCallback = new Callback(listener);
- HotwordRecognitionService.this.onStartHotwordRecognition(mCurrentCallback);
- } else {
- try {
- listener.onHotwordError(HotwordRecognizer.ERROR_RECOGNIZER_BUSY);
- } catch (RemoteException e) {
- if (DBG) Log.d(TAG, "onError call from startRecognition failed");
- }
- if (DBG) Log.d(TAG, "concurrent startRecognition received - ignoring this call");
- }
- }
-
- private void dispatchStopRecognition(IHotwordRecognitionListener listener) {
- try {
- if (mCurrentCallback == null) {
- listener.onHotwordError(HotwordRecognizer.ERROR_CLIENT);
- Log.w(TAG, "stopRecognition called with no preceding startRecognition - ignoring");
- } else if (mCurrentCallback.mListener.asBinder() != listener.asBinder()) {
- listener.onHotwordError(HotwordRecognizer.ERROR_RECOGNIZER_BUSY);
- Log.w(TAG, "stopRecognition called by a different caller - ignoring");
- } else { // the correct state
- mCurrentCallback.onHotwordRecognitionStopped();
- mCurrentCallback = null;
- HotwordRecognitionService.this.onStopHotwordRecognition();
- }
- } catch (RemoteException e) { // occurs if onError fails
- if (DBG) Log.d(TAG, "onError call from stopRecognition failed");
- }
- }
-
- @Override
- public IBinder onBind(final Intent intent) {
- if (DBG) Log.d(TAG, "onBind, intent=" + intent);
- return mBinder;
- }
-
- @Override
- public void onDestroy() {
- if (DBG) Log.d(TAG, "onDestroy");
- if (mCurrentCallback != null) {
- mCurrentCallback.mListener.asBinder().unlinkToDeath(mCallbackDeathRecipient, 0);
- mCurrentCallback = null;
- }
- mBinder.clearReference();
- super.onDestroy();
- }
-
- /**
- * Notifies the service to start a recognition.
- *
- * @param callback that receives the callbacks from the service.
- */
- public abstract void onStartHotwordRecognition(Callback callback);
-
- /**
- * Notifies the service to stop recognition.
- */
- public abstract void onStopHotwordRecognition();
-
- /** Binder of the hotword recognition service */
- private static class RecognitionServiceBinder extends IHotwordRecognitionService.Stub {
- private HotwordRecognitionService mInternalService;
-
- public RecognitionServiceBinder(HotwordRecognitionService service) {
- mInternalService = service;
- }
-
- public void startHotwordRecognition(IHotwordRecognitionListener listener) {
- if (DBG) Log.d(TAG, "startRecognition called by: " + listener.asBinder());
- if (mInternalService != null && mInternalService.checkPermissions(listener)) {
- mInternalService.mHandler.sendMessage(
- Message.obtain(mInternalService.mHandler, MSG_START_RECOGNITION, listener));
- }
- }
-
- public void stopHotwordRecognition(IHotwordRecognitionListener listener) {
- if (DBG) Log.d(TAG, "stopRecognition called by: " + listener.asBinder());
- if (mInternalService != null && mInternalService.checkPermissions(listener)) {
- mInternalService.mHandler.sendMessage(
- Message.obtain(mInternalService.mHandler, MSG_STOP_RECOGNITION, listener));
- }
- }
-
- private void clearReference() {
- mInternalService = null;
- }
- }
-
- /**
- * Checks whether the caller has sufficient permissions
- *
- * @param listener to send the error message to in case of error.
- * @return {@code true} if the caller has enough permissions, {@code false} otherwise.
- */
- private boolean checkPermissions(IHotwordRecognitionListener listener) {
- if (DBG) Log.d(TAG, "checkPermissions");
- if (checkCallingOrSelfPermission(android.Manifest.permission.HOTWORD_RECOGNITION) ==
- PackageManager.PERMISSION_GRANTED) {
- return true;
- }
- try {
- Log.e(TAG, "Recognition service called without HOTWORD_RECOGNITION permissions");
- listener.onHotwordError(HotwordRecognizer.ERROR_FAILED);
- } catch (RemoteException e) {
- Log.e(TAG, "onHotwordError(ERROR_FAILED) message failed", e);
- }
- return false;
- }
-
- /**
- * This class acts passes on the callbacks received from the Hotword service
- * to the listener.
- */
- public static class Callback {
- private final IHotwordRecognitionListener mListener;
-
- private Callback(IHotwordRecognitionListener listener) {
- mListener = listener;
- }
-
- /**
- * Called when the service starts listening for hotword.
- */
- public void onHotwordRecognitionStarted() throws RemoteException {
- mListener.onHotwordRecognitionStarted();
- }
-
- /**
- * Called when the service starts listening for hotword.
- */
- public void onHotwordRecognitionStopped() throws RemoteException {
- mListener.onHotwordRecognitionStopped();
- }
-
- /**
- * Called on an event of interest to the client.
- *
- * @param eventType the event type.
- * @param eventBundle a Bundle containing the hotword event(s).
- */
- public void onHotwordEvent(int eventType, Bundle eventBundle) throws RemoteException {
- mListener.onHotwordEvent(eventType, eventBundle);
- }
-
- /**
- * Called back when hotword is detected.
- *
- * @param activityIntent for the activity to launch, post hotword detection.
- */
- public void onHotwordRecognized(Intent activityIntent) throws RemoteException {
- mListener.onHotwordRecognized(activityIntent);
- }
-
- /**
- * Called when the HotwordRecognitionService encounters an error.
- *
- * @param errorCode the error code describing the error that was encountered.
- */
- public void onError(int errorCode) throws RemoteException {
- mListener.onHotwordError(errorCode);
- }
- }
-}
diff --git a/core/java/android/speech/hotword/HotwordRecognizer.java b/core/java/android/speech/hotword/HotwordRecognizer.java
deleted file mode 100644
index 939c11d7792f..000000000000
--- a/core/java/android/speech/hotword/HotwordRecognizer.java
+++ /dev/null
@@ -1,395 +0,0 @@
-/*
- * Copyright (C) 2013 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.speech.hotword;
-
-import android.app.PendingIntent;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-import android.content.ServiceConnection;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
-import android.os.RemoteException;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Queue;
-
-/**
- * This class provides access to the Hotword recognition service.
- * This class's methods must be invoked on the main application thread.
- * {@hide}
- */
-public class HotwordRecognizer {
- /** DEBUG value to enable verbose debug prints */
- private final static boolean DBG = false;
-
- /** Log messages identifier */
- private static final String TAG = "HotwordRecognizer";
-
- /**
- * Key used to retrieve a string to be displayed to the user passed to the
- * {@link android.speech.hotword.HotwordRecognitionListener#onHotwordEvent(int, Bundle)} method.
- */
- public static final String PROMPT_TEXT = "prompt_text";
-
- /**
- * Event type used to indicate to the user that the hotword service has changed
- * its state.
- */
- public static final int EVENT_TYPE_STATE_CHANGED = 1;
-
- /** Audio recording error. */
- public static final int ERROR_AUDIO = 1;
-
- /** RecognitionService busy. */
- public static final int ERROR_RECOGNIZER_BUSY = 2;
-
- /** This indicates a permanent failure and the clients shouldn't retry on this */
- public static final int ERROR_FAILED = 3;
-
- /** Client-side errors */
- public static final int ERROR_CLIENT = 4;
-
- /** The service timed out */
- public static final int ERROR_TIMEOUT = 5;
-
- /** The service received concurrent start calls */
- public static final int ERROR_SERVICE_ALREADY_STARTED = 6;
-
- /** Hotword recognition is unavailable on the device */
- public static final int ERROR_UNAVAILABLE = 7;
-
- /** action codes */
- private static final int MSG_START = 1;
- private static final int MSG_STOP = 2;
-
- /** The underlying HotwordRecognitionService endpoint */
- private IHotwordRecognitionService mService;
-
- /** The connection to the actual service */
- private Connection mConnection;
-
- /** Context with which the manager was created */
- private final Context mContext;
-
- /** Component to direct service intent to */
- private final ComponentName mServiceComponent;
-
- /** Handler that will execute the main tasks */
- private Handler mHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_START:
- handleStartRecognition();
- break;
- case MSG_STOP:
- handleStopRecognition();
- break;
- }
- }
- };
-
- /**
- * Temporary queue, saving the messages until the connection will be established, afterwards,
- * only mHandler will receive the messages
- */
- private final Queue<Message> mPendingTasks = new LinkedList<Message>();
-
- /** The Listener that will receive all the callbacks */
- private final InternalListener mListener = new InternalListener();
-
- /**
- * Checks whether a hotword recognition service is available on the system. If this method
- * returns {@code false}, {@link HotwordRecognizer#createHotwordRecognizer(Context)} will
- * fail.
- *
- * @param context with which {@code HotwordRecognizer} will be created
- * @return {@code true} if recognition is available, {@code false} otherwise
- */
- public static boolean isHotwordRecognitionAvailable(final Context context) {
- final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
- new Intent(HotwordRecognitionService.SERVICE_INTERFACE), 0);
- return list != null && list.size() != 0;
- }
-
- /**
- * Factory method to create a new {@code HotwordRecognizer}.
- *
- * @param context in which to create {@code HotwordRecognizer}
- * @return a new {@code HotwordRecognizer}
- */
- public static HotwordRecognizer createHotwordRecognizer(final Context context) {
- ComponentName serviceComponent = null;
- // Resolve to a default ComponentName.
- final List<ResolveInfo> list = context.getPackageManager().queryIntentServices(
- new Intent(HotwordRecognitionService.SERVICE_INTERFACE), 0);
- for (int i = 0; i < list.size(); i++) {
- final ResolveInfo ri = list.get(i);
- if (!ri.serviceInfo.enabled) {
- continue;
- }
- if ((ri.serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM)
- != PackageManager.MATCH_DEFAULT_ONLY) {
- serviceComponent = new ComponentName(
- ri.serviceInfo.packageName, ri.serviceInfo.name);
- break;
- }
- }
- // If all else fails, pick the first one.
- if (serviceComponent == null && !list.isEmpty()) {
- serviceComponent = new ComponentName(
- list.get(0).serviceInfo.packageName, list.get(0).serviceInfo.name);
- }
- return createHotwordRecognizer(context, serviceComponent);
- }
-
- /**
- * Factory method to create a new {@code HotwordRecognizer}.
- *
- * Use this version of the method to specify a specific service to direct this
- * {@link HotwordRecognizer} to. Normally you would not use this; use
- * {@link #createHotwordRecognizer(Context)} instead to use the system default recognition
- * service.
- *
- * @param context in which to create {@code HotwordRecognizer}
- * @param serviceComponent the {@link ComponentName} of a specific service to direct this
- * {@code HotwordRecognizer} to
- * @return a new {@code HotwordRecognizer}
- */
- public static HotwordRecognizer createHotwordRecognizer(
- final Context context, final ComponentName serviceComponent) {
- if (context == null) {
- throw new IllegalArgumentException("Context cannot be null)");
- }
- checkIsCalledFromMainThread();
- return new HotwordRecognizer(context, serviceComponent);
- }
-
- /**
- * Starts recognizing hotword and sets the listener that will receive the callbacks.
- *
- * @param listener listener that will receive all the callbacks from the created
- * {@link HotwordRecognizer}, this must not be null.
- */
- public void startRecognition(HotwordRecognitionListener listener) {
- checkIsCalledFromMainThread();
- if (mConnection == null) { // first time connection
- if (listener == null) {
- throw new IllegalArgumentException("listener must not be null");
- }
-
- mConnection = new Connection();
- Intent serviceIntent = new Intent(HotwordRecognitionService.SERVICE_INTERFACE);
- mListener.mInternalListener = listener;
-
- if (mServiceComponent == null) {
- Log.e(TAG, "no selected voice recognition service");
- mListener.onHotwordError(ERROR_CLIENT);
- return;
- } else {
- serviceIntent.setComponent(mServiceComponent);
- }
-
- if (!mContext.bindService(serviceIntent, mConnection, Context.BIND_AUTO_CREATE)) {
- Log.e(TAG, "bind to recognition service failed");
- mConnection = null;
- mService = null;
- mListener.onHotwordError(ERROR_CLIENT);
- return;
- }
- putMessage(Message.obtain(mHandler, MSG_START));
- } else {
- mListener.onHotwordError(ERROR_SERVICE_ALREADY_STARTED);
- return;
- }
- }
-
- /**
- * Stops recognizing hotword.
- */
- public void stopRecognition() {
- checkIsCalledFromMainThread();
- putMessage(Message.obtain(mHandler, MSG_STOP));
- }
-
- // Private constructor.
- private HotwordRecognizer(Context context, ComponentName serviceComponent) {
- mContext = context;
- mServiceComponent = serviceComponent;
- }
-
- private void handleStartRecognition() {
- if (!checkOpenConnection()) {
- return;
- }
- try {
- mService.startHotwordRecognition(mListener);
- if (DBG) Log.d(TAG, "service startRecognition command succeeded");
- } catch (final RemoteException e) {
- Log.e(TAG, "startRecognition() failed", e);
- mListener.onHotwordError(ERROR_CLIENT);
- }
- }
-
- private void handleStopRecognition() {
- if (!checkOpenConnection()) {
- return;
- }
- try {
- mService.stopHotwordRecognition(mListener);
- if (mConnection != null) {
- mContext.unbindService(mConnection);
- }
- if (DBG) Log.d(TAG, "service stopRecognition command succeeded");
- } catch (final RemoteException e) {
- Log.e(TAG, "stopRecognition() failed", e);
- mListener.onHotwordError(ERROR_CLIENT);
- } finally {
- mPendingTasks.clear();
- mService = null;
- mConnection = null;
- mListener.mInternalListener = null;
- }
- }
-
- private boolean checkOpenConnection() {
- if (mService != null) {
- return true;
- }
- mListener.onHotwordError(ERROR_CLIENT);
- Log.e(TAG, "not connected to the recognition service");
- return false;
- }
-
- private static void checkIsCalledFromMainThread() {
- if (Looper.myLooper() != Looper.getMainLooper()) {
- throw new RuntimeException(
- "HotwordRecognizer should be used only from the application's main thread");
- }
- }
-
- private void putMessage(Message msg) {
- if (mService == null) {
- mPendingTasks.offer(msg);
- } else {
- mHandler.sendMessage(msg);
- }
- }
-
- /**
- * Basic ServiceConnection that records the mService variable.
- * Additionally, on creation it invokes
- * {@link IHotwordRecognitionService#startHotwordRecognition(IHotwordRecognitionListener)}.
- */
- private class Connection implements ServiceConnection {
-
- public void onServiceConnected(final ComponentName name, final IBinder service) {
- // always done on the application main thread, so no need to send message to mHandler
- mService = IHotwordRecognitionService.Stub.asInterface(service);
- if (DBG) Log.d(TAG, "onServiceConnected - Success");
- while (!mPendingTasks.isEmpty()) {
- mHandler.sendMessage(mPendingTasks.poll());
- }
- }
-
- public void onServiceDisconnected(final ComponentName name) {
- // always done on the application main thread, so no need to send message to mHandler
- mService = null;
- mConnection = null;
- mPendingTasks.clear();
- if (DBG) Log.d(TAG, "onServiceDisconnected - Success");
- }
- }
-
- /**
- * Internal wrapper of IHotwordRecognitionListener which will propagate the results to
- * HotwordRecognitionListener.
- */
- private class InternalListener extends IHotwordRecognitionListener.Stub {
- private HotwordRecognitionListener mInternalListener;
-
- private final static int MSG_ON_START = 1;
- private final static int MSG_ON_STOP = 2;
- private final static int MSG_ON_EVENT = 3;
- private final static int MSG_ON_RECOGNIZED = 4;
- private final static int MSG_ON_ERROR = 5;
-
- private final Handler mInternalHandler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (mInternalListener == null) {
- return;
- }
- switch (msg.what) {
- case MSG_ON_START:
- mInternalListener.onHotwordRecognitionStarted();
- break;
- case MSG_ON_STOP:
- mInternalListener.onHotwordRecognitionStopped();
- break;
- case MSG_ON_EVENT:
- mInternalListener.onHotwordEvent(msg.arg1, (Bundle) msg.obj);
- break;
- case MSG_ON_RECOGNIZED:
- mInternalListener.onHotwordRecognized((Intent) msg.obj);
- break;
- case MSG_ON_ERROR:
- mInternalListener.onHotwordError((Integer) msg.obj);
- break;
- }
- }
- };
-
- @Override
- public void onHotwordRecognitionStarted() throws RemoteException {
- Message.obtain(mInternalHandler, MSG_ON_START).sendToTarget();
- }
-
- @Override
- public void onHotwordRecognitionStopped() throws RemoteException {
- Message.obtain(mInternalHandler, MSG_ON_STOP).sendToTarget();
- }
-
- @Override
- public void onHotwordEvent(final int eventType, final Bundle params) {
- Message.obtain(mInternalHandler, MSG_ON_EVENT, eventType, eventType, params)
- .sendToTarget();
- }
-
- @Override
- public void onHotwordRecognized(Intent activityIntent) throws RemoteException {
- Message.obtain(mInternalHandler, MSG_ON_RECOGNIZED, activityIntent)
- .sendToTarget();
- }
-
- @Override
- public void onHotwordError(final int error) {
- Message.obtain(mInternalHandler, MSG_ON_ERROR, error).sendToTarget();
- }
- }
-}
diff --git a/core/java/android/speech/hotword/IHotwordRecognitionListener.aidl b/core/java/android/speech/hotword/IHotwordRecognitionListener.aidl
deleted file mode 100644
index 4ea2e8e0ecfa..000000000000
--- a/core/java/android/speech/hotword/IHotwordRecognitionListener.aidl
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2013 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.speech.hotword;
-
-import android.content.Intent;
-import android.os.Bundle;
-
-/**
- * Listener for hotword detection events.
- * This indicates when the hotword was detected, and also notifies the
- * client of the intermediate events that may be used to show visual feedback
- * to the user.
- * {@hide}
- */
-oneway interface IHotwordRecognitionListener {
- /**
- * Called when the service starts listening for hotword.
- */
- void onHotwordRecognitionStarted();
-
- /**
- * Called when the service starts listening for hotword.
- */
- void onHotwordRecognitionStopped();
-
- /**
- * Called on an event of interest to the client.
- *
- * @param eventType the event type.
- * @param eventBundle a Bundle containing the hotword event(s).
- */
- void onHotwordEvent(in int eventType, in Bundle eventBundle);
-
- /**
- * Called back when hotword is detected.
- *
- * @param intent for the activity to launch, post hotword detection.
- */
- void onHotwordRecognized(in Intent intent);
-
- /**
- * Called when the HotwordRecognitionService encounters an error.
- *
- * @param errorCode the error code describing the error that was encountered.
- */
- void onHotwordError(in int errorCode);
-}
diff --git a/core/java/android/speech/hotword/IHotwordRecognitionService.aidl b/core/java/android/speech/hotword/IHotwordRecognitionService.aidl
deleted file mode 100644
index 331d81cc0c07..000000000000
--- a/core/java/android/speech/hotword/IHotwordRecognitionService.aidl
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2013 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.speech.hotword;
-
-import android.speech.hotword.IHotwordRecognitionListener;
-
-/**
- * A service interface to Hotword recognition.
- * Call startHotwordDetection with a listener when you want to begin detecting
- * hotword;
- * The service would automatically stop detection when hotword is detected;
- * So it's a create-once use-once service.
- * The service doesn't support nested calls to start detection and disallows them.
- * {@hide}
- */
-oneway interface IHotwordRecognitionService {
- /**
- * Start hotword recognition.
- * The clients should rely on the callback to figure out if the detection was
- * started.
- *
- * @param listener a listener to notify of hotword events.
- */
- void startHotwordRecognition(in IHotwordRecognitionListener listener);
-
- /**
- * Stop hotword recognition.
- * Stops the recognition only if it was started by the same caller.
- *
- * @param listener a listener to notify of hotword events.
- */
- void stopHotwordRecognition(in IHotwordRecognitionListener listener);
-}
diff --git a/core/java/android/transition/TextChange.java b/core/java/android/transition/TextChange.java
index 1b26942fe152..4f14d462675d 100644
--- a/core/java/android/transition/TextChange.java
+++ b/core/java/android/transition/TextChange.java
@@ -143,8 +143,8 @@ public class TextChange extends Transition {
final TextView view = (TextView) endValues.view;
Map<String, Object> startVals = startValues.values;
Map<String, Object> endVals = endValues.values;
- final String startText = (String) startVals.get(PROPNAME_TEXT);
- final String endText = (String) endVals.get(PROPNAME_TEXT);
+ final CharSequence startText = (CharSequence) startVals.get(PROPNAME_TEXT);
+ final CharSequence endText = (CharSequence) endVals.get(PROPNAME_TEXT);
if (!startText.equals(endText)) {
view.setText(startText);
Animator anim;
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index 59df183c0528..8ea9d4873ba0 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -122,6 +122,10 @@ public abstract class Transition implements Cloneable {
// Whether this transition is currently paused, due to a call to pause()
boolean mPaused = false;
+ // Whether this transition has ended. Used to avoid pause/resume on transitions
+ // that have completed
+ private boolean mEnded = false;
+
// The set of listeners to be sent transition lifecycle events.
ArrayList<TransitionListener> mListeners = null;
@@ -914,21 +918,23 @@ public abstract class Transition implements Cloneable {
* @hide
*/
public void pause() {
- ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
- int numOldAnims = runningAnimators.size();
- for (int i = numOldAnims - 1; i >= 0; i--) {
- Animator anim = runningAnimators.keyAt(i);
- anim.pause();
- }
- if (mListeners != null && mListeners.size() > 0) {
- ArrayList<TransitionListener> tmpListeners =
- (ArrayList<TransitionListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onTransitionPause(this);
+ if (!mEnded) {
+ ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+ int numOldAnims = runningAnimators.size();
+ for (int i = numOldAnims - 1; i >= 0; i--) {
+ Animator anim = runningAnimators.keyAt(i);
+ anim.pause();
+ }
+ if (mListeners != null && mListeners.size() > 0) {
+ ArrayList<TransitionListener> tmpListeners =
+ (ArrayList<TransitionListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onTransitionPause(this);
+ }
}
+ mPaused = true;
}
- mPaused = true;
}
/**
@@ -940,18 +946,20 @@ public abstract class Transition implements Cloneable {
*/
public void resume() {
if (mPaused) {
- ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
- int numOldAnims = runningAnimators.size();
- for (int i = numOldAnims - 1; i >= 0; i--) {
- Animator anim = runningAnimators.keyAt(i);
- anim.resume();
- }
- if (mListeners != null && mListeners.size() > 0) {
- ArrayList<TransitionListener> tmpListeners =
- (ArrayList<TransitionListener>) mListeners.clone();
- int numListeners = tmpListeners.size();
- for (int i = 0; i < numListeners; ++i) {
- tmpListeners.get(i).onTransitionResume(this);
+ if (!mEnded) {
+ ArrayMap<Animator, AnimationInfo> runningAnimators = getRunningAnimators();
+ int numOldAnims = runningAnimators.size();
+ for (int i = numOldAnims - 1; i >= 0; i--) {
+ Animator anim = runningAnimators.keyAt(i);
+ anim.resume();
+ }
+ if (mListeners != null && mListeners.size() > 0) {
+ ArrayList<TransitionListener> tmpListeners =
+ (ArrayList<TransitionListener>) mListeners.clone();
+ int numListeners = tmpListeners.size();
+ for (int i = 0; i < numListeners; ++i) {
+ tmpListeners.get(i).onTransitionResume(this);
+ }
}
}
mPaused = false;
@@ -1071,6 +1079,7 @@ public abstract class Transition implements Cloneable {
tmpListeners.get(i).onTransitionStart(this);
}
}
+ mEnded = false;
}
mNumInstances++;
}
@@ -1111,6 +1120,7 @@ public abstract class Transition implements Cloneable {
v.setHasTransientState(false);
}
}
+ mEnded = true;
}
}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index ba64f6bfd563..f21518931390 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -34,6 +34,8 @@ import android.os.SystemProperties;
import android.os.Trace;
import android.util.DisplayMetrics;
import android.util.Log;
+import android.view.Surface.OutOfResourcesException;
+
import com.google.android.gles_jni.EGLImpl;
import javax.microedition.khronos.egl.EGL10;
@@ -74,7 +76,7 @@ public abstract class HardwareRenderer {
* System property used to enable or disable dirty regions invalidation.
* This property is only queried if {@link #RENDER_DIRTY_REGIONS} is true.
* The default value of this property is assumed to be true.
- *
+ *
* Possible values:
* "true", to enable partial invalidates
* "false", to disable partial invalidates
@@ -134,7 +136,7 @@ public abstract class HardwareRenderer {
/**
* System property used to debug EGL configuration choice.
- *
+ *
* Possible values:
* "choice", print the chosen configuration only
* "all", print all possible configurations
@@ -147,7 +149,7 @@ public abstract class HardwareRenderer {
* Possible values:
* "true", to enable dirty regions debugging
* "false", to disable dirty regions debugging
- *
+ *
* @hide
*/
public static final String DEBUG_DIRTY_REGIONS_PROPERTY = "debug.hwui.show_dirty_regions";
@@ -208,14 +210,14 @@ public abstract class HardwareRenderer {
/**
* A process can set this flag to false to prevent the use of hardware
* rendering.
- *
+ *
* @hide
*/
public static boolean sRendererDisabled = false;
/**
* Further hardware renderer disabling for the system process.
- *
+ *
* @hide
*/
public static boolean sSystemRendererDisabled = false;
@@ -235,7 +237,7 @@ public abstract class HardwareRenderer {
/**
* Invoke this method to disable hardware rendering in the current process.
- *
+ *
* @hide
*/
public static void disable(boolean system) {
@@ -248,7 +250,7 @@ public abstract class HardwareRenderer {
/**
* Indicates whether hardware acceleration is available under any form for
* the view hierarchy.
- *
+ *
* @return True if the view hierarchy can potentially be hardware accelerated,
* false otherwise
*/
@@ -258,30 +260,30 @@ public abstract class HardwareRenderer {
/**
* Destroys the hardware rendering context.
- *
+ *
* @param full If true, destroys all associated resources.
*/
abstract void destroy(boolean full);
/**
* Initializes the hardware renderer for the specified surface.
- *
+ *
* @param surface The surface to hardware accelerate
- *
+ *
* @return True if the initialization was successful, false otherwise.
*/
- abstract boolean initialize(Surface surface) throws Surface.OutOfResourcesException;
-
+ abstract boolean initialize(Surface surface) throws OutOfResourcesException;
+
/**
* Updates the hardware renderer for the specified surface.
*
* @param surface The surface to hardware accelerate
*/
- abstract void updateSurface(Surface surface) throws Surface.OutOfResourcesException;
+ abstract void updateSurface(Surface surface) throws OutOfResourcesException;
/**
* Destroys the layers used by the specified view hierarchy.
- *
+ *
* @param view The root of the view hierarchy
*/
abstract void destroyLayers(View view);
@@ -289,11 +291,11 @@ public abstract class HardwareRenderer {
/**
* Destroys all hardware rendering resources associated with the specified
* view hierarchy.
- *
+ *
* @param view The root of the view hierarchy
*/
abstract void destroyHardwareResources(View view);
-
+
/**
* This method should be invoked whenever the current hardware renderer
* context should be reset.
@@ -306,7 +308,7 @@ public abstract class HardwareRenderer {
* This method should be invoked to ensure the hardware renderer is in
* valid state (for instance, to ensure the correct EGL context is bound
* to the current thread.)
- *
+ *
* @return true if the renderer is now valid, false otherwise
*/
abstract boolean validate();
@@ -314,7 +316,7 @@ public abstract class HardwareRenderer {
/**
* This method ensures the hardware renderer is in a valid state
* before executing the specified action.
- *
+ *
* This method will attempt to set a valid state even if the window
* the renderer is attached to was destroyed.
*
@@ -325,7 +327,7 @@ public abstract class HardwareRenderer {
/**
* Setup the hardware renderer for drawing. This is called whenever the
* size of the target surface changes or when the surface is first created.
- *
+ *
* @param width Width of the drawing surface.
* @param height Height of the drawing surface.
*/
@@ -384,7 +386,7 @@ public abstract class HardwareRenderer {
/**
* Sets the directory to use as a persistent storage for hardware rendering
* resources.
- *
+ *
* @param cacheDir A directory the current process can write to
*
* @hide
@@ -447,7 +449,7 @@ public abstract class HardwareRenderer {
/**
* Indicates that the specified hardware layer needs to be updated
* as soon as possible.
- *
+ *
* @param layer The hardware layer that needs an update
*
* @see #flushLayerUpdates()
@@ -481,7 +483,7 @@ public abstract class HardwareRenderer {
* Invoked before a view is drawn by a hardware renderer.
* This method can be used to apply transformations to the
* canvas but no drawing command should be issued.
- *
+ *
* @param canvas The Canvas used to render the view.
*/
void onHardwarePreDraw(HardwareCanvas canvas);
@@ -489,7 +491,7 @@ public abstract class HardwareRenderer {
/**
* Invoked after a view is drawn by a hardware renderer.
* It is safe to invoke drawing commands from this method.
- *
+ *
* @param canvas The Canvas used to render the view.
*/
void onHardwarePostDraw(HardwareCanvas canvas);
@@ -509,9 +511,9 @@ public abstract class HardwareRenderer {
/**
* Creates a new display list that can be used to record batches of
* drawing operations.
- *
+ *
* @param name The name of the display list, used for debugging purpose. May be null.
- *
+ *
* @return A new display list.
*
* @hide
@@ -521,20 +523,20 @@ public abstract class HardwareRenderer {
/**
* Creates a new hardware layer. A hardware layer built by calling this
* method will be treated as a texture layer, instead of as a render target.
- *
+ *
* @param isOpaque Whether the layer should be opaque or not
- *
+ *
* @return A hardware layer
*/
abstract HardwareLayer createHardwareLayer(boolean isOpaque);
/**
* Creates a new hardware layer.
- *
+ *
* @param width The minimum width of the layer
* @param height The minimum height of the layer
* @param isOpaque Whether the layer should be opaque or not
- *
+ *
* @return A hardware layer
*/
abstract HardwareLayer createHardwareLayer(int width, int height, boolean isOpaque);
@@ -544,7 +546,7 @@ public abstract class HardwareRenderer {
* specified hardware layer.
*
* @param layer The layer to render into using a {@link android.graphics.SurfaceTexture}
- *
+ *
* @return A {@link SurfaceTexture}
*/
abstract SurfaceTexture createSurfaceTexture(HardwareLayer layer);
@@ -560,11 +562,11 @@ public abstract class HardwareRenderer {
/**
* Detaches the specified functor from the current functor execution queue.
- *
+ *
* @param functor The native functor to remove from the execution queue.
- *
- * @see HardwareCanvas#callDrawGLFunction(int)
- * @see #attachFunctor(android.view.View.AttachInfo, int)
+ *
+ * @see HardwareCanvas#callDrawGLFunction(int)
+ * @see #attachFunctor(android.view.View.AttachInfo, int)
*/
abstract void detachFunctor(int functor);
@@ -591,12 +593,12 @@ public abstract class HardwareRenderer {
* @param width The width of the drawing surface.
* @param height The height of the drawing surface.
* @param surface The surface to hardware accelerate
- *
+ *
* @return true if the surface was initialized, false otherwise. Returning
* false might mean that the surface was already initialized.
*/
boolean initializeIfNeeded(int width, int height, Surface surface)
- throws Surface.OutOfResourcesException {
+ throws OutOfResourcesException {
if (isRequested()) {
// We lost the gl context, so recreate it.
if (!isEnabled()) {
@@ -618,10 +620,10 @@ public abstract class HardwareRenderer {
/**
* Creates a hardware renderer using OpenGL.
- *
+ *
* @param glVersion The version of OpenGL to use (1 for OpenGL 1, 11 for OpenGL 1.1, etc.)
* @param translucent True if the surface is translucent, false otherwise
- *
+ *
* @return A hardware renderer backed by OpenGL.
*/
static HardwareRenderer createGlRenderer(int glVersion, boolean translucent) {
@@ -636,7 +638,7 @@ public abstract class HardwareRenderer {
* Invoke this method when the system is running out of memory. This
* method will attempt to recover as much memory as possible, based on
* the specified hint.
- *
+ *
* @param level Hint about the amount of memory that should be trimmed,
* see {@link android.content.ComponentCallbacks}
*/
@@ -649,7 +651,7 @@ public abstract class HardwareRenderer {
* Starts the process of trimming memory. Usually this call will setup
* hardware rendering context and reclaim memory.Extra cleanup might
* be required by calling {@link #endTrimMemory()}.
- *
+ *
* @param level Hint about the amount of memory that should be trimmed,
* see {@link android.content.ComponentCallbacks}
*/
@@ -667,7 +669,7 @@ public abstract class HardwareRenderer {
/**
* Indicates whether hardware acceleration is currently enabled.
- *
+ *
* @return True if hardware acceleration is in use, false otherwise.
*/
boolean isEnabled() {
@@ -676,7 +678,7 @@ public abstract class HardwareRenderer {
/**
* Indicates whether hardware acceleration is currently enabled.
- *
+ *
* @param enabled True if the hardware renderer is in use, false otherwise.
*/
void setEnabled(boolean enabled) {
@@ -686,7 +688,7 @@ public abstract class HardwareRenderer {
/**
* Indicates whether hardware acceleration is currently request but not
* necessarily enabled yet.
- *
+ *
* @return True if requested, false otherwise.
*/
boolean isRequested() {
@@ -696,7 +698,7 @@ public abstract class HardwareRenderer {
/**
* Indicates whether hardware acceleration is currently requested but not
* necessarily enabled yet.
- *
+ *
* @return True to request hardware acceleration, false otherwise.
*/
void setRequested(boolean requested) {
@@ -837,7 +839,7 @@ public abstract class HardwareRenderer {
Thread mEglThread;
EGLSurface mEglSurface;
-
+
GL mGl;
HardwareCanvas mCanvas;
@@ -1050,7 +1052,7 @@ public abstract class HardwareRenderer {
}
@Override
- boolean initialize(Surface surface) throws Surface.OutOfResourcesException {
+ boolean initialize(Surface surface) throws OutOfResourcesException {
if (isRequested() && !isEnabled()) {
boolean contextCreated = initializeEgl();
mGl = createEglSurface(surface);
@@ -1078,9 +1080,9 @@ public abstract class HardwareRenderer {
}
return false;
}
-
+
@Override
- void updateSurface(Surface surface) throws Surface.OutOfResourcesException {
+ void updateSurface(Surface surface) throws OutOfResourcesException {
if (isRequested() && isEnabled()) {
createEglSurface(surface);
}
@@ -1094,15 +1096,15 @@ public abstract class HardwareRenderer {
synchronized (sEglLock) {
if (sEgl == null && sEglConfig == null) {
sEgl = (EGL10) EGLContext.getEGL();
-
+
// Get to the default display.
sEglDisplay = sEgl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
-
+
if (sEglDisplay == EGL_NO_DISPLAY) {
throw new RuntimeException("eglGetDisplay failed "
+ GLUtils.getEGLErrorString(sEgl.eglGetError()));
}
-
+
// We can now initialize EGL for that display
int[] version = new int[2];
if (!sEgl.eglInitialize(sEglDisplay, version)) {
@@ -1216,7 +1218,7 @@ public abstract class HardwareRenderer {
Log.d(LOG_TAG, " CONFIG_CAVEAT = 0x" + Integer.toHexString(value[0]));
}
- GL createEglSurface(Surface surface) throws Surface.OutOfResourcesException {
+ GL createEglSurface(Surface surface) throws OutOfResourcesException {
// Check preconditions.
if (sEgl == null) {
throw new RuntimeException("egl not initialized");
@@ -1228,7 +1230,7 @@ public abstract class HardwareRenderer {
throw new RuntimeException("eglConfig not initialized");
}
if (Thread.currentThread() != mEglThread) {
- throw new IllegalStateException("HardwareRenderer cannot be used "
+ throw new IllegalStateException("HardwareRenderer cannot be used "
+ "from multiple threads");
}
@@ -1394,8 +1396,8 @@ public abstract class HardwareRenderer {
boolean canDraw() {
return mGl != null && mCanvas != null;
- }
-
+ }
+
int onPreDraw(Rect dirty) {
return DisplayList.STATUS_DONE;
}
@@ -1732,7 +1734,7 @@ public abstract class HardwareRenderer {
* Ensures the current EGL context and surface are the ones we expect.
* This method throws an IllegalStateException if invoked from a thread
* that did not initialize EGL.
- *
+ *
* @return {@link #SURFACE_STATE_ERROR} if the correct EGL context cannot be made current,
* {@link #SURFACE_STATE_UPDATED} if the EGL context was changed or
* {@link #SURFACE_STATE_SUCCESS} if the EGL context was the correct one
diff --git a/core/java/android/view/IApplicationToken.aidl b/core/java/android/view/IApplicationToken.aidl
index 5f0600f9e566..633b40fb7967 100644
--- a/core/java/android/view/IApplicationToken.aidl
+++ b/core/java/android/view/IApplicationToken.aidl
@@ -23,7 +23,7 @@ interface IApplicationToken
void windowsDrawn();
void windowsVisible();
void windowsGone();
- boolean keyDispatchingTimedOut();
+ boolean keyDispatchingTimedOut(String reason);
long getKeyDispatchingTimeout();
}
diff --git a/core/java/android/view/InputDevice.java b/core/java/android/view/InputDevice.java
index afc7b3e789a6..e8291160a7f8 100644
--- a/core/java/android/view/InputDevice.java
+++ b/core/java/android/view/InputDevice.java
@@ -424,12 +424,17 @@ public final class InputDevice implements Parcelable {
/**
* The controller number for a given input device.
* <p>
- * Each game controller or joystick is given a unique controller number when initially
- * configured by the system. The number is not stable and may be changed by the system at any
- * point. All controller numbers will be non-negative. A game controller or joystick will be
- * given a unique number indexed from one; everything else will be assigned a controller number
+ * Each gamepad or joystick is given a unique, positive controller number when initially
+ * configured by the system. This number may change due to events such as device disconnects /
+ * reconnects or user initiated reassignment. Any change in number will trigger an event that
+ * can be observed by registering an {@link InputManager.InputDeviceListener}.
+ * </p>
+ * <p>
+ * All input devices which are not gamepads or joysticks will be assigned a controller number
* of 0.
* </p>
+ *
+ * @return The controller number of the device.
*/
public int getControllerNumber() {
return mControllerNumber;
diff --git a/core/java/android/view/ScaleGestureDetector.java b/core/java/android/view/ScaleGestureDetector.java
index 0bebc04f304f..a0d39ca9c9ec 100644
--- a/core/java/android/view/ScaleGestureDetector.java
+++ b/core/java/android/view/ScaleGestureDetector.java
@@ -159,6 +159,7 @@ public class ScaleGestureDetector {
private static final long TOUCH_STABILIZE_TIME = 128; // ms
private static final int DOUBLE_TAP_MODE_NONE = 0;
private static final int DOUBLE_TAP_MODE_IN_PROGRESS = 1;
+ private static final float SCALE_FACTOR = .5f;
/**
@@ -197,7 +198,7 @@ public class ScaleGestureDetector {
* @throws NullPointerException if {@code listener} is null.
*/
public ScaleGestureDetector(Context context, OnScaleGestureListener listener,
- Handler handler) {
+ Handler handler) {
mContext = context;
mListener = listener;
mSpanSlop = ViewConfiguration.get(context).getScaledTouchSlop() * 2;
@@ -409,7 +410,9 @@ public class ScaleGestureDetector {
mPrevSpanY = mCurrSpanY = spanY;
mInitialSpan = mPrevSpan = mCurrSpan = span;
}
- if (!mInProgress && span >= mMinSpan &&
+
+ final int minSpan = inDoubleTapMode() ? mSpanSlop : mMinSpan;
+ if (!mInProgress && span >= minSpan &&
(wasInProgress || Math.abs(span - mInitialSpan) > mSpanSlop)) {
mPrevSpanX = mCurrSpanX = spanX;
mPrevSpanY = mCurrSpanY = spanY;
@@ -464,7 +467,7 @@ public class ScaleGestureDetector {
mDoubleTapMode = DOUBLE_TAP_MODE_IN_PROGRESS;
return true;
}
- };
+ };
mGestureDetector = new GestureDetector(mContext, gestureListener, mHandler);
}
}
@@ -572,11 +575,15 @@ public class ScaleGestureDetector {
* @return The current scaling factor.
*/
public float getScaleFactor() {
- if (inDoubleTapMode() && mEventBeforeOrAboveStartingGestureEvent) {
+ if (inDoubleTapMode()) {
// Drag is moving up; the further away from the gesture
// start, the smaller the span should be, the closer,
// the larger the span, and therefore the larger the scale
- return (1 / mCurrSpan) / (1 / mPrevSpan);
+ final boolean scaleUp =
+ (mEventBeforeOrAboveStartingGestureEvent && (mCurrSpan < mPrevSpan)) ||
+ (!mEventBeforeOrAboveStartingGestureEvent && (mCurrSpan > mPrevSpan));
+ final float spanDiff = (Math.abs(1 - (mCurrSpan / mPrevSpan)) * SCALE_FACTOR);
+ return mPrevSpan <= 0 ? 1 : scaleUp ? (1 + spanDiff) : (1 - spanDiff);
}
return mPrevSpan > 0 ? mCurrSpan / mPrevSpan : 1;
}
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 409db8494506..1bfda2d9a45a 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -116,6 +116,7 @@ public class Surface implements Parcelable {
*
* @param surfaceTexture The {@link SurfaceTexture} that is updated by this
* Surface.
+ * @throws OutOfResourcesException if the surface could not be created.
*/
public Surface(SurfaceTexture surfaceTexture) {
if (surfaceTexture == null) {
@@ -124,12 +125,7 @@ public class Surface implements Parcelable {
synchronized (mLock) {
mName = surfaceTexture.toString();
- try {
- setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
- } catch (OutOfResourcesException ex) {
- // We can't throw OutOfResourcesException because it would be an API change.
- throw new RuntimeException(ex);
- }
+ setNativeObjectLocked(nativeCreateFromSurfaceTexture(surfaceTexture));
}
}
@@ -229,9 +225,12 @@ public class Surface implements Parcelable {
* The caller may also pass <code>null</code> instead, in the case where the
* entire surface should be redrawn.
* @return A canvas for drawing into the surface.
+ *
+ * @throws IllegalArgumentException If the inOutDirty rectangle is not valid.
+ * @throws OutOfResourcesException If the canvas cannot be locked.
*/
public Canvas lockCanvas(Rect inOutDirty)
- throws OutOfResourcesException, IllegalArgumentException {
+ throws Surface.OutOfResourcesException, IllegalArgumentException {
synchronized (mLock) {
checkNotReleasedLocked();
if (mLockedObject != 0) {
@@ -239,7 +238,7 @@ public class Surface implements Parcelable {
// double-lock, but that won't happen if mNativeObject was updated. We can't
// abandon the old mLockedObject because it might still be in use, so instead
// we just refuse to re-lock the Surface.
- throw new RuntimeException("Surface was already locked");
+ throw new IllegalStateException("Surface was already locked");
}
mLockedObject = nativeLockCanvas(mNativeObject, mCanvas, inOutDirty);
return mCanvas;
@@ -266,7 +265,7 @@ public class Surface implements Parcelable {
Integer.toHexString(mLockedObject) +")");
}
if (mLockedObject == 0) {
- throw new RuntimeException("Surface was not locked");
+ throw new IllegalStateException("Surface was not locked");
}
nativeUnlockCanvasAndPost(mLockedObject, canvas);
nativeRelease(mLockedObject);
@@ -411,9 +410,11 @@ public class Surface implements Parcelable {
}
/**
- * Exception thrown when a surface couldn't be created or resized.
+ * Exception thrown when a Canvas couldn't be locked with {@link Surface#lockCanvas}, or
+ * when a SurfaceTexture could not successfully be allocated.
*/
- public static class OutOfResourcesException extends Exception {
+ @SuppressWarnings("serial")
+ public static class OutOfResourcesException extends RuntimeException {
public OutOfResourcesException() {
}
public OutOfResourcesException(String name) {
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index dc31e0b91342..b22d5cf32af5 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -24,6 +24,7 @@ import android.view.Surface;
import android.os.IBinder;
import android.os.SystemProperties;
import android.util.Log;
+import android.view.Surface.OutOfResourcesException;
/**
* SurfaceControl
@@ -75,23 +76,12 @@ public class SurfaceControl {
private final CloseGuard mCloseGuard = CloseGuard.get();
- private String mName;
+ private final String mName;
int mNativeObject; // package visibility only for Surface.java access
private static final boolean HEADLESS = "1".equals(
SystemProperties.get("ro.config.headless", "0"));
- /**
- * Exception thrown when a surface couldn't be created or resized.
- */
- public static class OutOfResourcesException extends Exception {
- public OutOfResourcesException() {
- }
- public OutOfResourcesException(String name) {
- super(name);
- }
- }
-
/* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
/**
@@ -220,6 +210,8 @@ public class SurfaceControl {
* @param h The surface initial height.
* @param flags The surface creation flags. Should always include {@link #HIDDEN}
* in the creation flags.
+ *
+ * @throws throws OutOfResourcesException If the SurfaceControl cannot be created.
*/
public SurfaceControl(SurfaceSession session,
String name, int w, int h, int format, int flags)
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 8b2b556d0524..1e4b29f7a064 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -43,7 +43,7 @@ import java.util.concurrent.locks.ReentrantLock;
* You can control the format of this surface and, if you like, its size; the
* SurfaceView takes care of placing the surface at the correct location on the
* screen
- *
+ *
* <p>The surface is Z ordered so that it is behind the window holding its
* SurfaceView; the SurfaceView punches a hole in its window to allow its
* surface to be displayed. The view hierarchy will take care of correctly
@@ -52,7 +52,7 @@ import java.util.concurrent.locks.ReentrantLock;
* buttons on top of the Surface, though note however that it can have an
* impact on performance since a full alpha-blended composite will be performed
* each time the Surface changes.
- *
+ *
* <p> The transparent region that makes the surface visible is based on the
* layout positions in the view hierarchy. If the post-layout transform
* properties are used to draw a sibling view on top of the SurfaceView, the
@@ -60,16 +60,16 @@ import java.util.concurrent.locks.ReentrantLock;
*
* <p>Access to the underlying surface is provided via the SurfaceHolder interface,
* which can be retrieved by calling {@link #getHolder}.
- *
+ *
* <p>The Surface will be created for you while the SurfaceView's window is
* visible; you should implement {@link SurfaceHolder.Callback#surfaceCreated}
* and {@link SurfaceHolder.Callback#surfaceDestroyed} to discover when the
* Surface is created and destroyed as the window is shown and hidden.
- *
+ *
* <p>One of the purposes of this class is to provide a surface in which a
* secondary thread can render into the screen. If you are going to use it
* this way, you need to be aware of some threading semantics:
- *
+ *
* <ul>
* <li> All SurfaceView and
* {@link SurfaceHolder.Callback SurfaceHolder.Callback} methods will be called
@@ -91,7 +91,7 @@ public class SurfaceView extends View {
= new ArrayList<SurfaceHolder.Callback>();
final int[] mLocation = new int[2];
-
+
final ReentrantLock mSurfaceLock = new ReentrantLock();
final Surface mSurface = new Surface(); // Current surface in use
final Surface mNewSurface = new Surface(); // New surface we are switching to
@@ -106,13 +106,13 @@ public class SurfaceView extends View {
final Rect mOverscanInsets = new Rect();
final Rect mContentInsets = new Rect();
final Configuration mConfiguration = new Configuration();
-
+
static final int KEEP_SCREEN_ON_MSG = 1;
static final int GET_NEW_SURFACE_MSG = 2;
static final int UPDATE_WINDOW_MSG = 3;
-
+
int mWindowType = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
-
+
boolean mIsCreating = false;
final Handler mHandler = new Handler() {
@@ -131,14 +131,15 @@ public class SurfaceView extends View {
}
}
};
-
+
final ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
= new ViewTreeObserver.OnScrollChangedListener() {
+ @Override
public void onScrollChanged() {
updateWindow(false, false);
}
};
-
+
boolean mRequestedVisible = false;
boolean mWindowVisibility = false;
boolean mViewVisibility = false;
@@ -152,7 +153,7 @@ public class SurfaceView extends View {
boolean mHaveFrame = false;
boolean mSurfaceCreated = false;
long mLastLockTime = 0;
-
+
boolean mVisible = false;
int mLeft = -1;
int mTop = -1;
@@ -169,7 +170,7 @@ public class SurfaceView extends View {
new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
- // reposition ourselves where the surface is
+ // reposition ourselves where the surface is
mHaveFrame = getWidth() > 0 && getHeight() > 0;
updateWindow(false, false);
return true;
@@ -181,7 +182,7 @@ public class SurfaceView extends View {
super(context);
init();
}
-
+
public SurfaceView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
@@ -195,11 +196,11 @@ public class SurfaceView extends View {
private void init() {
setWillNotDraw(true);
}
-
+
/**
* Return the SurfaceHolder providing access and control over this
* SurfaceView's underlying surface.
- *
+ *
* @return SurfaceHolder The holder of the surface.
*/
public SurfaceHolder getHolder() {
@@ -285,7 +286,7 @@ public class SurfaceView extends View {
: getDefaultSize(0, heightMeasureSpec);
setMeasuredDimension(width, height);
}
-
+
/** @hide */
@Override
protected boolean setFrame(int left, int top, int right, int bottom) {
@@ -299,7 +300,7 @@ public class SurfaceView extends View {
if (mWindowType == WindowManager.LayoutParams.TYPE_APPLICATION_PANEL) {
return super.gatherTransparentRegion(region);
}
-
+
boolean opaque = true;
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == 0) {
// this view draws, remove it from the transparent region
@@ -350,10 +351,10 @@ public class SurfaceView extends View {
* regular surface view in the window (but still behind the window itself).
* This is typically used to place overlays on top of an underlying media
* surface view.
- *
+ *
* <p>Note that this must be set before the surface view's containing
* window is attached to the window manager.
- *
+ *
* <p>Calling this overrides any previous call to {@link #setZOrderOnTop}.
*/
public void setZOrderMediaOverlay(boolean isMediaOverlay) {
@@ -361,7 +362,7 @@ public class SurfaceView extends View {
? WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY
: WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
}
-
+
/**
* Control whether the surface view's surface is placed on top of its
* window. Normally it is placed behind the window, to allow it to
@@ -369,10 +370,10 @@ public class SurfaceView extends View {
* hierarchy. By setting this, you cause it to be placed above the
* window. This means that none of the contents of the window this
* SurfaceView is in will be visible on top of its surface.
- *
+ *
* <p>Note that this must be set before the surface view's containing
* window is attached to the window manager.
- *
+ *
* <p>Calling this overrides any previous call to {@link #setZOrderMediaOverlay}.
*/
public void setZOrderOnTop(boolean onTop) {
@@ -427,7 +428,7 @@ public class SurfaceView extends View {
if (mTranslator != null) {
mSurface.setCompatibilityTranslator(mTranslator);
}
-
+
int myWidth = mRequestedWidth;
if (myWidth <= 0) myWidth = getWidth();
int myHeight = mRequestedHeight;
@@ -458,7 +459,7 @@ public class SurfaceView extends View {
mFormat = mRequestedFormat;
// Scaling/Translate window's layout here because mLayout is not used elsewhere.
-
+
// Places the window relative
mLayout.x = mLeft;
mLayout.y = mTop;
@@ -467,7 +468,7 @@ public class SurfaceView extends View {
if (mTranslator != null) {
mTranslator.translateLayoutParamsInAppWindowToScreen(mLayout);
}
-
+
mLayout.format = mRequestedFormat;
mLayout.flags |=WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
@@ -489,7 +490,7 @@ public class SurfaceView extends View {
mSession.addToDisplayWithoutInputChannel(mWindow, mWindow.mSeq, mLayout,
mVisible ? VISIBLE : GONE, display.getDisplayId(), mContentInsets);
}
-
+
boolean realSizeChanged;
boolean reportDrawNeeded;
@@ -501,7 +502,7 @@ public class SurfaceView extends View {
reportDrawNeeded = mReportDrawNeeded;
mReportDrawNeeded = false;
mDrawingStopped = !visible;
-
+
if (DEBUG) Log.i(TAG, "Cur surface: " + mSurface);
relayoutResult = mSession.relayout(
@@ -527,7 +528,7 @@ public class SurfaceView extends View {
mSurfaceFrame.right = (int) (mWinFrame.width() * appInvertedScale + 0.5f);
mSurfaceFrame.bottom = (int) (mWinFrame.height() * appInvertedScale + 0.5f);
}
-
+
final int surfaceWidth = mSurfaceFrame.right;
final int surfaceHeight = mSurfaceFrame.bottom;
realSizeChanged = mLastSurfaceWidth != surfaceWidth
@@ -667,10 +668,12 @@ public class SurfaceView extends View {
}
}
+ @Override
public void dispatchAppVisibility(boolean visible) {
// The point of SurfaceView is to let the app control the surface.
}
+ @Override
public void dispatchGetNewSurface() {
SurfaceView surfaceView = mSurfaceView.get();
if (surfaceView != null) {
@@ -679,10 +682,12 @@ public class SurfaceView extends View {
}
}
+ @Override
public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
Log.w("SurfaceView", "Unexpected focus in surface: focus=" + hasFocus + ", touchEnabled=" + touchEnabled);
}
+ @Override
public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
}
@@ -690,30 +695,34 @@ public class SurfaceView extends View {
int mCurHeight = -1;
}
- private SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
-
+ private final SurfaceHolder mSurfaceHolder = new SurfaceHolder() {
+
private static final String LOG_TAG = "SurfaceHolder";
-
+
+ @Override
public boolean isCreating() {
return mIsCreating;
}
+ @Override
public void addCallback(Callback callback) {
synchronized (mCallbacks) {
- // This is a linear search, but in practice we'll
+ // This is a linear search, but in practice we'll
// have only a couple callbacks, so it doesn't matter.
- if (mCallbacks.contains(callback) == false) {
+ if (mCallbacks.contains(callback) == false) {
mCallbacks.add(callback);
}
}
}
+ @Override
public void removeCallback(Callback callback) {
synchronized (mCallbacks) {
mCallbacks.remove(callback);
}
}
-
+
+ @Override
public void setFixedSize(int width, int height) {
if (mRequestedWidth != width || mRequestedHeight != height) {
mRequestedWidth = width;
@@ -722,6 +731,7 @@ public class SurfaceView extends View {
}
}
+ @Override
public void setSizeFromLayout() {
if (mRequestedWidth != -1 || mRequestedHeight != -1) {
mRequestedWidth = mRequestedHeight = -1;
@@ -729,6 +739,7 @@ public class SurfaceView extends View {
}
}
+ @Override
public void setFormat(int format) {
// for backward compatibility reason, OPAQUE always
@@ -745,15 +756,17 @@ public class SurfaceView extends View {
/**
* @deprecated setType is now ignored.
*/
+ @Override
@Deprecated
public void setType(int type) { }
+ @Override
public void setKeepScreenOn(boolean screenOn) {
Message msg = mHandler.obtainMessage(KEEP_SCREEN_ON_MSG);
msg.arg1 = screenOn ? 1 : 0;
mHandler.sendMessage(msg);
}
-
+
/**
* Gets a {@link Canvas} for drawing into the SurfaceView's Surface
*
@@ -763,6 +776,7 @@ public class SurfaceView extends View {
* The caller must redraw the entire surface.
* @return A canvas for drawing into the surface.
*/
+ @Override
public Canvas lockCanvas() {
return internalLockCanvas(null);
}
@@ -782,6 +796,7 @@ public class SurfaceView extends View {
* entire surface should be redrawn.
* @return A canvas for drawing into the surface.
*/
+ @Override
public Canvas lockCanvas(Rect inOutDirty) {
return internalLockCanvas(inOutDirty);
}
@@ -806,7 +821,7 @@ public class SurfaceView extends View {
mLastLockTime = SystemClock.uptimeMillis();
return c;
}
-
+
// If the Surface is not ready to be drawn, then return null,
// but throttle calls to this function so it isn't called more
// than every 100ms.
@@ -821,7 +836,7 @@ public class SurfaceView extends View {
}
mLastLockTime = now;
mSurfaceLock.unlock();
-
+
return null;
}
@@ -831,15 +846,18 @@ public class SurfaceView extends View {
*
* @param canvas The canvas previously obtained from {@link #lockCanvas}.
*/
+ @Override
public void unlockCanvasAndPost(Canvas canvas) {
mSurface.unlockCanvasAndPost(canvas);
mSurfaceLock.unlock();
}
+ @Override
public Surface getSurface() {
return mSurface;
}
+ @Override
public Rect getSurfaceFrame() {
return mSurfaceFrame;
}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 8616aba39f71..30531edb87ca 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9546,9 +9546,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setPivotX(float pivotX) {
ensureTransformationInfo();
- mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
final TransformationInfo info = mTransformationInfo;
- if (info.mPivotX != pivotX) {
+ boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) ==
+ PFLAG_PIVOT_EXPLICITLY_SET;
+ if (info.mPivotX != pivotX || !pivotSet) {
+ mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
invalidateViewProperty(true, false);
info.mPivotX = pivotX;
info.mMatrixDirty = true;
@@ -9596,9 +9598,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
public void setPivotY(float pivotY) {
ensureTransformationInfo();
- mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
final TransformationInfo info = mTransformationInfo;
- if (info.mPivotY != pivotY) {
+ boolean pivotSet = (mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) ==
+ PFLAG_PIVOT_EXPLICITLY_SET;
+ if (info.mPivotY != pivotY || !pivotSet) {
+ mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
invalidateViewProperty(true, false);
info.mPivotY = pivotY;
info.mMatrixDirty = true;
@@ -13476,6 +13480,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
// Fast path for layouts with no backgrounds
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
dispatchDraw(canvas);
+ if (mOverlay != null && !mOverlay.isEmpty()) {
+ mOverlay.getOverlayView().draw(canvas);
+ }
} else {
draw(canvas);
}
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index ed128b073156..92e5e964fd34 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -698,6 +698,11 @@ public class ViewDebug {
captureViewLayer(group.getChildAt(i), clientStream, localVisible);
}
}
+
+ if (view.mOverlay != null) {
+ ViewGroup overlayContainer = view.getOverlay().mOverlayViewGroup;
+ captureViewLayer(overlayContainer, clientStream, localVisible);
+ }
}
private static void outputDisplayList(View root, String parameter) throws IOException {
@@ -743,7 +748,7 @@ public class ViewDebug {
}
}
- private static Bitmap performViewCapture(final View captureView, final boolean skpiChildren) {
+ private static Bitmap performViewCapture(final View captureView, final boolean skipChildren) {
if (captureView != null) {
final CountDownLatch latch = new CountDownLatch(1);
final Bitmap[] cache = new Bitmap[1];
@@ -752,7 +757,7 @@ public class ViewDebug {
public void run() {
try {
cache[0] = captureView.createSnapshot(
- Bitmap.Config.ARGB_8888, 0, skpiChildren);
+ Bitmap.Config.ARGB_8888, 0, skipChildren);
} catch (OutOfMemoryError e) {
Log.w("View", "Out of memory for bitmap");
} finally {
@@ -815,6 +820,13 @@ public class ViewDebug {
} else if (isRequestedView(view, className, hashCode)) {
return view;
}
+ if (view.mOverlay != null) {
+ final View found = findView((ViewGroup) view.mOverlay.mOverlayViewGroup,
+ className, hashCode);
+ if (found != null) {
+ return found;
+ }
+ }
if (view instanceof HierarchyHandler) {
final View found = ((HierarchyHandler)view)
.findHierarchyView(className, hashCode);
@@ -823,12 +835,19 @@ public class ViewDebug {
}
}
}
-
return null;
}
private static boolean isRequestedView(View view, String className, int hashCode) {
- return view.getClass().getName().equals(className) && view.hashCode() == hashCode;
+ if (view.hashCode() == hashCode) {
+ String viewClassName = view.getClass().getName();
+ if (className.equals("ViewOverlay")) {
+ return viewClassName.equals("android.view.ViewOverlay$OverlayViewGroup");
+ } else {
+ return className.equals(viewClassName);
+ }
+ }
+ return false;
}
private static void dumpViewHierarchy(Context context, ViewGroup group,
@@ -850,6 +869,12 @@ public class ViewDebug {
} else {
dumpView(context, view, out, level + 1, includeProperties);
}
+ if (view.mOverlay != null) {
+ ViewOverlay overlay = view.getOverlay();
+ ViewGroup overlayContainer = overlay.mOverlayViewGroup;
+ dumpViewHierarchy(context, overlayContainer, out, level + 2, skipChildren,
+ includeProperties);
+ }
}
if (group instanceof HierarchyHandler) {
((HierarchyHandler)group).dumpViewHierarchyWithProperties(out, level + 1);
@@ -863,7 +888,11 @@ public class ViewDebug {
for (int i = 0; i < level; i++) {
out.write(' ');
}
- out.write(view.getClass().getName());
+ String className = view.getClass().getName();
+ if (className.equals("android.view.ViewOverlay$OverlayViewGroup")) {
+ className = "ViewOverlay";
+ }
+ out.write(className);
out.write('@');
out.write(Integer.toHexString(view.hashCode()));
out.write(' ');
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index e6bf420acccc..107d2c606617 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -93,11 +93,16 @@ public class ViewPropertyAnimator {
private boolean mInterpolatorSet = false;
/**
- * Listener for the lifecycle events of the underlying
+ * Listener for the lifecycle events of the underlying ValueAnimator object.
*/
private Animator.AnimatorListener mListener = null;
/**
+ * Listener for the update events of the underlying ValueAnimator object.
+ */
+ private ValueAnimator.AnimatorUpdateListener mUpdateListener = null;
+
+ /**
* A lazily-created ValueAnimator used in order to get some default animator properties
* (duration, start delay, interpolator, etc.).
*/
@@ -353,7 +358,10 @@ public class ViewPropertyAnimator {
* Sets a listener for events in the underlying Animators that run the property
* animations.
*
- * @param listener The listener to be called with AnimatorListener events.
+ * @see Animator.AnimatorListener
+ *
+ * @param listener The listener to be called with AnimatorListener events. A value of
+ * <code>null</code> removes any existing listener.
* @return This object, allowing calls to methods in this class to be chained.
*/
public ViewPropertyAnimator setListener(Animator.AnimatorListener listener) {
@@ -362,6 +370,25 @@ public class ViewPropertyAnimator {
}
/**
+ * Sets a listener for update events in the underlying ValueAnimator that runs
+ * the property animations. Note that the underlying animator is animating between
+ * 0 and 1 (these values are then turned into the actual property values internally
+ * by ViewPropertyAnimator). So the animator cannot give information on the current
+ * values of the properties being animated by this ViewPropertyAnimator, although
+ * the view object itself can be queried to get the current values.
+ *
+ * @see android.animation.ValueAnimator.AnimatorUpdateListener
+ *
+ * @param listener The listener to be called with update events. A value of
+ * <code>null</code> removes any existing listener.
+ * @return This object, allowing calls to methods in this class to be chained.
+ */
+ public ViewPropertyAnimator setUpdateListener(ValueAnimator.AnimatorUpdateListener listener) {
+ mUpdateListener = listener;
+ return this;
+ }
+
+ /**
* Starts the currently pending property animations immediately. Calling <code>start()</code>
* is optional because all animations start automatically at the next opportunity. However,
* if the animations are needed to start immediately and synchronously (not at the time when
@@ -675,6 +702,7 @@ public class ViewPropertyAnimator {
@Override
public void run() {
mView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
+ mView.buildLayer();
}
};
final int currentLayerType = mView.getLayerType();
@@ -1073,6 +1101,9 @@ public class ViewPropertyAnimator {
} else {
mView.invalidateViewProperty(false, false);
}
+ if (mUpdateListener != null) {
+ mUpdateListener.onAnimationUpdate(animation);
+ }
}
}
}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index c7d61eb0f683..50d5d4598824 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -68,6 +68,7 @@ import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.view.inputmethod.InputConnection;
import android.view.inputmethod.InputMethodManager;
+import android.view.Surface.OutOfResourcesException;
import android.widget.Scroller;
import com.android.internal.R;
@@ -187,7 +188,7 @@ public final class ViewRootImpl implements ViewParent,
InputQueue mInputQueue;
FallbackEventHandler mFallbackEventHandler;
Choreographer mChoreographer;
-
+
final Rect mTempRect; // used in the transaction to not thrash the heap.
final Rect mVisRect; // used to retrieve visible rect of focused view.
@@ -278,8 +279,8 @@ public final class ViewRootImpl implements ViewParent,
volatile Object mLocalDragState;
final PointF mDragPoint = new PointF();
final PointF mLastTouchPoint = new PointF();
-
- private boolean mProfileRendering;
+
+ private boolean mProfileRendering;
private Choreographer.FrameCallback mRenderProfiler;
private boolean mRenderProfilingEnabled;
@@ -291,7 +292,7 @@ public final class ViewRootImpl implements ViewParent,
private int mFpsNumFrames;
private final ArrayList<DisplayList> mDisplayLists = new ArrayList<DisplayList>();
-
+
/**
* see {@link #playSoundEffect(int)}
*/
@@ -332,7 +333,7 @@ public final class ViewRootImpl implements ViewParent,
int localValue;
int localChanges;
}
-
+
public ViewRootImpl(Context context, Display display) {
mContext = context;
mWindowSession = WindowManagerGlobal.getWindowSession();
@@ -383,13 +384,13 @@ public final class ViewRootImpl implements ViewParent,
}
}
}
-
+
public static void addConfigCallback(ComponentCallbacks callback) {
synchronized (sConfigCallbacks) {
sConfigCallbacks.add(callback);
}
}
-
+
// FIXME for perf testing only
private boolean mProfile = false;
@@ -514,7 +515,7 @@ public final class ViewRootImpl implements ViewParent,
attrs.restore();
}
}
-
+
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
}
@@ -680,7 +681,7 @@ public final class ViewRootImpl implements ViewParent,
if (mTranslator != null) return;
// Try to enable hardware acceleration if requested
- final boolean hardwareAccelerated =
+ final boolean hardwareAccelerated =
(attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
if (hardwareAccelerated) {
@@ -707,7 +708,7 @@ public final class ViewRootImpl implements ViewParent,
// Don't enable hardware acceleration when we're not on the main thread
if (!HardwareRenderer.sSystemRendererDisabled &&
Looper.getMainLooper() != Looper.myLooper()) {
- Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware "
+ Log.w(HardwareRenderer.LOG_TAG, "Attempting to initialize hardware "
+ "acceleration outside of the main thread, aborting");
return;
}
@@ -918,6 +919,7 @@ public final class ViewRootImpl implements ViewParent,
return r.intersect(0, 0, mWidth, mHeight);
}
+ @Override
public void bringChildToFront(View child) {
}
@@ -1152,9 +1154,9 @@ public final class ViewRootImpl implements ViewParent,
mLastInCompatMode = true;
}
}
-
+
mWindowAttributesChangesFlag = 0;
-
+
Rect frame = mWinFrame;
if (mFirst) {
mFullRedrawNeeded = true;
@@ -1522,7 +1524,7 @@ public final class ViewRootImpl implements ViewParent,
try {
hwInitialized = mAttachInfo.mHardwareRenderer.initialize(
mHolder.getSurface());
- } catch (Surface.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
return;
}
@@ -1549,7 +1551,7 @@ public final class ViewRootImpl implements ViewParent,
mFullRedrawNeeded = true;
try {
mAttachInfo.mHardwareRenderer.updateSurface(mHolder.getSurface());
- } catch (Surface.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
return;
}
@@ -1644,23 +1646,23 @@ public final class ViewRootImpl implements ViewParent,
|| mHeight != host.getMeasuredHeight() || contentInsetsChanged) {
int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
-
+
if (DEBUG_LAYOUT) Log.v(TAG, "Ooops, something changed! mWidth="
+ mWidth + " measuredWidth=" + host.getMeasuredWidth()
+ " mHeight=" + mHeight
+ " measuredHeight=" + host.getMeasuredHeight()
+ " coveredInsetsChanged=" + contentInsetsChanged);
-
+
// Ask host how big it wants to be
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
-
+
// Implementation of weights from WindowManager.LayoutParams
// We just grow the dimensions as needed and re-measure if
// needs be
int width = host.getMeasuredWidth();
int height = host.getMeasuredHeight();
boolean measureAgain = false;
-
+
if (lp.horizontalWeight > 0.0f) {
width += (int) ((mWidth - width) * lp.horizontalWeight);
childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
@@ -1673,14 +1675,14 @@ public final class ViewRootImpl implements ViewParent,
MeasureSpec.EXACTLY);
measureAgain = true;
}
-
+
if (measureAgain) {
if (DEBUG_LAYOUT) Log.v(TAG,
"And hey let's measure once more: width=" + width
+ " height=" + height);
performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);
}
-
+
layoutRequested = true;
}
}
@@ -1851,7 +1853,7 @@ public final class ViewRootImpl implements ViewParent,
}
mPendingTransitions.clear();
}
-
+
performDraw();
}
} else {
@@ -2078,6 +2080,7 @@ public final class ViewRootImpl implements ViewParent,
return validLayoutRequesters;
}
+ @Override
public void requestTransparentRegion(View child) {
// the test below should not fail unless someone is messing with us
checkThread();
@@ -2128,10 +2131,12 @@ public final class ViewRootImpl implements ViewParent,
int mResizeAlpha;
final Paint mResizePaint = new Paint();
+ @Override
public void onHardwarePreDraw(HardwareCanvas canvas) {
canvas.translate(0, -mHardwareYOffset);
}
+ @Override
public void onHardwarePostDraw(HardwareCanvas canvas) {
if (mResizeBuffer != null) {
mResizePaint.setAlpha(mResizeAlpha);
@@ -2365,7 +2370,7 @@ public final class ViewRootImpl implements ViewParent,
try {
attachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
mHolder.getSurface());
- } catch (Surface.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
handleOutOfResourcesException(e);
return;
}
@@ -2741,6 +2746,7 @@ public final class ViewRootImpl implements ViewParent,
mAccessibilityFocusedVirtualView = node;
}
+ @Override
public void requestChildFocus(View child, View focused) {
if (DEBUG_INPUT_RESIZE) {
Log.v(TAG, "Request child focus: focus now " + focused);
@@ -2749,6 +2755,7 @@ public final class ViewRootImpl implements ViewParent,
scheduleTraversals();
}
+ @Override
public void clearChildFocus(View child) {
if (DEBUG_INPUT_RESIZE) {
Log.v(TAG, "Clearing child focus");
@@ -2762,6 +2769,7 @@ public final class ViewRootImpl implements ViewParent,
return null;
}
+ @Override
public void focusableViewAvailable(View v) {
checkThread();
if (mView != null) {
@@ -2783,6 +2791,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void recomputeViewAttributes(View child) {
checkThread();
if (mView == child) {
@@ -3076,7 +3085,7 @@ public final class ViewRootImpl implements ViewParent,
try {
mAttachInfo.mHardwareRenderer.initializeIfNeeded(
mWidth, mHeight, mHolder.getSurface());
- } catch (Surface.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
Log.e(TAG, "OutOfResourcesException locking surface", e);
try {
if (!mWindowSession.outOfMemory(mWindow)) {
@@ -4990,7 +4999,7 @@ public final class ViewRootImpl implements ViewParent,
// most recent data.
mSeq = args.seq;
mAttachInfo.mForceReportNewAttributes = true;
- scheduleTraversals();
+ scheduleTraversals();
}
if (mView == null) return;
if (args.localChanges != 0) {
@@ -5080,7 +5089,7 @@ public final class ViewRootImpl implements ViewParent,
if (restore) {
params.restore();
}
-
+
if (mTranslator != null) {
mTranslator.translateRectInScreenToAppWinFrame(mWinFrame);
mTranslator.translateRectInScreenToAppWindow(mPendingOverscanInsets);
@@ -5093,6 +5102,7 @@ public final class ViewRootImpl implements ViewParent,
/**
* {@inheritDoc}
*/
+ @Override
public void playSoundEffect(int effectId) {
checkThread();
@@ -5133,6 +5143,7 @@ public final class ViewRootImpl implements ViewParent,
/**
* {@inheritDoc}
*/
+ @Override
public boolean performHapticFeedback(int effectId, boolean always) {
try {
return mWindowSession.performHapticFeedback(mWindow, effectId, always);
@@ -5144,6 +5155,7 @@ public final class ViewRootImpl implements ViewParent,
/**
* {@inheritDoc}
*/
+ @Override
public View focusSearch(View focused, int direction) {
checkThread();
if (!(mView instanceof ViewGroup)) {
@@ -5155,7 +5167,7 @@ public final class ViewRootImpl implements ViewParent,
public void debug() {
mView.debug();
}
-
+
public void dumpGfxInfo(int[] info) {
info[0] = info[1] = 0;
if (mView != null) {
@@ -5574,8 +5586,8 @@ public final class ViewRootImpl implements ViewParent,
final class InvalidateOnAnimationRunnable implements Runnable {
private boolean mPosted;
- private ArrayList<View> mViews = new ArrayList<View>();
- private ArrayList<AttachInfo.InvalidateInfo> mViewRects =
+ private final ArrayList<View> mViews = new ArrayList<View>();
+ private final ArrayList<AttachInfo.InvalidateInfo> mViewRects =
new ArrayList<AttachInfo.InvalidateInfo>();
private View[] mTempViews;
private AttachInfo.InvalidateInfo[] mTempViewRects;
@@ -5813,20 +5825,25 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public boolean showContextMenuForChild(View originalView) {
return false;
}
+ @Override
public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback) {
return null;
}
+ @Override
public void createContextMenu(ContextMenu menu) {
}
+ @Override
public void childDrawableStateChanged(View child) {
}
+ @Override
public boolean requestSendAccessibilityEvent(View child, AccessibilityEvent event) {
if (mView == null) {
return false;
@@ -5958,10 +5975,12 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) {
// ViewAncestor never intercepts touch event, so this can be a no-op
}
+ @Override
public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
final boolean scrolled = scrollToRectOrFocus(rectangle, immediate);
if (rectangle != null) {
@@ -5977,6 +5996,7 @@ public final class ViewRootImpl implements ViewParent,
return scrolled;
}
+ @Override
public void childHasTransientStateChanged(View child, boolean hasTransientState) {
// Do nothing.
}
@@ -5997,20 +6017,23 @@ public final class ViewRootImpl implements ViewParent,
// Not currently interesting -- from changing between fixed and layout size.
}
+ @Override
public void setFormat(int format) {
((RootViewSurfaceTaker)mView).setSurfaceFormat(format);
}
+ @Override
public void setType(int type) {
((RootViewSurfaceTaker)mView).setSurfaceType(type);
}
-
+
@Override
public void onUpdateSurface() {
// We take care of format and type changes on our own.
throw new IllegalStateException("Shouldn't be here");
}
+ @Override
public boolean isCreating() {
return mIsCreating;
}
@@ -6020,7 +6043,8 @@ public final class ViewRootImpl implements ViewParent,
throw new UnsupportedOperationException(
"Currently only support sizing from layout");
}
-
+
+ @Override
public void setKeepScreenOn(boolean screenOn) {
((RootViewSurfaceTaker)mView).setSurfaceKeepScreenOn(screenOn);
}
@@ -6035,6 +6059,7 @@ public final class ViewRootImpl implements ViewParent,
mWindowSession = viewAncestor.mWindowSession;
}
+ @Override
public void resized(Rect frame, Rect overscanInsets, Rect contentInsets,
Rect visibleInsets, boolean reportDraw, Configuration newConfig) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
@@ -6052,6 +6077,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void dispatchAppVisibility(boolean visible) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
@@ -6059,6 +6085,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void dispatchScreenState(boolean on) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
@@ -6066,6 +6093,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void dispatchGetNewSurface() {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
@@ -6073,6 +6101,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void windowFocusChanged(boolean hasFocus, boolean inTouchMode) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
@@ -6089,6 +6118,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
@@ -6119,14 +6149,16 @@ public final class ViewRootImpl implements ViewParent,
}
}
}
-
+
+ @Override
public void closeSystemDialogs(String reason) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
viewAncestor.dispatchCloseSystemDialogs(reason);
}
}
-
+
+ @Override
public void dispatchWallpaperOffsets(float x, float y, float xStep, float yStep,
boolean sync) {
if (sync) {
@@ -6137,6 +6169,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void dispatchWallpaperCommand(String action, int x, int y,
int z, Bundle extras, boolean sync) {
if (sync) {
@@ -6148,6 +6181,7 @@ public final class ViewRootImpl implements ViewParent,
}
/* Drag/drop */
+ @Override
public void dispatchDragEvent(DragEvent event) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
@@ -6155,6 +6189,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void dispatchSystemUiVisibilityChanged(int seq, int globalVisibility,
int localValue, int localChanges) {
final ViewRootImpl viewAncestor = mViewAncestor.get();
@@ -6164,6 +6199,7 @@ public final class ViewRootImpl implements ViewParent,
}
}
+ @Override
public void doneAnimating() {
final ViewRootImpl viewAncestor = mViewAncestor.get();
if (viewAncestor != null) {
@@ -6178,50 +6214,63 @@ public final class ViewRootImpl implements ViewParent,
}
}
- private SurfaceHolder mHolder = new SurfaceHolder() {
+ private final SurfaceHolder mHolder = new SurfaceHolder() {
// we only need a SurfaceHolder for opengl. it would be nice
// to implement everything else though, especially the callback
// support (opengl doesn't make use of it right now, but eventually
// will).
+ @Override
public Surface getSurface() {
return mSurface;
}
+ @Override
public boolean isCreating() {
return false;
}
+ @Override
public void addCallback(Callback callback) {
}
+ @Override
public void removeCallback(Callback callback) {
}
+ @Override
public void setFixedSize(int width, int height) {
}
+ @Override
public void setSizeFromLayout() {
}
+ @Override
public void setFormat(int format) {
}
+ @Override
public void setType(int type) {
}
+ @Override
public void setKeepScreenOn(boolean screenOn) {
}
+ @Override
public Canvas lockCanvas() {
return null;
}
+ @Override
public Canvas lockCanvas(Rect dirty) {
return null;
}
+ @Override
public void unlockCanvasAndPost(Canvas canvas) {
}
+ @Override
public Rect getSurfaceFrame() {
return null;
}
@@ -6316,6 +6365,7 @@ public final class ViewRootImpl implements ViewParent,
*/
final class AccessibilityInteractionConnectionManager
implements AccessibilityStateChangeListener {
+ @Override
public void onAccessibilityStateChanged(boolean enabled) {
if (enabled) {
ensureConnection();
@@ -6491,6 +6541,7 @@ public final class ViewRootImpl implements ViewParent,
public View mSource;
public long mLastEventTimeMillis;
+ @Override
public void run() {
// The accessibility may be turned off while we were waiting so check again.
if (AccessibilityManager.getInstance(mContext).isEnabled()) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index ba634212a757..c61516b4d3c2 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -2279,9 +2279,12 @@ public class AccessibilityNodeInfo implements Parcelable {
if (other.mExtras != null && !other.mExtras.isEmpty()) {
getExtras().putAll(other.mExtras);
}
- mRangeInfo = other.mRangeInfo;
- mCollectionInfo = other.mCollectionInfo;
- mCollectionItemInfo = other.mCollectionItemInfo;
+ mRangeInfo = (other.mRangeInfo != null)
+ ? RangeInfo.obtain(other.mRangeInfo) : null;
+ mCollectionInfo = (other.mCollectionInfo != null)
+ ? CollectionInfo.obtain(other.mCollectionInfo) : null;
+ mCollectionItemInfo = (other.mCollectionItemInfo != null)
+ ? CollectionItemInfo.obtain(other.mCollectionItemInfo) : null;
}
/**
@@ -2602,6 +2605,17 @@ public class AccessibilityNodeInfo implements Parcelable {
private float mCurrent;
/**
+ * Obtains a pooled instance that is a clone of another one.
+ *
+ * @param other The instance to clone.
+ *
+ * @hide
+ */
+ public static RangeInfo obtain(RangeInfo other) {
+ return obtain(other.mType, other.mMin, other.mMax, other.mCurrent);
+ }
+
+ /**
* Obtains a pooled instance.
*
* @param type The type of the range.
@@ -2708,6 +2722,18 @@ public class AccessibilityNodeInfo implements Parcelable {
private boolean mHierarchical;
/**
+ * Obtains a pooled instance that is a clone of another one.
+ *
+ * @param other The instance to clone.
+ *
+ * @hide
+ */
+ public static CollectionInfo obtain(CollectionInfo other) {
+ return CollectionInfo.obtain(other.mRowCount, other.mColumnCount,
+ other.mHierarchical);
+ }
+
+ /**
* Obtains a pooled instance.
*
* @param rowCount The number of rows.
@@ -2796,6 +2822,18 @@ public class AccessibilityNodeInfo implements Parcelable {
new SynchronizedPool<CollectionItemInfo>(MAX_POOL_SIZE);
/**
+ * Obtains a pooled instance that is a clone of another one.
+ *
+ * @param other The instance to clone.
+ *
+ * @hide
+ */
+ public static CollectionItemInfo obtain(CollectionItemInfo other) {
+ return CollectionItemInfo.obtain(other.mRowIndex, other.mRowSpan,
+ other.mColumnIndex, other.mColumnSpan, other.mHeading);
+ }
+
+ /**
* Obtains a pooled instance.
*
* @param rowIndex The row index at which the item is located.
diff --git a/core/java/android/view/accessibility/CaptioningManager.java b/core/java/android/view/accessibility/CaptioningManager.java
index d4c6abe69abf..557239f6096d 100644
--- a/core/java/android/view/accessibility/CaptioningManager.java
+++ b/core/java/android/view/accessibility/CaptioningManager.java
@@ -140,7 +140,7 @@ public class CaptioningManager {
*
* @param listener the listener to add
*/
- public void addCaptioningStateChangeListener(CaptioningChangeListener listener) {
+ public void addCaptioningChangeListener(CaptioningChangeListener listener) {
synchronized (mListeners) {
if (mListeners.isEmpty()) {
registerObserver(Secure.ACCESSIBILITY_CAPTIONING_ENABLED);
@@ -163,11 +163,11 @@ public class CaptioningManager {
/**
* Removes a listener previously added using
- * {@link #addCaptioningStateChangeListener}.
+ * {@link #addCaptioningChangeListener}.
*
* @param listener the listener to remove
*/
- public void removeCaptioningStateChangeListener(CaptioningChangeListener listener) {
+ public void removeCaptioningChangeListener(CaptioningChangeListener listener) {
synchronized (mListeners) {
mListeners.remove(listener);
@@ -366,7 +366,7 @@ public class CaptioningManager {
* Listener for changes in captioning properties, including enabled state
* and user style preferences.
*/
- public abstract class CaptioningChangeListener {
+ public static abstract class CaptioningChangeListener {
/**
* Called when the captioning enabled state changes.
*
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 29b7cf2095db..7378d7479873 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -1250,7 +1250,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
mFastScroller.setEnabled(true);
}
- recomputePadding();
+ resolvePadding();
if (mFastScroller != null) {
mFastScroller.updateLayout();
@@ -1312,7 +1312,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
* @see #setFastScrollAlwaysVisible(boolean)
*/
public boolean isFastScrollAlwaysVisible() {
- return mFastScrollEnabled && mFastScrollAlwaysVisible;
+ if (mFastScroller == null) {
+ return mFastScrollEnabled && mFastScrollAlwaysVisible;
+ } else {
+ return mFastScroller.isEnabled() && mFastScroller.isAlwaysShowEnabled();
+ }
}
@Override
@@ -1331,7 +1335,11 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
@ViewDebug.ExportedProperty
public boolean isFastScrollEnabled() {
- return mFastScrollEnabled;
+ if (mFastScroller == null) {
+ return mFastScrollEnabled;
+ } else {
+ return mFastScroller.isEnabled();
+ }
}
@Override
@@ -1356,7 +1364,7 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
*/
@Override
protected boolean isVerticalScrollBarHidden() {
- return mFastScrollEnabled;
+ return isFastScrollEnabled();
}
/**
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index c48955f625b0..006b96e7834d 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -152,9 +152,6 @@ class FastScroller {
/** The number of headers at the top of the view. */
private int mHeaderCount;
- /** The number of items in the list. */
- private int mItemCount = -1;
-
/** The index of the current section. */
private int mCurrentSection = -1;
@@ -324,6 +321,7 @@ class FastScroller {
getSectionsFromIndexer();
refreshDrawablePressedState();
+ updateLongList(listView.getChildCount(), listView.getCount());
setScrollbarPosition(mList.getVerticalScrollbarPosition());
postAutoHide();
}
@@ -343,14 +341,10 @@ class FastScroller {
* @param enabled Whether the fast scroll thumb is enabled.
*/
public void setEnabled(boolean enabled) {
- mEnabled = enabled;
+ if (mEnabled != enabled) {
+ mEnabled = enabled;
- if (enabled) {
- if (mAlwaysShow) {
- setState(STATE_VISIBLE);
- }
- } else {
- stop();
+ onStateDependencyChanged();
}
}
@@ -358,19 +352,17 @@ class FastScroller {
* @return Whether the fast scroll thumb is enabled.
*/
public boolean isEnabled() {
- return mEnabled;
+ return mEnabled && (mLongList || mAlwaysShow);
}
/**
* @param alwaysShow Whether the fast scroll thumb should always be shown
*/
public void setAlwaysShow(boolean alwaysShow) {
- mAlwaysShow = alwaysShow;
+ if (mAlwaysShow != alwaysShow) {
+ mAlwaysShow = alwaysShow;
- if (alwaysShow) {
- setState(STATE_VISIBLE);
- } else if (mState == STATE_VISIBLE) {
- postAutoHide();
+ onStateDependencyChanged();
}
}
@@ -382,6 +374,23 @@ class FastScroller {
return mAlwaysShow;
}
+ /**
+ * Called when one of the variables affecting enabled state changes.
+ */
+ private void onStateDependencyChanged() {
+ if (isEnabled()) {
+ if (isAlwaysShowEnabled()) {
+ setState(STATE_VISIBLE);
+ } else if (mState == STATE_VISIBLE) {
+ postAutoHide();
+ }
+ } else {
+ stop();
+ }
+
+ mList.resolvePadding();
+ }
+
public void setScrollBarStyle(int style) {
if (mScrollBarStyle != style) {
mScrollBarStyle = style;
@@ -439,6 +448,18 @@ class FastScroller {
final int firstVisibleItem = mList.getFirstVisiblePosition();
setThumbPos(getPosFromItemCount(firstVisibleItem, visibleItemCount, totalItemCount));
}
+
+ updateLongList(visibleItemCount, totalItemCount);
+ }
+
+ private void updateLongList(int visibleItemCount, int totalItemCount) {
+ final boolean longList = visibleItemCount > 0
+ && totalItemCount / visibleItemCount >= MIN_PAGES;
+ if (mLongList != longList) {
+ mLongList = longList;
+
+ onStateDependencyChanged();
+ }
}
/**
@@ -795,19 +816,8 @@ class FastScroller {
mList.postDelayed(mDeferHide, FADE_TIMEOUT);
}
- private boolean isLongList(int visibleItemCount, int totalItemCount) {
- // Are there enough pages to require fast scroll? Recompute only if
- // total count changes.
- if (mItemCount != totalItemCount && visibleItemCount > 0) {
- mItemCount = totalItemCount;
- mLongList = mItemCount / visibleItemCount >= MIN_PAGES;
- }
-
- return mLongList;
- }
-
public void onScroll(int firstVisibleItem, int visibleItemCount, int totalItemCount) {
- if (!mEnabled || !mAlwaysShow && !isLongList(visibleItemCount, totalItemCount)) {
+ if (!isEnabled()) {
setState(STATE_NONE);
return;
}
@@ -1221,7 +1231,7 @@ class FastScroller {
}
public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (!mEnabled) {
+ if (!isEnabled()) {
return false;
}
@@ -1233,14 +1243,18 @@ class FastScroller {
// need to allow the parent time to decide whether it wants
// to intercept events. If it does, we will receive a CANCEL
// event.
- if (mList.isInScrollingContainer()) {
- mInitialTouchY = ev.getY();
- startPendingDrag();
- return false;
+ if (!mList.isInScrollingContainer()) {
+ beginDrag();
+ return true;
}
- beginDrag();
- return true;
+ mInitialTouchY = ev.getY();
+ startPendingDrag();
+ }
+ break;
+ case MotionEvent.ACTION_MOVE:
+ if (!isPointInside(ev.getX(), ev.getY())) {
+ cancelPendingDrag();
}
break;
case MotionEvent.ACTION_UP:
@@ -1253,7 +1267,7 @@ class FastScroller {
}
public boolean onInterceptHoverEvent(MotionEvent ev) {
- if (!mEnabled) {
+ if (!isEnabled()) {
return false;
}
@@ -1269,18 +1283,11 @@ class FastScroller {
}
public boolean onTouchEvent(MotionEvent me) {
- if (!mEnabled) {
+ if (!isEnabled()) {
return false;
}
switch (me.getActionMasked()) {
- case MotionEvent.ACTION_DOWN: {
- if (isPointInside(me.getX(), me.getY())) {
- beginDrag();
- return true;
- }
- } break;
-
case MotionEvent.ACTION_UP: {
if (mHasPendingDrag) {
// Allow a tap to scroll.
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index 389d9d64158e..b239fbd70706 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1555,8 +1555,9 @@ public class ListView extends AbsListView {
} else if (mItemCount != mAdapter.getCount()) {
throw new IllegalStateException("The content of the adapter has changed but "
+ "ListView did not receive a notification. Make sure the content of "
- + "your adapter is not modified from a background thread, but only "
- + "from the UI thread. [in ListView(" + getId() + ", " + getClass()
+ + "your adapter is not modified from a background thread, but only from "
+ + "the UI thread. Make sure your adapter calls notifyDataSetChanged() "
+ + "when its content changes. [in ListView(" + getId() + ", " + getClass()
+ ") with Adapter(" + mAdapter.getClass() + ")]");
}
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index b87ed7a15588..b75d36f0039c 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -412,6 +412,8 @@ public class Spinner extends AbsSpinner implements OnClickListener {
public void setAdapter(SpinnerAdapter adapter) {
super.setAdapter(adapter);
+ mRecycler.clear();
+
if (mPopup != null) {
mPopup.setAdapter(new DropDownAdapter(adapter));
} else {
@@ -426,9 +428,8 @@ public class Spinner extends AbsSpinner implements OnClickListener {
if (getChildCount() > 0) {
child = getChildAt(0);
} else if (mAdapter != null && mAdapter.getCount() > 0) {
- child = makeAndAddView(0);
+ child = makeView(0, false);
mRecycler.put(0, child);
- removeAllViewsInLayout();
}
if (child != null) {
@@ -536,7 +537,7 @@ public class Spinner extends AbsSpinner implements OnClickListener {
mFirstPosition = mSelectedPosition;
if (mAdapter != null) {
- View sel = makeAndAddView(mSelectedPosition);
+ View sel = makeView(mSelectedPosition, true);
int width = sel.getMeasuredWidth();
int selectedOffset = childrenLeft;
final int layoutDirection = getLayoutDirection();
@@ -571,17 +572,17 @@ public class Spinner extends AbsSpinner implements OnClickListener {
* from the old to new positions.
*
* @param position Position in the spinner for the view to obtain
- * @return A view that has been added to the spinner
+ * @param addChild true to add the child to the spinner, false to obtain and configure only.
+ * @return A view for the given position
*/
- private View makeAndAddView(int position) {
-
+ private View makeView(int position, boolean addChild) {
View child;
if (!mDataChanged) {
child = mRecycler.get(position);
if (child != null) {
// Position the view
- setUpChild(child);
+ setUpChild(child, addChild);
return child;
}
@@ -591,7 +592,7 @@ public class Spinner extends AbsSpinner implements OnClickListener {
child = mAdapter.getView(position, null, this);
// Position the view
- setUpChild(child);
+ setUpChild(child, addChild);
return child;
}
@@ -601,8 +602,9 @@ public class Spinner extends AbsSpinner implements OnClickListener {
* and fill out its layout paramters.
*
* @param child The view to position
+ * @param addChild true if the child should be added to the Spinner during setup
*/
- private void setUpChild(View child) {
+ private void setUpChild(View child, boolean addChild) {
// Respect layout params that are already in the view. Otherwise
// make some up...
@@ -611,7 +613,9 @@ public class Spinner extends AbsSpinner implements OnClickListener {
lp = generateDefaultLayoutParams();
}
- addViewInLayout(child, 0, lp);
+ if (addChild) {
+ addViewInLayout(child, 0, lp);
+ }
child.setSelected(hasFocus());
if (mDisableChildrenWhenDisabled) {
diff --git a/core/java/android/widget/VideoView.java b/core/java/android/widget/VideoView.java
index f449797d8053..009b729ffc75 100644
--- a/core/java/android/widget/VideoView.java
+++ b/core/java/android/widget/VideoView.java
@@ -30,6 +30,7 @@ import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.media.Metadata;
import android.media.SubtitleController;
+import android.media.SubtitleTrack.RenderingWidget;
import android.media.WebVttRenderer;
import android.net.Uri;
import android.util.AttributeSet;
@@ -46,7 +47,6 @@ import android.widget.MediaController.MediaPlayerControl;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
import java.util.Map;
import java.util.Vector;
@@ -100,14 +100,11 @@ public class VideoView extends SurfaceView
private boolean mCanSeekBack;
private boolean mCanSeekForward;
- /** List of views overlaid on top of the video. */
- private ArrayList<View> mOverlays;
+ /** Subtitle rendering widget overlaid on top of the video. */
+ private RenderingWidget mSubtitleWidget;
- /**
- * Listener for overlay layout changes. Invalidates the video view to ensure
- * that captions are redrawn whenever their layout changes.
- */
- private OnLayoutChangeListener mOverlayLayoutListener;
+ /** Listener for changes to subtitle data, used to redraw when needed. */
+ private RenderingWidget.OnChangedListener mSubtitlesChangedListener;
public VideoView(Context context) {
super(context);
@@ -302,11 +299,10 @@ public class VideoView extends SurfaceView
mMediaPlayer = new MediaPlayer();
// TODO: create SubtitleController in MediaPlayer, but we need
// a context for the subtitle renderers
- SubtitleController controller = new SubtitleController(
- getContext(),
- mMediaPlayer.getMediaTimeProvider(),
- mMediaPlayer);
- controller.registerRenderer(new WebVttRenderer(getContext(), null));
+ final Context context = getContext();
+ final SubtitleController controller = new SubtitleController(
+ context, mMediaPlayer.getMediaTimeProvider(), mMediaPlayer);
+ controller.registerRenderer(new WebVttRenderer(context));
mMediaPlayer.setSubtitleAnchor(controller, this);
if (mAudioSession != 0) {
@@ -792,117 +788,95 @@ public class VideoView extends SurfaceView
}
@Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- super.onLayout(changed, left, top, right, bottom);
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
- // Layout overlay views, if necessary.
- if (changed && mOverlays != null && !mOverlays.isEmpty()) {
- measureAndLayoutOverlays();
+ if (mSubtitleWidget != null) {
+ mSubtitleWidget.onAttachedToWindow();
}
}
@Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
- final int count = mOverlays.size();
- for (int i = 0; i < count; i++) {
- final View overlay = mOverlays.get(i);
- overlay.draw(canvas);
+ if (mSubtitleWidget != null) {
+ mSubtitleWidget.onDetachedFromWindow();
}
}
- /**
- * Adds a view to be overlaid on top of this video view. During layout, the
- * view will be forced to match the bounds, less padding, of the video view.
- * <p>
- * Overlays are drawn in the order they are added. The last added overlay
- * will be drawn on top.
- *
- * @param overlay the view to overlay
- * @see #removeOverlay(View)
- */
- private void addOverlay(View overlay) {
- if (mOverlays == null) {
- mOverlays = new ArrayList<View>(1);
- }
-
- if (mOverlayLayoutListener == null) {
- mOverlayLayoutListener = new OnLayoutChangeListener() {
- @Override
- public void onLayoutChange(View v, int left, int top, int right, int bottom,
- int oldLeft, int oldTop, int oldRight, int oldBottom) {
- invalidate();
- }
- };
- }
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
- if (mOverlays.isEmpty()) {
- setWillNotDraw(false);
+ if (mSubtitleWidget != null) {
+ measureAndLayoutSubtitleWidget();
}
-
- mOverlays.add(overlay);
- overlay.addOnLayoutChangeListener(mOverlayLayoutListener);
- measureAndLayoutOverlays();
}
- /**
- * Removes a view previously added using {@link #addOverlay}.
- *
- * @param overlay the view to remove
- * @see #addOverlay(View)
- */
- private void removeOverlay(View overlay) {
- if (mOverlays == null) {
- return;
- }
-
- overlay.removeOnLayoutChangeListener(mOverlayLayoutListener);
- mOverlays.remove(overlay);
+ @Override
+ public void draw(Canvas canvas) {
+ super.draw(canvas);
- if (mOverlays.isEmpty()) {
- setWillNotDraw(true);
+ if (mSubtitleWidget != null) {
+ final int saveCount = canvas.save();
+ canvas.translate(getPaddingLeft(), getPaddingTop());
+ mSubtitleWidget.draw(canvas);
+ canvas.restoreToCount(saveCount);
}
-
- invalidate();
}
/**
* Forces a measurement and layout pass for all overlaid views.
*
- * @see #addOverlay(View)
+ * @see #setSubtitleWidget(RenderingWidget)
*/
- private void measureAndLayoutOverlays() {
- final int left = getPaddingLeft();
- final int top = getPaddingTop();
- final int right = getWidth() - left - getPaddingRight();
- final int bottom = getHeight() - top - getPaddingBottom();
- final int widthSpec = MeasureSpec.makeMeasureSpec(right - left, MeasureSpec.EXACTLY);
- final int heightSpec = MeasureSpec.makeMeasureSpec(bottom - top, MeasureSpec.EXACTLY);
+ private void measureAndLayoutSubtitleWidget() {
+ final int width = getWidth() - getPaddingLeft() - getPaddingRight();
+ final int height = getHeight() - getPaddingTop() - getPaddingBottom();
- final int count = mOverlays.size();
- for (int i = 0; i < count; i++) {
- final View overlay = mOverlays.get(i);
- overlay.measure(widthSpec, heightSpec);
- overlay.layout(left, top, right, bottom);
- }
+ mSubtitleWidget.setSize(width, height);
}
/** @hide */
@Override
- public void setSubtitleView(View view) {
- if (mSubtitleView == view) {
+ public void setSubtitleWidget(RenderingWidget subtitleWidget) {
+ if (mSubtitleWidget == subtitleWidget) {
return;
}
- if (mSubtitleView != null) {
- removeOverlay(mSubtitleView);
+ final boolean attachedToWindow = isAttachedToWindow();
+ if (mSubtitleWidget != null) {
+ if (attachedToWindow) {
+ mSubtitleWidget.onDetachedFromWindow();
+ }
+
+ mSubtitleWidget.setOnChangedListener(null);
}
- mSubtitleView = view;
- if (mSubtitleView != null) {
- addOverlay(mSubtitleView);
+
+ mSubtitleWidget = subtitleWidget;
+
+ if (subtitleWidget != null) {
+ if (mSubtitlesChangedListener == null) {
+ mSubtitlesChangedListener = new RenderingWidget.OnChangedListener() {
+ @Override
+ public void onChanged(RenderingWidget renderingWidget) {
+ invalidate();
+ }
+ };
+ }
+
+ setWillNotDraw(false);
+ subtitleWidget.setOnChangedListener(mSubtitlesChangedListener);
+
+ if (attachedToWindow) {
+ subtitleWidget.onAttachedToWindow();
+ requestLayout();
+ }
+ } else {
+ setWillNotDraw(true);
}
- }
- private View mSubtitleView;
+ invalidate();
+ }
}
diff --git a/core/java/com/android/internal/app/ProcessStats.java b/core/java/com/android/internal/app/ProcessStats.java
index 16b119a68cb9..1f55a4cebeeb 100644
--- a/core/java/com/android/internal/app/ProcessStats.java
+++ b/core/java/com/android/internal/app/ProcessStats.java
@@ -165,7 +165,7 @@ public final class ProcessStats implements Parcelable {
static final String CSV_SEP = "\t";
// Current version of the parcel format.
- private static final int PARCEL_VERSION = 9;
+ private static final int PARCEL_VERSION = 11;
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0x50535453;
@@ -204,6 +204,12 @@ public final class ProcessStats implements Parcelable {
int[] mAddLongTable;
int mAddLongTableSize;
+ // For writing parcels.
+ ArrayMap<String, Integer> mCommonStringToIndex;
+
+ // For reading parcels.
+ ArrayList<String> mIndexToCommonString;
+
public ProcessStats(boolean running) {
mRunning = running;
reset();
@@ -247,7 +253,7 @@ public final class ProcessStats implements Parcelable {
if (DEBUG) Slog.d(TAG, "Adding pkg " + pkgName + " uid " + uid
+ " service " + otherSvc.mName);
ServiceState thisSvc = getServiceStateLocked(pkgName, uid,
- null, otherSvc.mName);
+ otherSvc.mProcessName, otherSvc.mName);
thisSvc.add(otherSvc);
}
}
@@ -959,7 +965,15 @@ public final class ProcessStats implements Parcelable {
for (int ip=procMap.size()-1; ip>=0; ip--) {
SparseArray<ProcessState> uids = procMap.valueAt(ip);
for (int iu=uids.size()-1; iu>=0; iu--) {
- uids.valueAt(iu).resetSafely(now);
+ ProcessState ps = uids.valueAt(iu);
+ if (ps.isInUse()) {
+ uids.valueAt(iu).resetSafely(now);
+ } else {
+ uids.removeAt(iu);
+ }
+ }
+ if (uids.size() <= 0) {
+ procMap.removeAt(ip);
}
}
ArrayMap<String, SparseArray<PackageState>> pkgMap = mPackages.getMap();
@@ -968,16 +982,27 @@ public final class ProcessStats implements Parcelable {
for (int iu=uids.size()-1; iu>=0; iu--) {
PackageState pkgState = uids.valueAt(iu);
for (int iproc=pkgState.mProcesses.size()-1; iproc>=0; iproc--) {
- pkgState.mProcesses.valueAt(iproc).resetSafely(now);
+ ProcessState ps = pkgState.mProcesses.valueAt(iproc);
+ if (ps.isInUse()) {
+ pkgState.mProcesses.valueAt(iproc).resetSafely(now);
+ } else {
+ pkgState.mProcesses.removeAt(iproc);
+ }
}
for (int isvc=pkgState.mServices.size()-1; isvc>=0; isvc--) {
ServiceState ss = pkgState.mServices.valueAt(isvc);
- if (ss.isActive()) {
+ if (ss.isInUse()) {
pkgState.mServices.valueAt(isvc).resetSafely(now);
} else {
pkgState.mServices.removeAt(isvc);
}
}
+ if (pkgState.mProcesses.size() <= 0 && pkgState.mServices.size() <= 0) {
+ uids.removeAt(iu);
+ }
+ }
+ if (uids.size() <= 0) {
+ pkgMap.removeAt(ip);
}
}
mStartTime = SystemClock.uptimeMillis();
@@ -1048,6 +1073,75 @@ public final class ProcessStats implements Parcelable {
return table;
}
+ private void writeCompactedLongArray(Parcel out, long[] array) {
+ final int N = array.length;
+ out.writeInt(N);
+ for (int i=0; i<N; i++) {
+ long val = array[i];
+ if (val < 0) {
+ Slog.w(TAG, "Time val negative: " + val);
+ val = 0;
+ }
+ if (val <= Integer.MAX_VALUE) {
+ out.writeInt((int)val);
+ } else {
+ int top = ~((int)((val>>32)&0x7fffffff));
+ int bottom = (int)(val&0xfffffff);
+ out.writeInt(top);
+ out.writeInt(bottom);
+ }
+ }
+ }
+
+ private void readCompactedLongArray(Parcel in, int version, long[] array) {
+ if (version <= 10) {
+ in.readLongArray(array);
+ return;
+ }
+ final int N = in.readInt();
+ if (N != array.length) {
+ throw new RuntimeException("bad array lengths");
+ }
+ for (int i=0; i<N; i++) {
+ int val = in.readInt();
+ if (val >= 0) {
+ array[i] = val;
+ } else {
+ int bottom = in.readInt();
+ array[i] = (((long)~val)<<32) | bottom;
+ }
+ }
+ }
+
+ private void writeCommonString(Parcel out, String name) {
+ Integer index = mCommonStringToIndex.get(name);
+ if (index != null) {
+ out.writeInt(index);
+ return;
+ }
+ index = mCommonStringToIndex.size();
+ mCommonStringToIndex.put(name, index);
+ out.writeInt(~index);
+ out.writeString(name);
+ }
+
+ private String readCommonString(Parcel in, int version) {
+ if (version <= 9) {
+ return in.readString();
+ }
+ int index = in.readInt();
+ if (index >= 0) {
+ return mIndexToCommonString.get(index);
+ }
+ index = ~index;
+ String name = in.readString();
+ while (mIndexToCommonString.size() <= index) {
+ mIndexToCommonString.add(null);
+ }
+ mIndexToCommonString.set(index, name);
+ return name;
+ }
+
@Override
public int describeContents() {
return 0;
@@ -1063,6 +1157,8 @@ public final class ProcessStats implements Parcelable {
out.writeInt(PSS_COUNT);
out.writeInt(LONGS_SIZE);
+ mCommonStringToIndex = new ArrayMap<String, Integer>(mProcesses.mMap.size());
+
// First commit all running times.
ArrayMap<String, SparseArray<ProcessState>> procMap = mProcesses.getMap();
final int NPROC = procMap.size();
@@ -1104,7 +1200,7 @@ public final class ProcessStats implements Parcelable {
out.writeInt(mLongs.size());
out.writeInt(mNextLong);
for (int i=0; i<(mLongs.size()-1); i++) {
- out.writeLongArray(mLongs.get(i));
+ writeCompactedLongArray(out, mLongs.get(i));
}
long[] lastLongs = mLongs.get(mLongs.size() - 1);
for (int i=0; i<mNextLong; i++) {
@@ -1116,24 +1212,24 @@ public final class ProcessStats implements Parcelable {
mMemFactorDurations[mMemFactor] += now - mStartTime;
mStartTime = now;
}
- out.writeLongArray(mMemFactorDurations);
+ writeCompactedLongArray(out, mMemFactorDurations);
out.writeInt(NPROC);
for (int ip=0; ip<NPROC; ip++) {
- out.writeString(procMap.keyAt(ip));
+ writeCommonString(out, procMap.keyAt(ip));
SparseArray<ProcessState> uids = procMap.valueAt(ip);
final int NUID = uids.size();
out.writeInt(NUID);
for (int iu=0; iu<NUID; iu++) {
out.writeInt(uids.keyAt(iu));
ProcessState proc = uids.valueAt(iu);
- out.writeString(proc.mPackage);
+ writeCommonString(out, proc.mPackage);
proc.writeToParcel(out, now);
}
}
out.writeInt(NPKG);
for (int ip=0; ip<NPKG; ip++) {
- out.writeString(pkgMap.keyAt(ip));
+ writeCommonString(out, pkgMap.keyAt(ip));
SparseArray<PackageState> uids = pkgMap.valueAt(ip);
final int NUID = uids.size();
out.writeInt(NUID);
@@ -1143,7 +1239,7 @@ public final class ProcessStats implements Parcelable {
final int NPROCS = pkgState.mProcesses.size();
out.writeInt(NPROCS);
for (int iproc=0; iproc<NPROCS; iproc++) {
- out.writeString(pkgState.mProcesses.keyAt(iproc));
+ writeCommonString(out, pkgState.mProcesses.keyAt(iproc));
ProcessState proc = pkgState.mProcesses.valueAt(iproc);
if (proc.mCommonProcess == proc) {
// This is the same as the common process we wrote above.
@@ -1159,10 +1255,13 @@ public final class ProcessStats implements Parcelable {
for (int isvc=0; isvc<NSRVS; isvc++) {
out.writeString(pkgState.mServices.keyAt(isvc));
ServiceState svc = pkgState.mServices.valueAt(isvc);
+ writeCommonString(out, svc.mProcessName);
svc.writeToParcel(out, now);
}
}
}
+
+ mCommonStringToIndex = null;
}
private boolean readCheckedInt(Parcel in, int val, String what) {
@@ -1222,7 +1321,7 @@ public final class ProcessStats implements Parcelable {
return;
}
int version = in.readInt();
- if (version != PARCEL_VERSION && version != 6) {
+ if (version != PARCEL_VERSION) {
mReadError = "bad version: " + version;
return;
}
@@ -1239,14 +1338,14 @@ public final class ProcessStats implements Parcelable {
return;
}
+ mIndexToCommonString = new ArrayList<String>();
+
mTimePeriodStartClock = in.readLong();
buildTimePeriodStartClockStr();
mTimePeriodStartRealtime = in.readLong();
mTimePeriodEndRealtime = in.readLong();
- if (version == PARCEL_VERSION) {
- mRuntime = in.readString();
- mWebView = in.readString();
- }
+ mRuntime = in.readString();
+ mWebView = in.readString();
mFlags = in.readInt();
final int NLONGS = in.readInt();
@@ -1256,7 +1355,7 @@ public final class ProcessStats implements Parcelable {
while (i >= mLongs.size()) {
mLongs.add(new long[LONGS_SIZE]);
}
- in.readLongArray(mLongs.get(i));
+ readCompactedLongArray(in, version, mLongs.get(i));
}
long[] longs = new long[LONGS_SIZE];
mNextLong = NEXTLONG;
@@ -1266,7 +1365,7 @@ public final class ProcessStats implements Parcelable {
}
mLongs.add(longs);
- in.readLongArray(mMemFactorDurations);
+ readCompactedLongArray(in, version, mMemFactorDurations);
int NPROC = in.readInt();
if (NPROC < 0) {
@@ -1275,7 +1374,7 @@ public final class ProcessStats implements Parcelable {
}
while (NPROC > 0) {
NPROC--;
- String procName = in.readString();
+ String procName = readCommonString(in, version);
if (procName == null) {
mReadError = "bad process name";
return;
@@ -1292,7 +1391,7 @@ public final class ProcessStats implements Parcelable {
mReadError = "bad uid: " + uid;
return;
}
- String pkgName = in.readString();
+ String pkgName = readCommonString(in, version);
if (pkgName == null) {
mReadError = "bad process package name";
return;
@@ -1322,7 +1421,7 @@ public final class ProcessStats implements Parcelable {
}
while (NPKG > 0) {
NPKG--;
- String pkgName = in.readString();
+ String pkgName = readCommonString(in, version);
if (pkgName == null) {
mReadError = "bad package name";
return;
@@ -1348,7 +1447,7 @@ public final class ProcessStats implements Parcelable {
}
while (NPROCS > 0) {
NPROCS--;
- String procName = in.readString();
+ String procName = readCommonString(in, version);
if (procName == null) {
mReadError = "bad package process name";
return;
@@ -1400,9 +1499,10 @@ public final class ProcessStats implements Parcelable {
mReadError = "bad package service name";
return;
}
+ String processName = version > 9 ? readCommonString(in, version) : null;
ServiceState serv = hadData ? pkgState.mServices.get(serviceName) : null;
if (serv == null) {
- serv = new ServiceState(this, pkgName, serviceName, null);
+ serv = new ServiceState(this, pkgName, serviceName, processName, null);
}
if (!serv.readFromParcel(in)) {
return;
@@ -1414,6 +1514,8 @@ public final class ProcessStats implements Parcelable {
}
}
+ mIndexToCommonString = null;
+
if (DEBUG) Slog.d(TAG, "Successfully read procstats!");
}
@@ -1555,12 +1657,11 @@ public final class ProcessStats implements Parcelable {
final ProcessStats.PackageState as = getPackageStateLocked(packageName, uid);
ProcessStats.ServiceState ss = as.mServices.get(className);
if (ss != null) {
- ss.makeActive();
return ss;
}
final ProcessStats.ProcessState ps = processName != null
? getProcessStateLocked(packageName, uid, processName) : null;
- ss = new ProcessStats.ServiceState(this, packageName, className, ps);
+ ss = new ProcessStats.ServiceState(this, packageName, className, processName, ps);
as.mServices.put(className, ss);
return ss;
}
@@ -1602,10 +1703,10 @@ public final class ProcessStats implements Parcelable {
ALL_PROC_STATES, now);
dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
ALL_PROC_STATES);
- if (dumpAll) {
- pw.print(" mNumStartedServices=");
- pw.println(proc.mNumStartedServices);
- }
+ pw.print(" mActive="); pw.println(proc.mActive);
+ pw.print(" mNumActiveServices="); pw.print(proc.mNumActiveServices);
+ pw.print(" mNumStartedServices=");
+ pw.println(proc.mNumStartedServices);
}
} else {
ArrayList<ProcessState> procs = new ArrayList<ProcessState>();
@@ -1624,6 +1725,9 @@ public final class ProcessStats implements Parcelable {
pw.print(pkgState.mServices.keyAt(isvc));
pw.println(":");
ServiceState svc = pkgState.mServices.valueAt(isvc);
+ dumpServiceStats(pw, " ", " ", " ", "Running", svc,
+ svc.mRunCount, ServiceState.SERVICE_RUN, svc.mRunState,
+ svc.mRunStartTime, now, totalTime, dumpAll);
dumpServiceStats(pw, " ", " ", " ", "Started", svc,
svc.mStartedCount, ServiceState.SERVICE_STARTED, svc.mStartedState,
svc.mStartedStartTime, now, totalTime, dumpAll);
@@ -1633,6 +1737,9 @@ public final class ProcessStats implements Parcelable {
dumpServiceStats(pw, " ", " ", " ", "Executing", svc,
svc.mExecCount, ServiceState.SERVICE_EXEC, svc.mExecState,
svc.mExecStartTime, now, totalTime, dumpAll);
+ if (dumpAll) {
+ pw.print(" mActive="); pw.println(svc.mActive);
+ }
}
}
}
@@ -1663,6 +1770,12 @@ public final class ProcessStats implements Parcelable {
ALL_PROC_STATES, now);
dumpProcessPss(pw, " ", proc, ALL_SCREEN_ADJ, ALL_MEM_ADJ,
ALL_PROC_STATES);
+ if (dumpAll) {
+ pw.print(" mActive="); pw.println(proc.mActive);
+ pw.print(" mNumActiveServices="); pw.print(proc.mNumActiveServices);
+ pw.print(" mNumStartedServices=");
+ pw.println(proc.mNumStartedServices);
+ }
}
}
@@ -1929,6 +2042,9 @@ public final class ProcessStats implements Parcelable {
String serviceName = collapseString(pkgName,
pkgState.mServices.keyAt(isvc));
ServiceState svc = pkgState.mServices.valueAt(isvc);
+ dumpServiceTimeCheckin(pw, "pkgsvc-run", pkgName, uid, serviceName,
+ svc, ServiceState.SERVICE_RUN, svc.mRunCount,
+ svc.mRunState, svc.mRunStartTime, now);
dumpServiceTimeCheckin(pw, "pkgsvc-start", pkgName, uid, serviceName,
svc, ServiceState.SERVICE_STARTED, svc.mStartedCount,
svc.mStartedState, svc.mStartedStartTime, now);
@@ -2003,6 +2119,8 @@ public final class ProcessStats implements Parcelable {
int[] mPssTable;
int mPssTableSize;
+ boolean mActive;
+ int mNumActiveServices;
int mNumStartedServices;
int mNumExcessiveWake;
@@ -2072,6 +2190,7 @@ public final class ProcessStats implements Parcelable {
}
pnew.mNumExcessiveWake = mNumExcessiveWake;
pnew.mNumExcessiveCpu = mNumExcessiveCpu;
+ pnew.mActive = mActive;
pnew.mNumStartedServices = mNumStartedServices;
return pnew;
}
@@ -2151,6 +2270,18 @@ public final class ProcessStats implements Parcelable {
return true;
}
+ public void makeActive() {
+ mActive = true;
+ }
+
+ public void makeInactive() {
+ mActive = false;
+ }
+
+ public boolean isInUse() {
+ return mActive || mNumActiveServices > 0 || mNumStartedServices > 0;
+ }
+
/**
* Update the current state of the given list of processes.
*
@@ -2219,6 +2350,24 @@ public final class ProcessStats implements Parcelable {
longs[(off>>OFFSET_INDEX_SHIFT)&OFFSET_INDEX_MASK] += dur;
}
+ void incActiveServices() {
+ if (mCommonProcess != this) {
+ mCommonProcess.incActiveServices();
+ }
+ mNumActiveServices++;
+ }
+
+ void decActiveServices() {
+ if (mCommonProcess != this) {
+ mCommonProcess.decActiveServices();
+ }
+ mNumActiveServices--;
+ if (mNumActiveServices < 0) {
+ throw new IllegalStateException("Proc active services underrun: pkg="
+ + mPackage + " uid=" + mUid + " name=" + mName);
+ }
+ }
+
void incStartedServices(int memFactor, long now) {
if (mCommonProcess != this) {
mCommonProcess.incStartedServices(memFactor, now);
@@ -2406,18 +2555,24 @@ public final class ProcessStats implements Parcelable {
final ProcessStats mStats;
public final String mPackage;
public final String mName;
+ public final String mProcessName;
ProcessState mProc;
- int mActive = 1;
+ int mActive = 0;
- public static final int SERVICE_STARTED = 0;
- public static final int SERVICE_BOUND = 1;
- public static final int SERVICE_EXEC = 2;
- static final int SERVICE_COUNT = 3;
+ public static final int SERVICE_RUN = 0;
+ public static final int SERVICE_STARTED = 1;
+ public static final int SERVICE_BOUND = 2;
+ public static final int SERVICE_EXEC = 3;
+ static final int SERVICE_COUNT = 4;
int[] mDurationsTable;
int mDurationsTableSize;
+ int mRunCount;
+ public int mRunState = STATE_NOTHING;
+ long mRunStartTime;
+
int mStartedCount;
public int mStartedState = STATE_NOTHING;
long mStartedStartTime;
@@ -2430,14 +2585,19 @@ public final class ProcessStats implements Parcelable {
public int mExecState = STATE_NOTHING;
long mExecStartTime;
- public ServiceState(ProcessStats processStats, String pkg, String name, ProcessState proc) {
+ public ServiceState(ProcessStats processStats, String pkg, String name,
+ String processName, ProcessState proc) {
mStats = processStats;
mPackage = pkg;
mName = name;
+ mProcessName = processName;
mProc = proc;
}
public void makeActive() {
+ if (mActive == 0) {
+ mProc.incActiveServices();
+ }
mActive++;
}
@@ -2448,9 +2608,12 @@ public final class ProcessStats implements Parcelable {
Slog.i(TAG, "Making " + this + " inactive", here);
*/
mActive--;
+ if (mActive == 0) {
+ mProc.decActiveServices();
+ }
}
- public boolean isActive() {
+ public boolean isInUse() {
return mActive > 0;
}
@@ -2460,6 +2623,7 @@ public final class ProcessStats implements Parcelable {
int state = (ent>>OFFSET_TYPE_SHIFT)&OFFSET_TYPE_MASK;
addStateTime(state, other.mStats.getLong(ent, 0));
}
+ mRunCount += other.mRunCount;
mStartedCount += other.mStartedCount;
mBoundCount += other.mBoundCount;
mExecCount += other.mExecCount;
@@ -2468,6 +2632,7 @@ public final class ProcessStats implements Parcelable {
void resetSafely(long now) {
mDurationsTable = null;
mDurationsTableSize = 0;
+ mRunCount = mRunState != STATE_NOTHING ? 1 : 0;
mStartedCount = mStartedState != STATE_NOTHING ? 1 : 0;
mBoundCount = mBoundState != STATE_NOTHING ? 1 : 0;
mExecCount = mExecState != STATE_NOTHING ? 1 : 0;
@@ -2481,6 +2646,7 @@ public final class ProcessStats implements Parcelable {
+ printLongOffset(mDurationsTable[i]));
out.writeInt(mDurationsTable[i]);
}
+ out.writeInt(mRunCount);
out.writeInt(mStartedCount);
out.writeInt(mBoundCount);
out.writeInt(mExecCount);
@@ -2493,6 +2659,7 @@ public final class ProcessStats implements Parcelable {
return false;
}
mDurationsTableSize = mDurationsTable != null ? mDurationsTable.length : 0;
+ mRunCount = in.readInt();
mStartedCount = in.readInt();
mBoundCount = in.readInt();
mExecCount = in.readInt();
@@ -2518,6 +2685,10 @@ public final class ProcessStats implements Parcelable {
}
void commitStateTime(long now) {
+ if (mRunState != STATE_NOTHING) {
+ addStateTime(SERVICE_RUN + (mRunState*SERVICE_COUNT), now - mRunStartTime);
+ mRunStartTime = now;
+ }
if (mStartedState != STATE_NOTHING) {
addStateTime(SERVICE_STARTED + (mStartedState*SERVICE_COUNT),
now - mStartedStartTime);
@@ -2533,6 +2704,21 @@ public final class ProcessStats implements Parcelable {
}
}
+ private void updateRunning(int memFactor, long now) {
+ final int state = (mStartedState != STATE_NOTHING || mBoundState != STATE_NOTHING
+ || mExecState != STATE_NOTHING) ? memFactor : STATE_NOTHING;
+ if (mRunState != state) {
+ if (mRunState != STATE_NOTHING) {
+ addStateTime(SERVICE_RUN + (mRunState*SERVICE_COUNT),
+ now - mRunStartTime);
+ } else if (state != STATE_NOTHING) {
+ mRunCount++;
+ }
+ mRunState = state;
+ mRunStartTime = now;
+ }
+ }
+
public void setStarted(boolean started, int memFactor, long now) {
if (mActive <= 0) {
throw new IllegalStateException("Service " + this + " has mActive=" + mActive);
@@ -2556,6 +2742,7 @@ public final class ProcessStats implements Parcelable {
mProc.decStartedServices(memFactor, now);
}
}
+ updateRunning(memFactor, now);
}
}
@@ -2573,6 +2760,7 @@ public final class ProcessStats implements Parcelable {
}
mBoundState = state;
mBoundStartTime = now;
+ updateRunning(memFactor, now);
}
}
@@ -2589,6 +2777,7 @@ public final class ProcessStats implements Parcelable {
}
mExecState = state;
mExecStartTime = now;
+ updateRunning(memFactor, now);
}
}
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index a85d5fef2a21..5538dca2a4fa 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -17,6 +17,7 @@
package com.android.internal.os;
import android.app.ActivityManagerNative;
+import android.app.ActivityThread;
import android.app.ApplicationErrorReport;
import android.os.Build;
import android.os.Debug;
@@ -69,7 +70,14 @@ public class RuntimeInit {
if (mApplicationObject == null) {
Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
} else {
- Slog.e(TAG, "FATAL EXCEPTION: " + t.getName(), e);
+ StringBuilder message = new StringBuilder();
+ message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
+ final String processName = ActivityThread.currentProcessName();
+ if (processName != null) {
+ message.append("Process: ").append(processName).append(", ");
+ }
+ message.append("PID: ").append(Process.myPid());
+ Slog.e(TAG, message.toString(), e);
}
// Bring up crash dialog, wait for it to be dismissed
diff --git a/core/java/com/android/internal/transition/ActionBarTransition.java b/core/java/com/android/internal/transition/ActionBarTransition.java
new file mode 100644
index 000000000000..de597285a146
--- /dev/null
+++ b/core/java/com/android/internal/transition/ActionBarTransition.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.transition;
+
+import android.transition.ChangeBounds;
+import android.transition.Fade;
+import android.transition.TextChange;
+import android.transition.Transition;
+import android.transition.TransitionSet;
+
+public class ActionBarTransition {
+
+ private static final int TRANSITION_DURATION = 120; // ms
+
+ private static final Transition sTransition;
+
+ static {
+ final TextChange tc = new TextChange();
+ tc.setChangeBehavior(TextChange.CHANGE_BEHAVIOR_OUT_IN);
+ final TransitionSet inner = new TransitionSet();
+ inner.addTransition(tc).addTransition(new ChangeBounds());
+ final TransitionSet tg = new TransitionSet();
+ tg.addTransition(new Fade(Fade.OUT)).addTransition(inner).addTransition(new Fade(Fade.IN));
+ tg.setOrdering(TransitionSet.ORDERING_SEQUENTIAL);
+ tg.setDuration(TRANSITION_DURATION);
+ sTransition = tg;
+ }
+
+ public static Transition getActionBarTransition() {
+ return sTransition;
+ }
+}
diff --git a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
index f060efd98451..68c3d0ae2a47 100644
--- a/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
+++ b/core/java/com/android/internal/view/menu/ActionMenuPresenter.java
@@ -21,20 +21,20 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
+import android.transition.Transition;
+import android.transition.TransitionManager;
import android.util.SparseBooleanArray;
import android.view.ActionProvider;
import android.view.MenuItem;
-import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
-import android.view.ViewConfiguration;
import android.view.View.MeasureSpec;
-import android.view.accessibility.AccessibilityNodeInfo;
import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageButton;
import android.widget.ListPopupWindow;
import android.widget.ListPopupWindow.ForwardingListener;
-
+import com.android.internal.transition.ActionBarTransition;
import com.android.internal.view.ActionBarPolicy;
import com.android.internal.view.menu.ActionMenuView.ActionMenuChildView;
@@ -73,6 +73,8 @@ public class ActionMenuPresenter extends BaseMenuPresenter
final PopupPresenterCallback mPopupPresenterCallback = new PopupPresenterCallback();
int mOpenSubMenuId;
+ private static final Transition sTransition = ActionBarTransition.getActionBarTransition();
+
public ActionMenuPresenter(Context context) {
super(context, com.android.internal.R.layout.action_menu_layout,
com.android.internal.R.layout.action_menu_item_layout);
@@ -156,7 +158,7 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
@Override
- public View getItemView(MenuItemImpl item, View convertView, ViewGroup parent) {
+ public View getItemView(final MenuItemImpl item, View convertView, ViewGroup parent) {
View actionView = item.getActionView();
if (actionView == null || item.hasCollapsibleActionView()) {
if (!(convertView instanceof ActionMenuItemView)) {
@@ -166,6 +168,27 @@ public class ActionMenuPresenter extends BaseMenuPresenter
}
actionView.setVisibility(item.isActionViewExpanded() ? View.GONE : View.VISIBLE);
+ if (item.hasSubMenu()) {
+ actionView.setOnTouchListener(new ForwardingListener(actionView) {
+ @Override
+ public ListPopupWindow getPopup() {
+ return mActionButtonPopup != null ? mActionButtonPopup.getPopup() : null;
+ }
+
+ @Override
+ protected boolean onForwardingStarted() {
+ return onSubMenuSelected((SubMenuBuilder) item.getSubMenu());
+ }
+
+ @Override
+ protected boolean onForwardingStopped() {
+ return dismissPopupMenus();
+ }
+ });
+ } else {
+ actionView.setOnTouchListener(null);
+ }
+
final ActionMenuView menuParent = (ActionMenuView) parent;
final ViewGroup.LayoutParams lp = actionView.getLayoutParams();
if (!menuParent.checkLayoutParams(lp)) {
@@ -190,6 +213,10 @@ public class ActionMenuPresenter extends BaseMenuPresenter
@Override
public void updateMenuView(boolean cleared) {
+ final ViewGroup menuViewParent = (ViewGroup) ((View) mMenuView).getParent();
+ if (menuViewParent != null) {
+ TransitionManager.beginDelayedTransition(menuViewParent, sTransition);
+ }
super.updateMenuView(cleared);
if (mMenu != null) {
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index f2bd5224ffcf..969c94babd68 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -29,6 +29,12 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.text.Layout;
import android.text.TextUtils;
+import android.transition.ChangeBounds;
+import android.transition.Fade;
+import android.transition.TextChange;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
import android.util.AttributeSet;
import android.view.CollapsibleActionView;
import android.view.Gravity;
@@ -50,6 +56,7 @@ import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.TextView;
import com.android.internal.R;
+import com.android.internal.transition.ActionBarTransition;
import com.android.internal.view.menu.ActionMenuItem;
import com.android.internal.view.menu.ActionMenuPresenter;
import com.android.internal.view.menu.ActionMenuView;
@@ -97,7 +104,6 @@ public class ActionBarView extends AbsActionBarView {
private LinearLayout mTitleLayout;
private TextView mTitleView;
private TextView mSubtitleView;
- private View mTitleUpView;
private ViewGroup mUpGoerFive;
private Spinner mSpinner;
@@ -138,6 +144,8 @@ public class ActionBarView extends AbsActionBarView {
Window.Callback mWindowCallback;
+ private final static Transition sTransition = ActionBarTransition.getActionBarTransition();
+
private final AdapterView.OnItemSelectedListener mNavItemSelectedListener =
new AdapterView.OnItemSelectedListener() {
public void onItemSelected(AdapterView parent, View view, int position, long id) {
@@ -198,7 +206,7 @@ public class ActionBarView extends AbsActionBarView {
mHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
mExpandedHomeLayout = (HomeView) inflater.inflate(homeResId, mUpGoerFive, false);
- mExpandedHomeLayout.setUp(true);
+ mExpandedHomeLayout.setShowUp(true);
mExpandedHomeLayout.setOnClickListener(mExpandedActionViewUpListener);
mExpandedHomeLayout.setContentDescription(getResources().getText(
R.string.action_bar_up_description));
@@ -251,7 +259,6 @@ public class ActionBarView extends AbsActionBarView {
mTitleView = null;
mSubtitleView = null;
- mTitleUpView = null;
if (mTitleLayout != null && mTitleLayout.getParent() == mUpGoerFive) {
mUpGoerFive.removeView(mTitleLayout);
}
@@ -475,6 +482,9 @@ public class ActionBarView extends AbsActionBarView {
public void setCustomNavigationView(View view) {
final boolean showCustom = (mDisplayOptions & ActionBar.DISPLAY_SHOW_CUSTOM) != 0;
+ if (showCustom) {
+ TransitionManager.beginDelayedTransition(this, sTransition);
+ }
if (mCustomNavView != null && showCustom) {
removeView(mCustomNavView);
}
@@ -512,6 +522,7 @@ public class ActionBarView extends AbsActionBarView {
}
private void setTitleImpl(CharSequence title) {
+ TransitionManager.beginDelayedTransition(this, sTransition);
mTitle = title;
if (mTitleView != null) {
mTitleView.setText(title);
@@ -531,6 +542,7 @@ public class ActionBarView extends AbsActionBarView {
}
public void setSubtitle(CharSequence subtitle) {
+ TransitionManager.beginDelayedTransition(this, sTransition);
mSubtitle = subtitle;
if (mSubtitleView != null) {
mSubtitleView.setText(subtitle);
@@ -611,13 +623,11 @@ public class ActionBarView extends AbsActionBarView {
mDisplayOptions = options;
if ((flagsChanged & DISPLAY_RELAYOUT_MASK) != 0) {
- final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
- final int vis = showHome && mExpandedActionView == null ? VISIBLE : GONE;
- mHomeLayout.setVisibility(vis);
+ TransitionManager.beginDelayedTransition(this, sTransition);
if ((flagsChanged & ActionBar.DISPLAY_HOME_AS_UP) != 0) {
final boolean setUp = (options & ActionBar.DISPLAY_HOME_AS_UP) != 0;
- mHomeLayout.setUp(setUp);
+ mHomeLayout.setShowUp(setUp);
// Showing home as up implicitly enables interaction with it.
// In honeycomb it was always enabled, so make this transition
@@ -641,11 +651,14 @@ public class ActionBarView extends AbsActionBarView {
}
}
- if (mTitleLayout != null && (flagsChanged &
- (ActionBar.DISPLAY_HOME_AS_UP | ActionBar.DISPLAY_SHOW_HOME)) != 0) {
- final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
- mTitleUpView.setVisibility(!showHome ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
- }
+ final boolean showHome = (options & ActionBar.DISPLAY_SHOW_HOME) != 0;
+ final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
+ final boolean titleUp = !showHome && homeAsUp;
+ mHomeLayout.setShowIcon(showHome);
+
+ final int homeVis = (showHome || titleUp) && mExpandedActionView == null ?
+ VISIBLE : GONE;
+ mHomeLayout.setVisibility(homeVis);
if ((flagsChanged & ActionBar.DISPLAY_SHOW_CUSTOM) != 0 && mCustomNavView != null) {
if ((options & ActionBar.DISPLAY_SHOW_CUSTOM) != 0) {
@@ -724,6 +737,7 @@ public class ActionBarView extends AbsActionBarView {
public void setNavigationMode(int mode) {
final int oldMode = mNavigationMode;
if (mode != oldMode) {
+ TransitionManager.beginDelayedTransition(this, sTransition);
switch (oldMode) {
case ActionBar.NAVIGATION_MODE_LIST:
if (mListNavLayout != null) {
@@ -829,7 +843,6 @@ public class ActionBarView extends AbsActionBarView {
this, false);
mTitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_title);
mSubtitleView = (TextView) mTitleLayout.findViewById(R.id.action_bar_subtitle);
- mTitleUpView = (View) mTitleLayout.findViewById(R.id.up);
if (mTitleStyleRes != 0) {
mTitleView.setTextAppearance(mContext, mTitleStyleRes);
@@ -845,13 +858,9 @@ public class ActionBarView extends AbsActionBarView {
mSubtitleView.setText(mSubtitle);
mSubtitleView.setVisibility(VISIBLE);
}
-
- final boolean homeAsUp = (mDisplayOptions & ActionBar.DISPLAY_HOME_AS_UP) != 0;
- final boolean showHome = (mDisplayOptions & ActionBar.DISPLAY_SHOW_HOME) != 0;
- final boolean showTitleUp = !showHome;
- mTitleUpView.setVisibility(showTitleUp ? (homeAsUp ? VISIBLE : INVISIBLE) : GONE);
}
+ TransitionManager.beginDelayedTransition(this, sTransition);
mUpGoerFive.addView(mTitleLayout);
if (mExpandedActionView != null ||
(TextUtils.isEmpty(mTitle) && TextUtils.isEmpty(mSubtitle))) {
@@ -955,25 +964,32 @@ public class ActionBarView extends AbsActionBarView {
int leftOfCenter = availableWidth / 2;
int rightOfCenter = leftOfCenter;
+ final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
+ (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+
HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
- int homeWidth = 0;
- if (homeLayout.getVisibility() != GONE && homeLayout.getParent() == mUpGoerFive) {
- final ViewGroup.LayoutParams lp = homeLayout.getLayoutParams();
- int homeWidthSpec;
- if (lp.width < 0) {
- homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
- } else {
- homeWidthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
- }
+ final ViewGroup.LayoutParams homeLp = homeLayout.getLayoutParams();
+ int homeWidthSpec;
+ if (homeLp.width < 0) {
+ homeWidthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
+ } else {
+ homeWidthSpec = MeasureSpec.makeMeasureSpec(homeLp.width, MeasureSpec.EXACTLY);
+ }
+
+ /*
+ * This is a little weird.
+ * We're only measuring the *home* affordance within the Up container here
+ * on purpose, because we want to give the available space to all other views before
+ * the title text. We'll remeasure the whole up container again later.
+ * We need to measure this container so we know the right offset for the up affordance
+ * no matter what.
+ */
+ homeLayout.measure(homeWidthSpec, exactHeightSpec);
- /*
- * This is a little weird.
- * We're only measuring the *home* affordance within the Up container here
- * on purpose, because we want to give the available space to all other views before
- * the title text. We'll remeasure the whole up container again later.
- */
- homeLayout.measure(homeWidthSpec, exactHeightSpec);
+ int homeWidth = 0;
+ if ((homeLayout.getVisibility() != GONE && homeLayout.getParent() == mUpGoerFive)
+ || showTitle) {
homeWidth = homeLayout.getMeasuredWidth();
final int homeOffsetWidth = homeWidth + homeLayout.getStartOffset();
availableWidth = Math.max(0, availableWidth - homeOffsetWidth);
@@ -993,9 +1009,6 @@ public class ActionBarView extends AbsActionBarView {
rightOfCenter - mIndeterminateProgressView.getMeasuredWidth());
}
- final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
- (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-
if (mExpandedActionView == null) {
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_LIST:
@@ -1124,7 +1137,7 @@ public class ActionBarView extends AbsActionBarView {
}
final boolean isLayoutRtl = isLayoutRtl();
- final int direction = isLayoutRtl ? +1 : -1;
+ final int direction = isLayoutRtl ? 1 : -1;
int menuStart = isLayoutRtl ? getPaddingLeft() : r - l - getPaddingRight();
// In LTR mode, we start from left padding and go to the right; in RTL mode, we start
// from the padding right and go to the left (in reverse way)
@@ -1132,8 +1145,16 @@ public class ActionBarView extends AbsActionBarView {
final int y = getPaddingTop();
HomeView homeLayout = mExpandedActionView != null ? mExpandedHomeLayout : mHomeLayout;
- final int startOffset = homeLayout.getVisibility() != GONE &&
- homeLayout.getParent() == mUpGoerFive ? homeLayout.getStartOffset() : 0;
+ final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
+ (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
+ int startOffset = 0;
+ if (homeLayout.getParent() == mUpGoerFive) {
+ if (homeLayout.getVisibility() != GONE) {
+ startOffset = homeLayout.getStartOffset();
+ } else if (showTitle) {
+ startOffset = homeLayout.getUpWidth();
+ }
+ }
// Position the up container based on where the edge of the home layout should go.
x += positionChild(mUpGoerFive,
@@ -1141,9 +1162,6 @@ public class ActionBarView extends AbsActionBarView {
x = next(x, startOffset, isLayoutRtl);
if (mExpandedActionView == null) {
- final boolean showTitle = mTitleLayout != null && mTitleLayout.getVisibility() != GONE &&
- (mDisplayOptions & ActionBar.DISPLAY_SHOW_TITLE) != 0;
-
switch (mNavigationMode) {
case ActionBar.NAVIGATION_MODE_STANDARD:
break;
@@ -1374,6 +1392,7 @@ public class ActionBarView extends AbsActionBarView {
private ImageView mUpView;
private ImageView mIconView;
private int mUpWidth;
+ private int mStartOffset;
private int mUpIndicatorRes;
private Drawable mDefaultUpIndicator;
@@ -1392,10 +1411,14 @@ public class ActionBarView extends AbsActionBarView {
}
}
- public void setUp(boolean isUp) {
+ public void setShowUp(boolean isUp) {
mUpView.setVisibility(isUp ? VISIBLE : GONE);
}
+ public void setShowIcon(boolean showIcon) {
+ mIconView.setVisibility(showIcon ? VISIBLE : GONE);
+ }
+
public void setIcon(Drawable icon) {
mIconView.setImageDrawable(icon);
}
@@ -1448,21 +1471,33 @@ public class ActionBarView extends AbsActionBarView {
}
public int getStartOffset() {
- return mUpView.getVisibility() == GONE ? mUpWidth : 0;
+ return mUpView.getVisibility() == GONE ? mStartOffset : 0;
+ }
+
+ public int getUpWidth() {
+ return mUpWidth;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
measureChildWithMargins(mUpView, widthMeasureSpec, 0, heightMeasureSpec, 0);
final LayoutParams upLp = (LayoutParams) mUpView.getLayoutParams();
- mUpWidth = upLp.leftMargin + mUpView.getMeasuredWidth() + upLp.rightMargin;
- int width = mUpView.getVisibility() == GONE ? 0 : mUpWidth;
+ final int upMargins = upLp.leftMargin + upLp.rightMargin;
+ mUpWidth = mUpView.getMeasuredWidth();
+ mStartOffset = mUpWidth + upMargins;
+ int width = mUpView.getVisibility() == GONE ? 0 : mStartOffset;
int height = upLp.topMargin + mUpView.getMeasuredHeight() + upLp.bottomMargin;
- measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
- final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
- width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
- height = Math.max(height,
- iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
+
+ if (mIconView.getVisibility() != GONE) {
+ measureChildWithMargins(mIconView, widthMeasureSpec, width, heightMeasureSpec, 0);
+ final LayoutParams iconLp = (LayoutParams) mIconView.getLayoutParams();
+ width += iconLp.leftMargin + mIconView.getMeasuredWidth() + iconLp.rightMargin;
+ height = Math.max(height,
+ iconLp.topMargin + mIconView.getMeasuredHeight() + iconLp.bottomMargin);
+ } else if (upMargins < 0) {
+ // Remove the measurement effects of negative margins used for offsets
+ width -= upMargins;
+ }
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
diff --git a/core/java/com/android/internal/widget/AutoScrollHelper.java b/core/java/com/android/internal/widget/AutoScrollHelper.java
index afa410338cda..7a294aa52401 100644
--- a/core/java/com/android/internal/widget/AutoScrollHelper.java
+++ b/core/java/com/android/internal/widget/AutoScrollHelper.java
@@ -66,7 +66,7 @@ import android.widget.AbsListView;
* The following scrolling properties may be configured:
* <ul>
* <li>Acceleration ramp-up duration, see {@link #setRampUpDuration}. Default
- * value is 2500 milliseconds.
+ * value is 500 milliseconds.
* <li>Acceleration ramp-down duration, see {@link #setRampDownDuration}.
* Default value is 500 milliseconds.
* <li>Target velocity relative to view size, see {@link #setRelativeVelocity}.
@@ -191,7 +191,7 @@ public abstract class AutoScrollHelper implements View.OnTouchListener {
private static final float DEFAULT_RELATIVE_EDGE = 0.2f;
private static final float DEFAULT_RELATIVE_VELOCITY = 1f;
private static final int DEFAULT_ACTIVATION_DELAY = ViewConfiguration.getTapTimeout();
- private static final int DEFAULT_RAMP_UP_DURATION = 2500;
+ private static final int DEFAULT_RAMP_UP_DURATION = 500;
private static final int DEFAULT_RAMP_DOWN_DURATION = 500;
/**
diff --git a/core/java/com/android/internal/widget/SubtitleView.java b/core/java/com/android/internal/widget/SubtitleView.java
index 131015124d87..356401c2a322 100644
--- a/core/java/com/android/internal/widget/SubtitleView.java
+++ b/core/java/com/android/internal/widget/SubtitleView.java
@@ -74,6 +74,10 @@ public class SubtitleView extends View {
private float mSpacingAdd = 0;
private int mInnerPaddingX = 0;
+ public SubtitleView(Context context) {
+ this(context, null);
+ }
+
public SubtitleView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index a17b301560bd..490d85c4b707 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -53,6 +53,7 @@ extern int register_android_graphics_Bitmap(JNIEnv*);
extern int register_android_graphics_BitmapFactory(JNIEnv*);
extern int register_android_graphics_BitmapRegionDecoder(JNIEnv*);
extern int register_android_graphics_Camera(JNIEnv* env);
+extern int register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env);
extern int register_android_graphics_Graphics(JNIEnv* env);
extern int register_android_graphics_Interpolator(JNIEnv* env);
extern int register_android_graphics_LayerRasterizer(JNIEnv*);
@@ -1137,6 +1138,7 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_graphics_BitmapFactory),
REG_JNI(register_android_graphics_BitmapRegionDecoder),
REG_JNI(register_android_graphics_Camera),
+ REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor),
REG_JNI(register_android_graphics_Canvas),
REG_JNI(register_android_graphics_ColorFilter),
REG_JNI(register_android_graphics_DrawFilter),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 16beb022de0b..f9bb2331482d 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -189,7 +189,13 @@ public:
mSize, bitmap->getSize());
return false;
}
- bitmap->setPixelRef(mPixelRef);
+
+ // Create a new pixelref with the new ctable that wraps the previous pixelref
+ SkPixelRef* pr = new AndroidPixelRef(*static_cast<AndroidPixelRef*>(mPixelRef), ctable);
+
+ bitmap->setPixelRef(pr)->unref();
+ // since we're already allocated, we lockPixels right away
+ // HeapAllocator/JavaPixelAllocator behaves this way too
bitmap->lockPixels();
return true;
}
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index d264392a198c..2d06b681f73d 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -7,12 +7,6 @@
#include "Utils.h"
#include <androidfw/Asset.h>
-#define RETURN_NULL_IF_NULL(value) \
- do { if (!(value)) { SkASSERT(0); return NULL; } } while (false)
-
-#define RETURN_ZERO_IF_NULL(value) \
- do { if (!(value)) { SkASSERT(0); return 0; } } while (false)
-
static jmethodID gInputStream_resetMethodID;
static jmethodID gInputStream_markMethodID;
static jmethodID gInputStream_markSupportedMethodID;
@@ -161,32 +155,6 @@ private:
SkStream* CreateJavaInputStreamAdaptor(JNIEnv* env, jobject stream,
jbyteArray storage) {
- static bool gInited;
-
- if (!gInited) {
- jclass inputStream_Clazz = env->FindClass("java/io/InputStream");
- RETURN_NULL_IF_NULL(inputStream_Clazz);
-
- gInputStream_resetMethodID = env->GetMethodID(inputStream_Clazz,
- "reset", "()V");
- gInputStream_markMethodID = env->GetMethodID(inputStream_Clazz,
- "mark", "(I)V");
- gInputStream_markSupportedMethodID = env->GetMethodID(inputStream_Clazz,
- "markSupported", "()Z");
- gInputStream_readMethodID = env->GetMethodID(inputStream_Clazz,
- "read", "([BII)I");
- gInputStream_skipMethodID = env->GetMethodID(inputStream_Clazz,
- "skip", "(J)J");
-
- RETURN_NULL_IF_NULL(gInputStream_resetMethodID);
- RETURN_NULL_IF_NULL(gInputStream_markMethodID);
- RETURN_NULL_IF_NULL(gInputStream_markSupportedMethodID);
- RETURN_NULL_IF_NULL(gInputStream_readMethodID);
- RETURN_NULL_IF_NULL(gInputStream_skipMethodID);
-
- gInited = true;
- }
-
return new JavaInputStreamAdaptor(env, stream, storage);
}
@@ -263,27 +231,19 @@ private:
const size_t fLength;
};
+static jclass gByteArrayInputStream_Clazz;
+static jfieldID gCountField;
+static jfieldID gPosField;
+
/**
* If jstream is a ByteArrayInputStream, return its remaining length. Otherwise
* return 0.
*/
static size_t get_length_from_byte_array_stream(JNIEnv* env, jobject jstream) {
- static jclass byteArrayInputStream_Clazz;
- static jfieldID countField;
- static jfieldID posField;
-
- byteArrayInputStream_Clazz = env->FindClass("java/io/ByteArrayInputStream");
- RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
-
- countField = env->GetFieldID(byteArrayInputStream_Clazz, "count", "I");
- RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
- posField = env->GetFieldID(byteArrayInputStream_Clazz, "pos", "I");
- RETURN_ZERO_IF_NULL(byteArrayInputStream_Clazz);
-
- if (env->IsInstanceOf(jstream, byteArrayInputStream_Clazz)) {
+ if (env->IsInstanceOf(jstream, gByteArrayInputStream_Clazz)) {
// Return the remaining length, to keep the same behavior of using the rest of the
// stream.
- return env->GetIntField(jstream, countField) - env->GetIntField(jstream, posField);
+ return env->GetIntField(jstream, gCountField) - env->GetIntField(jstream, gPosField);
}
return 0;
}
@@ -321,21 +281,15 @@ SkStreamRewindable* GetRewindableStream(JNIEnv* env, jobject stream,
return adaptor_to_mem_stream(adaptor.get());
}
-android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) {
- static jclass assetInputStream_Clazz;
- static jmethodID getAssetIntMethodID;
-
- assetInputStream_Clazz = env->FindClass("android/content/res/AssetManager$AssetInputStream");
- RETURN_NULL_IF_NULL(assetInputStream_Clazz);
-
- getAssetIntMethodID = env->GetMethodID(assetInputStream_Clazz, "getAssetInt", "()I");
- RETURN_NULL_IF_NULL(getAssetIntMethodID);
+static jclass gAssetInputStream_Clazz;
+static jmethodID gGetAssetIntMethodID;
- if (!env->IsInstanceOf(jstream, assetInputStream_Clazz)) {
+android::AssetStreamAdaptor* CheckForAssetStream(JNIEnv* env, jobject jstream) {
+ if (!env->IsInstanceOf(jstream, gAssetInputStream_Clazz)) {
return NULL;
}
- jint jasset = env->CallIntMethod(jstream, getAssetIntMethodID);
+ jint jasset = env->CallIntMethod(jstream, gGetAssetIntMethodID);
android::Asset* a = reinterpret_cast<android::Asset*>(jasset);
if (NULL == a) {
jniThrowNullPointerException(env, "NULL native asset");
@@ -406,18 +360,57 @@ SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
static bool gInited;
if (!gInited) {
- jclass outputStream_Clazz = env->FindClass("java/io/OutputStream");
- RETURN_NULL_IF_NULL(outputStream_Clazz);
-
- gOutputStream_writeMethodID = env->GetMethodID(outputStream_Clazz,
- "write", "([BII)V");
- RETURN_NULL_IF_NULL(gOutputStream_writeMethodID);
- gOutputStream_flushMethodID = env->GetMethodID(outputStream_Clazz,
- "flush", "()V");
- RETURN_NULL_IF_NULL(gOutputStream_flushMethodID);
gInited = true;
}
return new SkJavaOutputStream(env, stream, storage);
}
+
+static jclass findClassCheck(JNIEnv* env, const char classname[]) {
+ jclass clazz = env->FindClass(classname);
+ SkASSERT(!env->ExceptionCheck());
+ return clazz;
+}
+
+static jfieldID getFieldIDCheck(JNIEnv* env, jclass clazz,
+ const char fieldname[], const char type[]) {
+ jfieldID id = env->GetFieldID(clazz, fieldname, type);
+ SkASSERT(!env->ExceptionCheck());
+ return id;
+}
+
+static jmethodID getMethodIDCheck(JNIEnv* env, jclass clazz,
+ const char methodname[], const char type[]) {
+ jmethodID id = env->GetMethodID(clazz, methodname, type);
+ SkASSERT(!env->ExceptionCheck());
+ return id;
+}
+
+int register_android_graphics_CreateJavaOutputStreamAdaptor(JNIEnv* env) {
+ jclass inputStream_Clazz = findClassCheck(env, "java/io/InputStream");
+ gInputStream_resetMethodID = getMethodIDCheck(env, inputStream_Clazz, "reset", "()V");
+ gInputStream_markMethodID = getMethodIDCheck(env, inputStream_Clazz, "mark", "(I)V");
+ gInputStream_markSupportedMethodID = getMethodIDCheck(env, inputStream_Clazz, "markSupported", "()Z");
+ gInputStream_readMethodID = getMethodIDCheck(env, inputStream_Clazz, "read", "([BII)I");
+ gInputStream_skipMethodID = getMethodIDCheck(env, inputStream_Clazz, "skip", "(J)J");
+
+ gByteArrayInputStream_Clazz = findClassCheck(env, "java/io/ByteArrayInputStream");
+ // Ref gByteArrayInputStream_Clazz so we can continue to refer to it when
+ // calling IsInstance.
+ gByteArrayInputStream_Clazz = (jclass) env->NewGlobalRef(gByteArrayInputStream_Clazz);
+ gCountField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "count", "I");
+ gPosField = getFieldIDCheck(env, gByteArrayInputStream_Clazz, "pos", "I");
+
+ gAssetInputStream_Clazz = findClassCheck(env, "android/content/res/AssetManager$AssetInputStream");
+ // Ref gAssetInputStream_Clazz so we can continue to refer to it when
+ // calling IsInstance.
+ gAssetInputStream_Clazz = (jclass) env->NewGlobalRef(gAssetInputStream_Clazz);
+ gGetAssetIntMethodID = getMethodIDCheck(env, gAssetInputStream_Clazz, "getAssetInt", "()I");
+
+ jclass outputStream_Clazz = findClassCheck(env, "java/io/OutputStream");
+ gOutputStream_writeMethodID = getMethodIDCheck(env, outputStream_Clazz, "write", "([BII)V");
+ gOutputStream_flushMethodID = getMethodIDCheck(env, outputStream_Clazz, "flush", "()V");
+
+ return 0;
+}
diff --git a/core/jni/android/graphics/Graphics.cpp b/core/jni/android/graphics/Graphics.cpp
index ef5b7c91e67a..8cb152db06e3 100644
--- a/core/jni/android/graphics/Graphics.cpp
+++ b/core/jni/android/graphics/Graphics.cpp
@@ -414,7 +414,8 @@ static JNIEnv* vm2env(JavaVM* vm)
///////////////////////////////////////////////////////////////////////////////
AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
- SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)) {
+ SkColorTable* ctable) : SkMallocPixelRef(storage, size, ctable, (storageObj == NULL)),
+ fWrappedPixelRef(NULL) {
SkASSERT(storage);
SkASSERT(env);
@@ -431,8 +432,25 @@ AndroidPixelRef::AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteA
}
+AndroidPixelRef::AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable) :
+ SkMallocPixelRef(wrappedPixelRef.getAddr(), wrappedPixelRef.getSize(), ctable, false),
+ fWrappedPixelRef(wrappedPixelRef.fWrappedPixelRef ?
+ wrappedPixelRef.fWrappedPixelRef : &wrappedPixelRef)
+{
+ SkASSERT(fWrappedPixelRef);
+ SkSafeRef(fWrappedPixelRef);
+
+ // don't need to initialize these, as all the relevant logic delegates to the wrapped ref
+ fStorageObj = NULL;
+ fHasGlobalRef = false;
+ fGlobalRefCnt = 0;
+ fOnJavaHeap = false;
+}
+
AndroidPixelRef::~AndroidPixelRef() {
- if (fOnJavaHeap) {
+ if (fWrappedPixelRef) {
+ SkSafeUnref(fWrappedPixelRef);
+ } else if (fOnJavaHeap) {
JNIEnv* env = vm2env(fVM);
if (fStorageObj && fHasGlobalRef) {
@@ -441,14 +459,32 @@ AndroidPixelRef::~AndroidPixelRef() {
fStorageObj = NULL;
}
}
+jbyteArray AndroidPixelRef::getStorageObj() {
+ if (fWrappedPixelRef) {
+ return fWrappedPixelRef->fStorageObj;
+ }
+ return fStorageObj;
+}
void AndroidPixelRef::setLocalJNIRef(jbyteArray arr) {
- if (!fHasGlobalRef) {
+ if (fWrappedPixelRef) {
+ // delegate java obj management to the wrapped ref
+ fWrappedPixelRef->setLocalJNIRef(arr);
+ } else if (!fHasGlobalRef) {
fStorageObj = arr;
}
}
void AndroidPixelRef::globalRef(void* localref) {
+ if (fWrappedPixelRef) {
+ // delegate java obj management to the wrapped ref
+ fWrappedPixelRef->globalRef(localref);
+
+ // Note: we only ref and unref the wrapped AndroidPixelRef so that
+ // bitmap->pixelRef()->globalRef() and globalUnref() can be used in a pair, even if
+ // the bitmap has its underlying AndroidPixelRef swapped out/wrapped
+ return;
+ }
if (fOnJavaHeap && sk_atomic_inc(&fGlobalRefCnt) == 0) {
JNIEnv *env = vm2env(fVM);
@@ -473,6 +509,11 @@ void AndroidPixelRef::globalRef(void* localref) {
}
void AndroidPixelRef::globalUnref() {
+ if (fWrappedPixelRef) {
+ // delegate java obj management to the wrapped ref
+ fWrappedPixelRef->globalUnref();
+ return;
+ }
if (fOnJavaHeap && sk_atomic_dec(&fGlobalRefCnt) == 1) {
JNIEnv *env = vm2env(fVM);
if (!fHasGlobalRef) {
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 5a2a6f826fbc..f4590b956d78 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -91,9 +91,16 @@ public:
AndroidPixelRef(JNIEnv* env, void* storage, size_t size, jbyteArray storageObj,
SkColorTable* ctable);
+ /**
+ * Creates an AndroidPixelRef that wraps (and refs) another to reuse/share
+ * the same storage and java byte array refcounting, yet have a different
+ * color table.
+ */
+ AndroidPixelRef(AndroidPixelRef& wrappedPixelRef, SkColorTable* ctable);
+
virtual ~AndroidPixelRef();
- jbyteArray getStorageObj() { return fStorageObj; }
+ jbyteArray getStorageObj();
void setLocalJNIRef(jbyteArray arr);
@@ -110,6 +117,8 @@ public:
virtual void globalUnref();
private:
+ AndroidPixelRef* const fWrappedPixelRef; // if set, delegate memory management calls to this
+
JavaVM* fVM;
bool fOnJavaHeap; // If true, the memory was allocated on the Java heap
diff --git a/core/jni/android/graphics/SurfaceTexture.cpp b/core/jni/android/graphics/SurfaceTexture.cpp
index bacfdf6ae8d1..0c9b3bcac270 100644
--- a/core/jni/android/graphics/SurfaceTexture.cpp
+++ b/core/jni/android/graphics/SurfaceTexture.cpp
@@ -37,7 +37,7 @@
namespace android {
static const char* const OutOfResourcesException =
- "android/graphics/SurfaceTexture$OutOfResourcesException";
+ "android/view/Surface$OutOfResourcesException";
static const char* const IllegalStateException = "java/lang/IllegalStateException";
const char* const kSurfaceTextureClassPathName = "android/graphics/SurfaceTexture";
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 2e479283f147..d4ca5a0b2d82 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -899,6 +899,13 @@
android:label="@string/permlab_wakeLock"
android:description="@string/permdesc_wakeLock" />
+ <!-- Allows using the device's IR transmitter, if available -->
+ <permission android:name="android.permission.TRANSMIT_IR"
+ android:permissionGroup="android.permission-group.AFFECTS_BATTERY"
+ android:protectionLevel="normal"
+ android:label="@string/permlab_transmitIr"
+ android:description="@string/permdesc_transmitIr" />
+
<!-- ==================================================== -->
<!-- Permissions related to changing audio settings -->
<!-- ==================================================== -->
@@ -1096,6 +1103,12 @@
android:description="@string/permdesc_use_sip"
android:label="@string/permlab_use_sip" />
+ <!-- Allows an application to request CallHandlerService implementations. -->
+ <permission android:name="android.permission.BIND_CALL_SERVICE"
+ android:permissionGroup="android.permission-group.PHONE_CALLS"
+ android:protectionLevel="system" />
+
+
<!-- ================================== -->
<!-- Permissions for sdcard interaction -->
<!-- ================================== -->
@@ -2444,13 +2457,6 @@
android:description="@string/permdesc_accessNetworkConditions"
android:protectionLevel="signature|system" />
- <!-- Allows an application to request HotwordRecognition.
- @hide This is not a third-party API (intended for system apps). -->
- <permission android:name="android.permission.HOTWORD_RECOGNITION"
- android:label="@string/permlab_hotwordRecognition"
- android:description="@string/permdesc_hotwordRecognition"
- android:protectionLevel="signature|system" />
-
<!-- The system process is explicitly the only one allowed to launch the
confirmation UI for full backup/restore -->
<uses-permission android:name="android.permission.CONFIRM_FULL_BACKUP"/>
diff --git a/core/res/res/drawable-hdpi/activity_picker_bg_activated.9.png b/core/res/res/drawable-hdpi/activity_picker_bg_activated.9.png
deleted file mode 100644
index e591a7b009ad..000000000000
--- a/core/res/res/drawable-hdpi/activity_picker_bg_activated.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/activity_picker_bg_focused.9.png b/core/res/res/drawable-hdpi/activity_picker_bg_focused.9.png
deleted file mode 100644
index ea27290d76dd..000000000000
--- a/core/res/res/drawable-hdpi/activity_picker_bg_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/activity_picker_bg_activated.9.png b/core/res/res/drawable-mdpi/activity_picker_bg_activated.9.png
deleted file mode 100644
index 7dfea4c00546..000000000000
--- a/core/res/res/drawable-mdpi/activity_picker_bg_activated.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/activity_picker_bg_focused.9.png b/core/res/res/drawable-mdpi/activity_picker_bg_focused.9.png
deleted file mode 100644
index 99b027946926..000000000000
--- a/core/res/res/drawable-mdpi/activity_picker_bg_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-nodpi/view_accessibility_focused.9.png b/core/res/res/drawable-nodpi/view_accessibility_focused.9.png
deleted file mode 100644
index f03f57503466..000000000000
--- a/core/res/res/drawable-nodpi/view_accessibility_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/activity_picker_bg_activated.9.png b/core/res/res/drawable-xhdpi/activity_picker_bg_activated.9.png
deleted file mode 100644
index f01a79e3bf44..000000000000
--- a/core/res/res/drawable-xhdpi/activity_picker_bg_activated.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/activity_picker_bg_focused.9.png b/core/res/res/drawable-xhdpi/activity_picker_bg_focused.9.png
deleted file mode 100644
index 7bea197d0c51..000000000000
--- a/core/res/res/drawable-xhdpi/activity_picker_bg_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/activity_picker_bg_activated.9.png b/core/res/res/drawable-xxhdpi/activity_picker_bg_activated.9.png
deleted file mode 100644
index 47bc2b59f141..000000000000
--- a/core/res/res/drawable-xxhdpi/activity_picker_bg_activated.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/activity_picker_bg_focused.9.png b/core/res/res/drawable-xxhdpi/activity_picker_bg_focused.9.png
deleted file mode 100644
index 3bd381d9e293..000000000000
--- a/core/res/res/drawable-xxhdpi/activity_picker_bg_focused.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/activity_picker_bg.xml b/core/res/res/drawable/activity_picker_bg.xml
deleted file mode 100644
index a471c949a4f6..000000000000
--- a/core/res/res/drawable/activity_picker_bg.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 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.
--->
-
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-
- <item android:state_window_focused="false" android:drawable="@color/transparent" />
-
- <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
- <item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@drawable/list_selector_disabled_holo_light" />
- <item android:state_focused="true" android:state_enabled="false" android:drawable="@drawable/list_selector_disabled_holo_light" />
- <item android:state_focused="true" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_light" />
- <item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/list_selector_background_transition_holo_light" />
- <item android:state_focused="true" android:drawable="@drawable/activity_picker_bg_focused" />
- <item android:state_activated="true" android:drawable="@drawable/activity_picker_bg_activated" />
- <item android:drawable="@color/transparent" />
-
-</selector>
diff --git a/core/res/res/drawable/view_accessibility_focused.xml b/core/res/res/drawable/view_accessibility_focused.xml
new file mode 100644
index 000000000000..0da9a81bd8fb
--- /dev/null
+++ b/core/res/res/drawable/view_accessibility_focused.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <stroke
+ android:width="2dp"
+ android:color="@color/accessibility_focus_highlight" />
+
+ <corners android:radius="2dp"/>
+
+</shape>
diff --git a/core/res/res/layout/action_bar_title_item.xml b/core/res/res/layout/action_bar_title_item.xml
index ccc5b07d694f..fecfded83793 100644
--- a/core/res/res/layout/action_bar_title_item.xml
+++ b/core/res/res/layout/action_bar_title_item.xml
@@ -16,33 +16,20 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:paddingEnd="8dip"
- android:enabled="false">
-
- <ImageView android:id="@android:id/up"
- android:src="?android:attr/homeAsUpIndicator"
- android:layout_gravity="center_vertical|start"
- android:visibility="gone"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content" />
-
- <LinearLayout android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_vertical|start"
- android:orientation="vertical">
- <TextView android:id="@+id/action_bar_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="end" />
- <TextView android:id="@+id/action_bar_subtitle"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/action_bar_subtitle_top_margin"
- android:singleLine="true"
- android:ellipsize="end"
- android:visibility="gone" />
- </LinearLayout>
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_vertical|start"
+ android:orientation="vertical"
+ android:paddingEnd="8dp">
+ <TextView android:id="@+id/action_bar_title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:singleLine="true"
+ android:ellipsize="end" />
+ <TextView android:id="@+id/action_bar_subtitle"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/action_bar_subtitle_top_margin"
+ android:singleLine="true"
+ android:ellipsize="end"
+ android:visibility="gone" />
</LinearLayout>
diff --git a/core/res/res/layout/resolve_list_item.xml b/core/res/res/layout/resolve_list_item.xml
index 28c5b74e6f96..281541b4ceb6 100644
--- a/core/res/res/layout/resolve_list_item.xml
+++ b/core/res/res/layout/resolve_list_item.xml
@@ -21,7 +21,7 @@
android:orientation="horizontal"
android:layout_height="wrap_content"
android:layout_width="match_parent"
- android:background="@android:drawable/activity_picker_bg">
+ android:background="?attr/activatedBackgroundIndicator">
<!-- Activity icon when presenting dialog
Size will be filled in by ResolverActivity -->
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index 59749d41830d..5a693b3d5ebb 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Laat die houer toe om die opstellingsprogram wat deur die diensverskaffer voorsien word, op te roep. Behoort nooit vir gewone programme nodig te wees nie."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"luister vir waarnemings oor netwerktoestande"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Laat \'n program luister vir waarnemings oor netwerktoestande. Behoort nooit nodig te wees vir normale programme nie."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Stel wagwoordreëls"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Beheer lengte en watter karakters wat in die skermontsluit-wagwoorde gebruik word."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor pogings om skerm te ontsluit"</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 8e782a3c1fdf..8bc211dcaa94 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ያዢው በድምጸ-ተያያዥ ሞደም የቀረበው የውቅር መተግበሪያውን እንዲጠራው ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"በአውታረ መረብ ሁኔታዎች ላይ የተስተዋሉ ነገሮችን ያዳምጣል"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"አንድ መተግበሪያ በአውታረ መረብ ሁኔታዎች ላይ የተስተዋሉ ነገሮችን እንዲያዳምጥ ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አስፈላጊ ሊሆን አይገባም።"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ድንቦች አዘጋጅ"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና ቁምፊዎች ተቆጣጠር።"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
@@ -964,7 +968,7 @@
<string name="oneMonthDurationPast" msgid="7396384508953779925">"ከ1 ወር በፊት"</string>
<string name="beforeOneMonthDurationPast" msgid="909134546836499826">"ከ1 ወር በፊት"</string>
<plurals name="num_seconds_ago">
- <item quantity="one" msgid="4869870056547896011">"ከ1 ሰከንድ በፊት"</item>
+ <item quantity="one" msgid="4869870056547896011">"ከ1 ሴኮንድ በፊት"</item>
<item quantity="other" msgid="3903706804349556379">"<xliff:g id="COUNT">%d</xliff:g> ሰኮንዶች በፊት"</item>
</plurals>
<plurals name="num_minutes_ago">
@@ -985,7 +989,7 @@
<item quantity="other" msgid="2479586466153314633">"ከ <xliff:g id="COUNT">%d</xliff:g>ቀን በፊት"</item>
</plurals>
<plurals name="in_num_seconds">
- <item quantity="one" msgid="2729745560954905102">"በ1 ሰከንድ"</item>
+ <item quantity="one" msgid="2729745560954905102">"በ1 ሴኮንድ"</item>
<item quantity="other" msgid="1241926116443974687">"በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ"</item>
</plurals>
<plurals name="in_num_minutes">
@@ -1001,7 +1005,7 @@
<item quantity="other" msgid="5109449375100953247">"በ<xliff:g id="COUNT">%d</xliff:g> ቀናት"</item>
</plurals>
<plurals name="abbrev_num_seconds_ago">
- <item quantity="one" msgid="1849036840200069118">"1 ሰከንድ በፊት"</item>
+ <item quantity="one" msgid="1849036840200069118">"1 ሴኮንድ በፊት"</item>
<item quantity="other" msgid="3699169366650930415">"<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች በፊት"</item>
</plurals>
<plurals name="abbrev_num_minutes_ago">
@@ -1017,7 +1021,7 @@
<item quantity="other" msgid="3453342639616481191">"ከ <xliff:g id="COUNT">%d</xliff:g>ቀን በፊት"</item>
</plurals>
<plurals name="abbrev_in_num_seconds">
- <item quantity="one" msgid="5842225370795066299">"በ1 ሰከንድ"</item>
+ <item quantity="one" msgid="5842225370795066299">"በ1 ሴኮንድ"</item>
<item quantity="other" msgid="5495880108825805108">"በ<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች ውስጥ"</item>
</plurals>
<plurals name="abbrev_in_num_minutes">
@@ -1041,14 +1045,14 @@
<string name="hours" msgid="894424005266852993">"ሰዓቶች"</string>
<string name="minute" msgid="9148878657703769868">"ደቂቃ"</string>
<string name="minutes" msgid="5646001005827034509">" ደቂቃዎች"</string>
- <string name="second" msgid="3184235808021478">"ሰከንድ"</string>
+ <string name="second" msgid="3184235808021478">"ሴኮንድ"</string>
<string name="seconds" msgid="3161515347216589235">"ሰከንዶች"</string>
<string name="week" msgid="5617961537173061583">"ሳምንት"</string>
<string name="weeks" msgid="6509623834583944518">"ሳምንቶች"</string>
<string name="year" msgid="4001118221013892076">"ዓመት"</string>
<string name="years" msgid="6881577717993213522">"ዓመታት"</string>
<plurals name="duration_seconds">
- <item quantity="one" msgid="6962015528372969481">"1 ሰከንድ"</item>
+ <item quantity="one" msgid="6962015528372969481">"1 ሴኮንድ"</item>
<item quantity="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> ሰከንዶች"</item>
</plurals>
<plurals name="duration_minutes">
@@ -1568,7 +1572,7 @@
<string name="write_fail_reason_cancelled" msgid="7091258378121627624">"ተትቷል"</string>
<string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"ይዘት መጻፍ ላይ ስህተት"</string>
<string name="reason_unknown" msgid="6048913880184628119">"አይታወቅም"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"አስተዳዳሪ ፒን ያስገቡ"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"የአስተዳዳሪ ፒን ያስገቡ"</string>
<string name="restr_pin_enter_pin" msgid="3395953421368476103">"ፒን ያስገቡ"</string>
<string name="restr_pin_incorrect" msgid="8571512003955077924">"ትክክል አይደለም"</string>
<string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"የአሁኑ ፒን"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 8988e2eb52fd..1dd3b6754b3f 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -655,6 +655,8 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"للسماح للمالك باستدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"الاستماع إلى ملاحظات حول أحوال الشبكة"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"للسماح للتطبيق بالاستماع إلى ملاحظات حول أحوال الشبكة. لا حاجة إلى هذا مع التطبيقات العادية."</string>
+ <string name="permlab_hotwordRecognition" msgid="3225080408746361313">"طلب التعرف على الكلمة المهمة"</string>
+ <string name="permdesc_hotwordRecognition" msgid="3716741260195364252">"للسماح للتطبيق بطلب التعرف على الكلمة المهمة. لا حاجة إلى هذا مع التطبيقات العادية."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"تعيين قواعد كلمة المرور"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"يمكنك التحكم في الطول والأحرف المسموح بها في كلمات مرور إلغاء تأمين الشاشة."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"مراقبة محاولات إلغاء قفل الشاشة"</string>
diff --git a/core/res/res/values-az-rAZ/strings.xml b/core/res/res/values-az-rAZ/strings.xml
index 839ac38a7377..e29914eac32f 100644
--- a/core/res/res/values-az-rAZ/strings.xml
+++ b/core/res/res/values-az-rAZ/strings.xml
@@ -655,6 +655,8 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Sahibinə operator xidmətli tətbiq konfiqurasiyasına müraciət imkanı verir. Normal tətbiqlər üçün tələb olunmamalıdır."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"şəbəkə şəraiti haqqında müşahidələr üçün qulaq asmaq"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Tətbiqə şəbəkə şəraiti üzrə müşahidələr üçün qulaq asmaq imkanı verir. Normal tətbiqlər üçün heç vaxt lazım olmamalıdır."</string>
+ <string name="permlab_hotwordRecognition" msgid="3225080408746361313">"isti söz tanınması tələb et"</string>
+ <string name="permdesc_hotwordRecognition" msgid="3716741260195364252">"Tətbiqə isti söz tanınması tələb etməyə imkan verir. Normal tətbiq üçün lazım ola bilməz."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Parol qaydalarını təyin edin"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Ekran kilidini açan şifrələrin uzunluğunu və onlardakı icazə verilən işarələrə nəzarət edir."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidi cəhdlərini monitorinq et"</string>
diff --git a/core/res/res/values-be/strings.xml b/core/res/res/values-be/strings.xml
index cc799dfd440f..8a1f164e3bb4 100644
--- a/core/res/res/values-be/strings.xml
+++ b/core/res/res/values-be/strings.xml
@@ -680,6 +680,10 @@
<skip />
<!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
<skip />
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Устанавіць правілы паролю"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Кіраванне даўжынёй і колькасцю знакаў у паролі разблакоўкі экрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Сачыць за спробамі разблакоўкі экрана"</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index b9cb281c0d45..10b9fbb21f64 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Разрешава на притежателя да извиква предоставеното от оператора приложение за конфигуриране. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"слушане за наблюдения на мрежовите условия"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Разрешава на приложението да слуша за наблюдения на мрежовите условия. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Задаване на правила за паролата"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролирайте дължината и разрешените знаци за паролите за отключване на екрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Наблюдаване на опитите за отключване на екрана"</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 4ed06643344f..c83bd27b1cba 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -530,13 +530,13 @@
<string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"iniciar directament la configuració del telèfon CDMA"</string>
<string name="permdesc_performCdmaProvisioning" msgid="1994193538802314186">"Permet que l\'aplicació iniciï l\'aprovisionament CDMA. Les aplicacions malicioses poden iniciar l\'aprovisionament CDMA innecessàriament."</string>
<string name="permlab_locationUpdates" msgid="7785408253364335740">"controlar les notificacions d\'actualització de la ubicació"</string>
- <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permet que l\'aplicació activi i desactivi les notificacions d\'actualització de la ubicació de la ràdio. No la poden fer servir les aplicacions normals."</string>
+ <string name="permdesc_locationUpdates" msgid="1120741557891438876">"Permet que l\'aplicació activi i desactivi les notificacions d\'actualització de la ubicació del senyal mòbil. No la poden fer servir les aplicacions normals."</string>
<string name="permlab_checkinProperties" msgid="7855259461268734914">"accedir a les propietats d\'accés"</string>
<string name="permdesc_checkinProperties" msgid="4024526968630194128">"Permet a l\'aplicació l\'accés de lectura/escriptura a les propietats penjades pel servei de registre. No es pot fer servir per a les aplicacions normals."</string>
<string name="permlab_bindGadget" msgid="776905339015863471">"triar widgets"</string>
<string name="permdesc_bindGadget" msgid="8261326938599049290">"Permet que l\'aplicació indiqui al sistema quins widgets pot utilitzar cada aplicació. Amb aquest permís, les aplicacions poden concedir accés a les dades personals a altres aplicacions. No indicat per a les aplicacions normals."</string>
<string name="permlab_modifyPhoneState" msgid="8423923777659292228">"modificar l\'estat del telèfon"</string>
- <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Permet que l\'aplicació controli les funcions de telèfon del dispositiu. Una aplicació amb aquest permís pot canviar de xarxa, activar i desactivar la ràdio del telèfon i dur a terme accions semblants sense notificar-t\'ho."</string>
+ <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Permet que l\'aplicació controli les funcions de telèfon del dispositiu. Una aplicació amb aquest permís pot canviar de xarxa, activar i desactivar el senyal mòbil i dur a terme accions semblants sense notificar-t\'ho."</string>
<string name="permlab_readPhoneState" msgid="9178228524507610486">"veure l\'estat i la identitat del telèfon"</string>
<string name="permdesc_readPhoneState" msgid="1639212771826125528">"Permet que l\'aplicació accedeixi a les funcions de telèfon del dispositiu. Aquest permís permet que l\'aplicació determini el número de telèfon i els identificadors del dispositiu, si hi ha una trucada activa i el número remot connectat amb una trucada."</string>
<string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"evita que la tauleta entri en mode d\'inactivitat"</string>
@@ -593,14 +593,14 @@
<string name="permdesc_changeWifiMulticastState" product="tablet" msgid="7969774021256336548">"Permet que l\'aplicació rebi paquets enviats a tots els dispositius d\'una xarxa Wi-Fi mitjançant les adreces multidifusió, no només a la teva tauleta. Fa servir més energia que el mode que no és multidifusió."</string>
<string name="permdesc_changeWifiMulticastState" product="default" msgid="6851949706025349926">"Permet que l\'aplicació rebi paquets enviats a tots els dispositius d\'una xarxa Wi-Fi mitjançant les adreces multidifusió, no només al teu telèfon. Fa servir més energia que el mode que no és multidifusió."</string>
<string name="permlab_bluetoothAdmin" msgid="6006967373935926659">"accés a la configuració de Bluetooth"</string>
- <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permet que l\'aplicació configuri la tauleta Bluetooth local i que cerqui i sincronitzi dispositius remots."</string>
- <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permet que l\'aplicació configuri el telèfon Bluetooth local i que cerqui i sincronitzi dispositius remots."</string>
+ <string name="permdesc_bluetoothAdmin" product="tablet" msgid="6921177471748882137">"Permet que l\'aplicació configuri la tauleta Bluetooth local i que detecti i emparelli dispositius remots."</string>
+ <string name="permdesc_bluetoothAdmin" product="default" msgid="8931682159331542137">"Permet que l\'aplicació configuri el telèfon Bluetooth local i que detecti i emparelli dispositius remots."</string>
<string name="permlab_accessWimaxState" msgid="4195907010610205703">"connecta i desconnecta de WiMAX"</string>
<string name="permdesc_accessWimaxState" msgid="6360102877261978887">"Permet que l\'aplicació determini si WiMAX està activat i que vegi la informació sobre totes les xarxes WiMAX que estan connectades."</string>
<string name="permlab_changeWimaxState" msgid="2405042267131496579">"Canvia l\'estat de WiMAX"</string>
<string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet que l\'aplicació connecti i desconnecti la tauleta de les xarxes WiMAX."</string>
<string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permet que l\'aplicació connecti i desconnecti el telèfon de les xarxes WiMAX."</string>
- <string name="permlab_bluetooth" msgid="6127769336339276828">"sincronització amb dispositius Bluetooth"</string>
+ <string name="permlab_bluetooth" msgid="6127769336339276828">"emparella amb dispositius Bluetooth"</string>
<string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet que l\'aplicació visualitzi la configuració de Bluetooth de la tauleta i que estableixi i accepti connexions amb dispositius sincronitzats."</string>
<string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet que una aplicació visualitzi la configuració de Bluetooth del telèfon i que estableixi i accepti connexions amb els dispositius sincronitzats."</string>
<string name="permlab_nfc" msgid="4423351274757876953">"controla Near Field Communication (NFC)"</string>
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet que el titular invoqui l\'aplicació de configuració proporcionada per l\'operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"conèixer les observacions sobre les condicions de la xarxa"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet que una aplicació conegui les observacions sobre les condicions de la xarxa. No s\'ha de necessitar mai per a aplicacions normals."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Defineix les normes de contrasenya"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Control d\'intents de desbloqueig de pantalla"</string>
@@ -734,7 +738,7 @@
<string name="phoneTypeIsdn" msgid="8022453193171370337">"XDSI"</string>
<string name="phoneTypeMain" msgid="6766137010628326916">"Principal"</string>
<string name="phoneTypeOtherFax" msgid="8587657145072446565">"Altres faxos"</string>
- <string name="phoneTypeRadio" msgid="4093738079908667513">"Ràdio"</string>
+ <string name="phoneTypeRadio" msgid="4093738079908667513">"Senyal mòbil"</string>
<string name="phoneTypeTelex" msgid="3367879952476250512">"Tèlex"</string>
<string name="phoneTypeTtyTdd" msgid="8606514378585000044">"TTY TDD"</string>
<string name="phoneTypeWorkMobile" msgid="1311426989184065709">"Mòbil de la feina"</string>
@@ -1458,7 +1462,7 @@
<string name="default_audio_route_name" product="tablet" msgid="4617053898167127471">"Tauleta"</string>
<string name="default_audio_route_name" product="default" msgid="4239291273420140123">"Telèfon"</string>
<string name="default_audio_route_name_headphones" msgid="8119971843803439110">"Auriculars"</string>
- <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altaveus del connector"</string>
+ <string name="default_audio_route_name_dock_speakers" msgid="6240602982276591864">"Altaveus de la base"</string>
<string name="default_media_route_name_hdmi" msgid="2450970399023478055">"HDMI"</string>
<string name="default_audio_route_category_name" msgid="3722811174003886946">"Sistema"</string>
<string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"Àudio per Bluetooth"</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b71ff181bb67..9962533caee2 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje vyvolání konfigurační aplikace poskytnuté operátorem. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"naslouchat informacím o stavu sítě"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Umožňuje aplikaci naslouchat informacím o stavu sítě. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavit pravidla pro heslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Řídit délku hesel pro odemčení obrazovky a povolené znaky."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovat pokusy o odemčení obrazovky"</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index 753625206173..b37c087ada6b 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Tillader, at brugeren aktiverer konfigurationsappen, der er forsynet af mobilselskabet. Dette bør aldrig være nødvendigt for almindelige apps."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"observer netværksforhold"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Tillader, at en applikation observerer netværksforhold. Bør aldrig være nødvendigt for almindelige apps."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Indstil regler for adgangskode"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller længden samt tilladte tegn i adgangskoder til oplåsning af skærmen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåg forsøg på oplåsning af skærm"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 2185a4290ac1..d489d2718844 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ermöglicht dem Inhaber, die vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufzurufen. Sollte für normale Apps nie benötigt werden."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Informationen zu den Netzwerkbedingungen erfassen"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ermöglicht der App, Informationen zu den Netzwerkbedingungen zu erfassen. Sollte für normale Apps nie benötigt werden."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Passwortregeln festlegen"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Zulässige Länge und Zeichen für Passwörter zum Entsperren des Bildschirms festlegen"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Versuche zum Entsperren des Displays überwachen"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 9fb21e61490a..36aff6d1ef60 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Επιτρέπει στον κάτοχο την κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας. Δεν απαιτείται για κανονικές εφαρμογές."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"λήψη παρατηρήσεων σχετικά με την κατάσταση δικτύου"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Επιτρέπει σε μια εφαρμογή να λαμβάνει παρατηρήσεις σχετικά με την κατάσταση δικτύου. Δεν θα πρέπει να απαιτείται ποτέ για κανονικές εφαρμογές."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Ορισμός κανόνων κωδικού πρόσβασης"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Έλεγχος του μεγέθους και των χαρακτήρων που επιτρέπονται στους κωδικούς πρόσβασης ξεκλειδώματος οθόνης."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Παρακολούθηση προσπαθειών ξεκλειδώματος οθόνης"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 936062b81c5f..3db3116d4288 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"listen for observations on network conditions"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 936062b81c5f..3db3116d4288 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"listen for observations on network conditions"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Allows an application to listen for observations on network conditions. Should never be needed for normal apps."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Set password rules"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Control the length and the characters allowed in screen-unlock passwords."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitor screen-unlock attempts"</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index b91438d76a88..0271bc8e8022 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite al propietario ejecutar la aplicación de configuración proporcionada por el proveedor. Las aplicaciones normales no deberían necesitar este permiso."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Detectar cambios en el estado de la red"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que una aplicación detecte cambios en el estado de la red. Las aplicaciones normales no deberían necesitar este permiso."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecer reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas para desbloquear la pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Supervisa los intentos para desbloquear la pantalla"</string>
@@ -1581,7 +1585,7 @@
<item quantity="one" msgid="311050995198548675">"Intentar en 1 s"</item>
<item quantity="other" msgid="4730868920742952817">"Intentar en <xliff:g id="COUNT">%d</xliff:g> s"</item>
</plurals>
- <string name="restr_pin_try_later" msgid="973144472490532377">"Volver a intentar más tarde"</string>
+ <string name="restr_pin_try_later" msgid="973144472490532377">"Vuelve a intentar más tarde."</string>
<string name="transient_navigation_confirmation" msgid="4907844043611123426">"Desliza el borde para ver la barra."</string>
<string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"Desliza el dedo desde el borde de la pantalla para mostrar la barra del sistema."</string>
</resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 620410eeeea1..820ea100c373 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite ejecutar la aplicación de configuración proporcionada por el operador. No debe ser necesario para aplicaciones normales."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar cambios en el estado de la red"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que una aplicación detecte cambios en el estado de la red. No debe ser necesario para aplicaciones normales."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Establecimiento de reglas de contraseña"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar la longitud y los caracteres permitidos en las contraseñas de bloqueo de pantalla"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Control de intentos de bloqueo de pantalla"</string>
@@ -1568,9 +1572,9 @@
<string name="write_fail_reason_cancelled" msgid="7091258378121627624">"Cancelado"</string>
<string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"Error al escribir contenido"</string>
<string name="reason_unknown" msgid="6048913880184628119">"desconocido"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"Introducir PIN de administrador"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"Introduce el PIN del administrador"</string>
<string name="restr_pin_enter_pin" msgid="3395953421368476103">"Introducir PIN"</string>
- <string name="restr_pin_incorrect" msgid="8571512003955077924">"Incorrecta"</string>
+ <string name="restr_pin_incorrect" msgid="8571512003955077924">"Incorrecto"</string>
<string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"PIN actual"</string>
<string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"PIN nuevo"</string>
<string name="restr_pin_confirm_pin" msgid="8501523829633146239">"Confirma tu nuevo PIN"</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index a74334da9cb1..6ea84f3736e8 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lubab omanikul aktiveerida operaatoripoolse konfiguratsioonirakenduse. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"võrgutingimuste teabe kuulamine"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Lubab rakendusel kuulata võrgutingimuste teavet. Ei ole kunagi vajalik tavaliste rakenduste puhul."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Parooli reeglite määramine"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrollige ekraaniluku avamise paroolide pikkust ja tähemärke."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekraani avamiskatsed"</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 019347521ec7..4e6030930523 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"به دارنده اجازه می‌دهد که تنظیمات برنامه شرکت مخابراتی را لغو کند. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"گوش دادن برای بررسی شرایط شبکه"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"به برنامه امکان می‌دهد برای بررسی شرایط شبکه گوش دهد. این امکان هرگز نباید برای برنامه‌های معمولی مورد نیاز باشد."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"تنظیم قوانین رمز ورود"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"طول و نویسه‎های مجاز در گذرواژه‌های بازکردن قفل صفحه را کنترل کنید."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"نمایش تلاش‌های قفل گشایی صفحه"</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index dbd77e0503fe..94a1aeb33353 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Antaa luvanhaltijan käynnistää palveluntarjoajan määrityssovelluksen. Ei tavallisten sovelluksien käyttöön."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"verkon tilahavaintojen kuunteleminen"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Antaa sovellukselle luvan kuunnella verkon tilahavaintoja. Ei tavallisten sovellusten käyttöön."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Aseta salasanasäännöt"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Hallinnoi ruudun lukituksenpoistosalasanoissa sallittuja merkkejä ja salasanan pituutta."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Tarkkaile ruudun lukituksen poistoyrityksiä"</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 47df2d0c1e66..9c4ee148e807 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par le fournisseur de services. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"détecter des observations sur les conditions du réseau"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet à une application de détecter les observations sur les conditions du réseau. Ne devrait jamais être nécessaire pour les applications standards."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1578,8 +1582,8 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Les NIP ne correspondent pas. Essayez à nouveau."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Le NIP est trop court. Il doit comporter au moins 4 chiffres."</string>
<plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Dans 1 seconde"</item>
- <item quantity="other" msgid="4730868920742952817">"Dans <xliff:g id="COUNT">%d</xliff:g> secondes"</item>
+ <item quantity="one" msgid="311050995198548675">"Réessayer dans 1 s"</item>
+ <item quantity="other" msgid="4730868920742952817">"Réessayer dans <xliff:g id="COUNT">%d</xliff:g> s"</item>
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Réessayez plus tard"</string>
<string name="transient_navigation_confirmation" msgid="4907844043611123426">"Gliss. doigt sur côté écr. aff. barre"</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index d639f49cdb76..e8411251f823 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par l\'opérateur. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"détecter des observations sur les conditions du réseau"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet à une application de détecter des observations sur les conditions du réseau. Les applications standards ne devraient pas nécessiter cette autorisation."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Définir les règles du mot de passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Choisir le nombre et le type de caractères autorisés dans les mots de passe de déverrouillage de l\'écran"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gérer les tentatives de déverrouillage de l\'écran"</string>
@@ -1578,8 +1582,8 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Les codes PIN ne correspondent pas. Veuillez réessayer."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Le code PIN est trop court. Il doit comporter au moins 4 chiffres."</string>
<plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Essay. dans 1 s"</item>
- <item quantity="other" msgid="4730868920742952817">"Essay. dans <xliff:g id="COUNT">%d</xliff:g> s"</item>
+ <item quantity="one" msgid="311050995198548675">"Réessayer dans 1 s"</item>
+ <item quantity="other" msgid="4730868920742952817">"Réessayer dans <xliff:g id="COUNT">%d</xliff:g> s"</item>
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Veuillez réessayer ultérieurement."</string>
<string name="transient_navigation_confirmation" msgid="4907844043611123426">"Faire glisser côté pour voir barre."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index 9f4927b10a6d..a1a311fed590 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -374,7 +374,7 @@
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"धारक को किसी विजेट सेवा के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
<string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"किसी उपकरण व्‍यवस्‍थापक के साथ सहभागिता करें"</string>
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"धारक को किसी उपकरण व्‍यवस्‍थापक को उद्देश्य भेजने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
- <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"उपकरण व्यवस्थापक को जोड़ें या निकालें"</string>
+ <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"उपकरण उपकरण सुचारू ढ़ंग से चलाने वाले को जोड़ें या निकालें"</string>
<string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"धारक को सक्रिय डिवाइस व्यवस्थापकों को जोड़ने या निकालने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
<string name="permlab_setOrientation" msgid="3365947717163866844">"स्‍क्रीन अभिविन्‍यास बदलें"</string>
<string name="permdesc_setOrientation" msgid="3046126619316671476">"एप्‍लिकेशन को किसी भी समय स्‍क्रीन का रोटेशन बदलने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
@@ -453,9 +453,9 @@
<string name="permlab_readCalendar" msgid="5972727560257612398">"केलैंडर ईवेंट के साथ-साथ गोपनीय जानकारी पढ़ें"</string>
<string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"एप्लिकेशन को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके टेबलेट पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे गोपनीयता या संवेदनशीलता पर ध्यान दिए बिना, एप्लिकेशन आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है."</string>
<string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"एप्लिकेशन को मित्रों या सहकर्मियों के कैलेंडर इवेंट सहित, आपके फ़ोन पर संग्रहीत कैलेंडर इवेंट पढ़ने देता है. इससे गोपनीयता या संवेदनशीलता पर ध्यान दिए बिना, एप्लिकेशन आपके कैलेंडर डेटा को साझा कर सकता है या सहेज सकता है."</string>
- <string name="permlab_writeCalendar" msgid="8438874755193825647">"स्‍वामी की जानकारी के बि‍ना कैलेंडर ईवेंट जोड़ें या संशोधि‍त करें और अति‍थि‍यों को ईमेल भेजें"</string>
- <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"एप्लिकेशन को मित्रों या सहकर्मियों के ईवेंट के साथ ही वे ईवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने टेबलेट पर संशोधित कर सकते हैं. इससे एप्लिकेशन, स्‍वामी की जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या ईवेंट संशोधित कर सकता है."</string>
- <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"एप्लिकेशन को मित्रों या सहकर्मियों के ईवेंट के साथ ही वे ईवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने फ़ोन पर संशोधित कर सकते हैं. इससे एप्लिकेशन, स्‍वामी की जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या ईवेंट संशोधित कर सकता है."</string>
+ <string name="permlab_writeCalendar" msgid="8438874755193825647">"अपनी जानकारी के बि‍ना कैलेंडर ईवेंट जोड़ें या संशोधि‍त करें और अति‍थि‍यों को ईमेल भेजें"</string>
+ <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"एप्लिकेशन को मित्रों या सहकर्मियों के ईवेंट के साथ ही वे ईवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने टेबलेट पर संशोधित कर सकते हैं. इससे एप्लिकेशन,अपनी जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या ईवेंट संशोधित कर सकता है."</string>
+ <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"एप्लिकेशन को मित्रों या सहकर्मियों के ईवेंट के साथ ही वे ईवेंट जोड़ने, निकालने, बदलने देता है जिन्हें आप अपने फ़ोन पर संशोधित कर सकते हैं. इससे एप्लिकेशन, अपनी जानकारी के बिना उन संदेशों को भेज सकता है जो कैलेंडर स्वामियों की ओर से आते दिखाई देते हैं, या ईवेंट संशोधित कर सकता है."</string>
<string name="permlab_accessMockLocation" msgid="8688334974036823330">"परीक्षण के लिए नकली स्‍थान स्रोत"</string>
<string name="permdesc_accessMockLocation" msgid="5808711039482051824">"परीक्षण के लिए कृत्रिम स्थान स्रोत बनाएं या एक नया स्थान प्रदाता इंस्‍टॉल करें. यह एप्लिकेशन को स्‍थान और/या अन्‍य स्थान स्रोतों जैसे GPS या स्‍थान प्रदाताओं द्वारा लौटाई गई स्थिति को ओवरराइड करने देता है."</string>
<string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"अतिरिक्त स्‍थान प्रदाता आदेशों में पहुंचे"</string>
@@ -617,10 +617,10 @@
<string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"एप्‍लिकेशन को वर्तमान में समन्वयित फ़ीड के बारे में विवरण प्राप्त करने देता है."</string>
<string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"ग्राहकी-प्राप्त फ़ीड लिखें"</string>
<string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"एप्लिकेशन को आपके वर्तमान समन्वयित फ़ीड को संशोधित करने देता है. दुर्भावनापूर्ण एप्लिकेशन आपके समन्वयित फ़ीड को बदल सकते है."</string>
- <string name="permlab_readDictionary" msgid="4107101525746035718">"डिक्शनरी में आपके द्वारा जोड़े गए शब्‍दों को पढ़ें"</string>
- <string name="permdesc_readDictionary" msgid="659614600338904243">"एप्‍लिकेशन को ऐसे सभी शब्‍दों, नामों और वाक्यांशों को पढ़ने देता है जो संभवत: उपयोगकर्ता द्वारा उपयोगकर्ता ‍डिक्शनरी में संग्रहीत किए गए हों."</string>
- <string name="permlab_writeDictionary" msgid="2183110402314441106">"उपयोगकर्ता द्वारा परिभाषित डिक्शनरी में शब्द जोड़ें"</string>
- <string name="permdesc_writeDictionary" msgid="8185385716255065291">"एप्लिकेशन को उपयोगकर्ता डिक्शनरी में नए शब्द लिखने देता है."</string>
+ <string name="permlab_readDictionary" msgid="4107101525746035718">"शब्दकोश में आपके द्वारा जोड़े गए शब्‍दों को पढ़ें"</string>
+ <string name="permdesc_readDictionary" msgid="659614600338904243">"एप्‍लिकेशन को ऐसे सभी शब्‍दों, नामों और वाक्यांशों को पढ़ने देता है जो संभवत: उपयोगकर्ता द्वारा उपयोगकर्ता ‍शब्दकोश में संग्रहीत किए गए हों."</string>
+ <string name="permlab_writeDictionary" msgid="2183110402314441106">"उपयोगकर्ता द्वारा परिभाषित शब्दकोश में शब्द जोड़ें"</string>
+ <string name="permdesc_writeDictionary" msgid="8185385716255065291">"एप्लिकेशन को उपयोगकर्ता शब्दकोश में नए शब्द लिखने देता है."</string>
<string name="permlab_sdcardRead" product="nosdcard" msgid="8235341515605559677">"संरक्ष‍ित संग्रहण पर पहुंच का परीक्षण करें"</string>
<string name="permlab_sdcardRead" product="default" msgid="8235341515605559677">"संरक्ष‍ित संग्रहण पर पहुंच का परीक्षण करें"</string>
<string name="permdesc_sdcardRead" product="nosdcard" msgid="3642473292348132072">"एप्लि. को USB संग्रहण अनुमति का परीक्षण करने देता है जो भविष्‍य के उपकरणों में उपलब्‍ध होगा."</string>
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"धारक को वाहक के द्वारा उपलब्ध कराया गया कॉन्फ़िगरेशन एप्लिकेशन प्रारंभ करने देता है. सामान्‍य एप्‍लिकेशन के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"नेटवर्क स्थितियों के अवलोकनों को सुनें"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"एप्लिकेशन को नेटवर्क स्थितियों के अवलोकनों को सुनने देता है. सामान्य एप्लिकेशन के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियम सेट करें"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"स्‍क्रीन-अनलॉक पासवर्ड में अनुमति प्राप्त लंबाई और वर्णों को नियंत्रित करें."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"स्‍क्रीन-अनलॉक के प्रयासों पर निगरानी रखें"</string>
@@ -804,7 +808,7 @@
<string name="lockscreen_screen_locked" msgid="7288443074806832904">"स्‍क्रीन लॉक की गई है."</string>
<string name="lockscreen_instructions_when_pattern_enabled" msgid="46154051614126049">"अनलॉक करने के लिए मेनू दबाएं या आपातलकालीन कॉल करें."</string>
<string name="lockscreen_instructions_when_pattern_disabled" msgid="686260028797158364">"अनलॉक करने के लिए मेनू दबाएं."</string>
- <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"अनलॉक करने के लिए प्रतिमान आरेखित करें"</string>
+ <string name="lockscreen_pattern_instructions" msgid="7478703254964810302">"अनलॉक करने के लिए आकार आरेखित करें"</string>
<string name="lockscreen_emergency_call" msgid="5347633784401285225">"आपातकालीन कॉल"</string>
<string name="lockscreen_return_to_call" msgid="5244259785500040021">"कॉल पर वापस लौटें"</string>
<string name="lockscreen_pattern_correct" msgid="9039008650362261237">"सही!"</string>
@@ -833,19 +837,19 @@
<string name="lockscreen_sim_puk_locked_instructions" msgid="8127916255245181063">"कृपया उपयोगकर्ता मार्गदर्शिका देखें या ग्राहक सहायता से संपर्क करें."</string>
<string name="lockscreen_sim_locked_message" msgid="8066660129206001039">"सिम कार्ड लॉक किया गया है."</string>
<string name="lockscreen_sim_unlock_progress_dialog_message" msgid="595323214052881264">"सिम कार्ड अनलॉक कर रहा है…"</string>
- <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"आपने अपना अनलॉक प्रतिमान <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत बनाया है. \n\n <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+ <string name="lockscreen_too_many_failed_attempts_dialog_message" msgid="6481623830344107222">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत बनाया है. \n\n <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="lockscreen_too_many_failed_password_attempts_dialog_message" msgid="2725973286239344555">"आपने अपना पासवर्ड <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से लिखा है. \n\n<xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="lockscreen_too_many_failed_pin_attempts_dialog_message" msgid="6216672706545696955">"आपने अपना पिन <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से लिखा है. \n\n<xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुनः प्रयास करें."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"आपने अपना अनलॉक प्रतिमान <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत बनाया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने Google साइन-इन का उपयोग करके आपके टेबलेट को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
- <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"आपने अपना अनलॉक प्रतिमान <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत बनाया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने Google साइन-इन का उपयोग करके आपके फ़ोन को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="tablet" msgid="9191611984625460820">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत बनाया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने Google साइन-इन का उपयोग करके आपके टेबलेट को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+ <string name="lockscreen_failed_attempts_almost_glogin" product="default" msgid="2590227559763762751">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत बनाया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने Google साइन-इन का उपयोग करके आपके फ़ोन को अनलॉक करने को कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="tablet" msgid="6128106399745755604">"आप गलत तरीके से टेबलेट को अनलॉक करने का प्रयास <xliff:g id="NUMBER_0">%d</xliff:g> बार कर चुके हैं. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयास के बाद, टेबलेट फ़ैक्‍टरी डिफ़ॉल्‍ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string>
<string name="lockscreen_failed_attempts_almost_at_wipe" product="default" msgid="8603565142156826565">"आप गलत तरीके से फ़ोन को अनलॉक करने का प्रयास <xliff:g id="NUMBER_0">%d</xliff:g> बार कर चुके हैं. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयास के बाद, फ़ोन फ़ैक्‍टरी डिफ़ॉल्‍ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="tablet" msgid="280873516493934365">"आप टेबलेट को गलत तरीके से <xliff:g id="NUMBER">%d</xliff:g> बार अनलॉक करने का प्रयास कर चुके हैं. टेबलेट अब फ़ैक्‍टरी डिफ़ॉल्‍ट पर रीसेट हो जाएगा."</string>
<string name="lockscreen_failed_attempts_now_wiping" product="default" msgid="3025504721764922246">"आप फ़ोन को गलत तरीके से <xliff:g id="NUMBER">%d</xliff:g> बार अनलॉक करने का प्रयास कर चुके हैं. फ़ोन अब फ़ैक्‍टरी डिफ़ॉल्‍ट पर रीसेट हो जाएगा."</string>
<string name="lockscreen_too_many_failed_attempts_countdown" msgid="6251480343394389665">"<xliff:g id="NUMBER">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
- <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"प्रतिमान भूल गए?"</string>
+ <string name="lockscreen_forgot_pattern_button_text" msgid="2626999449610695930">"आकार भूल गए?"</string>
<string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"खाता अनलॉक"</string>
- <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"बहुत अधिक प्रतिमान प्रयास"</string>
+ <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"बहुत अधिक आकार प्रयास"</string>
<string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"अनलॉक करने के लिए, अपने Google खाते से प्रवेश करें."</string>
<string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"उपयोगकर्ता नाम (ईमेल)"</string>
<string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"पासवर्ड"</string>
@@ -856,10 +860,10 @@
<string name="lockscreen_unlock_label" msgid="737440483220667054">"अनलॉक करें"</string>
<string name="lockscreen_sound_on_label" msgid="9068877576513425970">"ध्‍वनि चालू करें"</string>
<string name="lockscreen_sound_off_label" msgid="996822825154319026">"ध्वनि बंद"</string>
- <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"प्रतिमान प्रारंभ किया गया"</string>
- <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"प्रतिमान साफ़ किया गया"</string>
+ <string name="lockscreen_access_pattern_start" msgid="3941045502933142847">"आकार प्रारंभ किया गया"</string>
+ <string name="lockscreen_access_pattern_cleared" msgid="5583479721001639579">"आकार साफ़ किया गया"</string>
<string name="lockscreen_access_pattern_cell_added" msgid="6756031208359292487">"कक्ष जोड़ा गया"</string>
- <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"प्रतिमान पूरा किया गया"</string>
+ <string name="lockscreen_access_pattern_detected" msgid="4988730895554057058">"आकार पूरा किया गया"</string>
<string name="keyguard_accessibility_widget_changed" msgid="5678624624681400191">"%1$s. %3$d विजेट में से %2$d."</string>
<string name="keyguard_accessibility_add_widget" msgid="8273277058724924654">"विजेट जोड़ें"</string>
<string name="keyguard_accessibility_widget_empty_slot" msgid="1281505703307930757">"रिक्त"</string>
@@ -875,11 +879,11 @@
<string name="keyguard_accessibility_widget_deleted" msgid="4426204263929224434">"विजेट <xliff:g id="WIDGET_INDEX">%1$s</xliff:g> को हटा दिया गया."</string>
<string name="keyguard_accessibility_expand_lock_area" msgid="519859720934178024">"अनलॉक क्षेत्र विस्तृत करें."</string>
<string name="keyguard_accessibility_slide_unlock" msgid="2959928478764697254">"स्लाइड अनलॉक."</string>
- <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"प्रतिमान अनलॉक."</string>
+ <string name="keyguard_accessibility_pattern_unlock" msgid="1490840706075246612">"आकार अनलॉक."</string>
<string name="keyguard_accessibility_face_unlock" msgid="4817282543351718535">"फेस अनलॉक."</string>
<string name="keyguard_accessibility_pin_unlock" msgid="2469687111784035046">"पिन अनलॉक."</string>
<string name="keyguard_accessibility_password_unlock" msgid="7675777623912155089">"पासवर्ड अनलॉक."</string>
- <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"प्रतिमान क्षेत्र."</string>
+ <string name="keyguard_accessibility_pattern_area" msgid="7679891324509597904">"आकार क्षेत्र."</string>
<string name="keyguard_accessibility_slide_area" msgid="6736064494019979544">"स्लाइड क्षेत्र."</string>
<string name="password_keyboard_label_symbol_key" msgid="992280756256536042">"?123"</string>
<string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
@@ -1479,12 +1483,12 @@
<string name="wifi_display_notification_message" msgid="4498802012464170685">"यह स्क्रीन अन्य उपकरण पर दिखाई दे रही है"</string>
<string name="wifi_display_notification_disconnect" msgid="6183754463561153372">"डिस्कनेक्ट करें"</string>
<string name="kg_emergency_call_label" msgid="684946192523830531">"आपातकालीन कॉल"</string>
- <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"प्रतिमान भूल गए"</string>
- <string name="kg_wrong_pattern" msgid="1850806070801358830">"गलत प्रतिमान"</string>
+ <string name="kg_forgot_pattern_button_text" msgid="8852021467868220608">"आकार भूल गए"</string>
+ <string name="kg_wrong_pattern" msgid="1850806070801358830">"गलत आकार"</string>
<string name="kg_wrong_password" msgid="2333281762128113157">"गलत पासवर्ड"</string>
<string name="kg_wrong_pin" msgid="1131306510833563801">"गलत PIN"</string>
<string name="kg_too_many_failed_attempts_countdown" msgid="6358110221603297548">"<xliff:g id="NUMBER">%1$d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
- <string name="kg_pattern_instructions" msgid="398978611683075868">"अपना प्रतिमान आरेखित करें"</string>
+ <string name="kg_pattern_instructions" msgid="398978611683075868">"अपना आकार आरेखित करें"</string>
<string name="kg_sim_pin_instructions" msgid="2319508550934557331">"सिम PIN डालें"</string>
<string name="kg_pin_instructions" msgid="2377242233495111557">"PIN डालें"</string>
<string name="kg_password_instructions" msgid="5753646556186936819">"पासवर्ड डालें"</string>
@@ -1497,7 +1501,7 @@
<string name="kg_invalid_sim_puk_hint" msgid="7553388325654369575">"PUK कोड 8 या अधिक संख्या वाला होना चाहिए."</string>
<string name="kg_invalid_puk" msgid="3638289409676051243">"सही PUK कोड पुन: डालें. बार-बार प्रयास करने से सिम स्थायी रूप से अक्षम हो जाएगी."</string>
<string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"पिन कोड का मिलान नहीं होता"</string>
- <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"बहुत अधिक प्रतिमान प्रयास"</string>
+ <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"बहुत अधिक आकार प्रयास"</string>
<string name="kg_login_instructions" msgid="1100551261265506448">"अनलॉक करने के लिए, अपने Google खाते से प्रवेश करें."</string>
<string name="kg_login_username_hint" msgid="5718534272070920364">"उपयोगकर्ता नाम (ईमेल)"</string>
<string name="kg_login_password_hint" msgid="9057289103827298549">"पासवर्ड"</string>
@@ -1507,13 +1511,13 @@
<string name="kg_login_checking_password" msgid="1052685197710252395">"खाते की जांच की जा रही है…"</string>
<string name="kg_too_many_failed_pin_attempts_dialog_message" msgid="8276745642049502550">"आप अपना PIN <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="kg_too_many_failed_password_attempts_dialog_message" msgid="7813713389422226531">"आप अपना पासवर्ड <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से लिख चुके हैं. \n\n <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
- <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"आपने अपना अनलॉक प्रतिमान <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. \n\n <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+ <string name="kg_too_many_failed_pattern_attempts_dialog_message" msgid="74089475965050805">"आपने अपना अनलॉक आकार <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. \n\n <xliff:g id="NUMBER_1">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="tablet" msgid="1575557200627128949">"आप टेबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, टेबलेट फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string>
<string name="kg_failed_attempts_almost_at_wipe" product="default" msgid="4051015943038199910">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, फ़ोन फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा और सभी उपयोगकर्ता डेटा खो जाएगा."</string>
<string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2072996269148483637">"आप टेबलेट को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. टेबलेट अब फ़ैक्‍टरी डिफ़ॉल्‍ट पर रीसेट हो जाएगा."</string>
<string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"आप फ़ोन को अनलॉक करने के लिए <xliff:g id="NUMBER">%d</xliff:g> बार गलत तरीके से प्रयास कर चुके हैं. फ़ोन अब फ़ैक्टरी डिफ़ॉल्ट पर रीसेट हो जाएगा."</string>
- <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपने अपने अनलॉक प्रतिमान को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टेबलेट को किसी ईमेल खाते के उपयोग से अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
- <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"आपने अपने अनलॉक प्रतिमान को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने टेबलेट को किसी ईमेल खाते के उपयोग से अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
+ <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"आपने अपने अनलॉक आकार को <xliff:g id="NUMBER_0">%d</xliff:g> बार गलत तरीके से आरेखित किया है. <xliff:g id="NUMBER_1">%d</xliff:g> और असफल प्रयासों के बाद, आपसे अपने फ़ोन को किसी ईमेल खाते का उपयोग करके अनलॉक करने के लिए कहा जाएगा.\n\n <xliff:g id="NUMBER_2">%d</xliff:g> सेकंड में पुन: प्रयास करें."</string>
<string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
<string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"निकालें"</string>
<string name="safe_media_volume_warning" product="default" msgid="7324161939475478066">"वॉल्यूम को उपरोक्त अनुशंसित स्तर तक बढ़ाएं?\nलंबे समय तक अधिक वॉल्यूम पर सुनने से आपकी सुनने की क्षमता को क्षति पहुंच सकती है."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index cd43b8dac34b..cfac52006922 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Dopušta nositelju pozivanje operaterove aplikacije za konfiguraciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"praćenje motrenja mrežnih uvjeta"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Omogućuje aplikaciji praćenje motrenja mrežnih uvjeta. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otključavanje zaslona i dopuštenim znakovima u tim zaporkama."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 437367f1b908..28a43172dbed 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lehetővé teszi a használó számára a szolgáltató által biztosított konfigurációs alkalmazás hívását. A normál alkalmazásoknak erre soha nincs szükségük."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"hálózati körülményekkel kapcsolatos észrevételek figyelemmel kísérése"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Lehetővé teszi egy alkalmazás számára, hogy figyelemmel kísérje a hálózati körülményekkel kapcsolatos észrevételeket. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index b15ea4f2ed7b..c6c484b99304 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Թույլ է տալիս սեփականատիրոջը գործարկել օպերատորի կողմից տրամադրված կազմաձևման ծրագիրը: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"լսել դիտարկումներ ցանցային պայմանների վերաբերյալ"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Հավելվածին թույլ է տալիս լսել դիտարկումներ ցանցային պայմանների վերաբերյալ: Սովորական հավելվածների համար երբեք պետք չի գալիս:"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Սահմանել գաղտնաբառի կանոնները"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Վերահսկել էկրանի ապակողպման գաղտնաբառերի թույլատրելի երկարությունն ու գրանշանները:"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Վերահսկել էկրանի ապակողպման փորձերը"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index 04110af846fe..cd2fc6b27954 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Memungkinkan pemegang meminta aplikasi konfigurasi yang disediakan operator. Tidak pernah diperlukan aplikasi normal."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"mendengar untuk observasi kondisi jaringan"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Memungkinkan aplikasi mendengar untuk observasi kondisi jaringan. Tidak pernah dibutuhkan oleh aplikasi normal."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setel aturan sandi"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrol panjang dan karakter yang diizinkan dalam sandi pembuka layar."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Upaya pembukaan kunci layar monitor"</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index fd864da0192b..3bf8401c7874 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Consente al titolare di richiamare l\'app di configurazione dell\'operatore-provider. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascolto delle osservazioni sulle condizioni di rete"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Consente a un\'applicazione di ascoltare le osservazioni sulle condizioni di rete. Da non utilizzare mai con app normali."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Imposta regole password"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlla la lunghezza e i caratteri ammessi nelle password di sblocco dello schermo."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitora tentativi di sblocco dello schermo"</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 18751229dfa7..aa3d41032b1b 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -655,6 +655,8 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ההרשאה הזו מאפשרת לבעלים להפעיל את אפליקציית התצורה שסופקה על ידי ספק. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"קליטת מעקב אחר תנאי רשת"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"מאפשרת לאפליקציה לקלוט מעקב אחר תנאי רשת. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
+ <string name="permlab_hotwordRecognition" msgid="3225080408746361313">"בקשה של הכרה במילת הפעלה"</string>
+ <string name="permdesc_hotwordRecognition" msgid="3716741260195364252">"מאפשרת לאפליקציה לבקש הכרה במילת הפעלה. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"הגדר כללי סיסמה"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"שלוט באורך ובתווים המותרים בסיסמאות לביטול נעילת מסך."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"עקוב אחר ניסיונות לביטול נעילת מסך"</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index bf2dcac98910..28bc0d86c10a 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"携帯通信会社が提供する設定アプリを呼び出すことを所有者に許可します。通常のアプリでは不要です。"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ネットワーク状況監視のためのリッスン"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ネットワーク状況を監視するためリッスンすることをアプリに許可します。通常のアプリで必要になることはありません。"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"パスワードルールの設定"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"画面ロック解除パスワードの長さと使用できる文字を制御します。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"画面ロック解除試行の監視"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 745b4c7f7d63..b9a794642960 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"საშუალებას აძლევს მფლობელს გამოიწვიოს ოპერატორის მიერ მოწოდებული კონფიგურაციის აპი. ჩვეულებრივ აპს ეს წესით არასოდეს არ უნდა დაჭირდეს."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"განხორციელდეს ქსელის მდგომარეობის მონიტორინგი"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"საშუალებას აძლევს აპლიკაციებს განახორციელოს ქსელის მდგომარეობის მონიტორინგი. ეს ფუნქცია ჩვეულებრივ აპებს არ ჭირდება."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"პაროლის წესების დაყენება"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"გააკონტროლეთ ეკრანის განბლოკვის პაროლში დაშვებული სიმბოლოები და მისი სიგრძე."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ეკრანის განბლოკვის მცდელობების გაკონტროლება"</string>
@@ -1122,7 +1126,7 @@
<string name="smv_application" msgid="3307209192155442829">"აპმა <xliff:g id="APPLICATION">%1$s</xliff:g> (პროცესი <xliff:g id="PROCESS">%2$s</xliff:g>) დაარღვია საკუთარი StrictMode დებულება."</string>
<string name="smv_process" msgid="5120397012047462446">"ამ პროცესმა <xliff:g id="PROCESS">%1$s</xliff:g> დააზიანა საკუთარი StrictMode დებულება."</string>
<string name="android_upgrading_title" msgid="1584192285441405746">"Android ახალ ვერსიაზე გადადის…"</string>
- <string name="android_upgrading_apk" msgid="7904042682111526169">"<xliff:g id="NUMBER_0">%1$d</xliff:g> აპლიკაციის (სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>-დან) ოპტიმიზაცია."</string>
+ <string name="android_upgrading_apk" msgid="7904042682111526169">"მიმდინარეობს აპლიკაციების ოპტიმიზაცია. დასრულებულია <xliff:g id="NUMBER_0">%1$d</xliff:g>, სულ <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
<string name="android_upgrading_starting_apps" msgid="451464516346926713">"აპების ჩართვა"</string>
<string name="android_upgrading_complete" msgid="1405954754112999229">"ჩატვირთვის დასასრული."</string>
<string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> გაშვებულია"</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index a75c6a9d09d0..4362bdc5cf0a 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -655,6 +655,8 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ដក​ហូត​កម្មវិធី​កំណត់​រចនាសម្ព័ន្ធ​ដែល​បាន​ផ្ដល់​ដោយ​ក្រុមហ៊ុន​បញ្ជូន។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"សង្កេត​មើល​លើ​លក្ខខណ្ឌ​បណ្ដាញ"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ឲ្យ​កម្មវិធី​សង្កេត​មើល​​លើ​លក្ខខណ្ឌ​បណ្ដាញ​។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
+ <string name="permlab_hotwordRecognition" msgid="3225080408746361313">"ស្នើ​ការ​ស្គាល់ hotword"</string>
+ <string name="permdesc_hotwordRecognition" msgid="3716741260195364252">"ឲ្យ​កម្មវិធី​ស្នើ​ការ​ស្គាល់ hotword ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"កំណត់​ក្បួន​ពាក្យ​សម្ងាត់"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ពិនិត្យ​ប្រវែង និង​តួអក្សរ​ដែល​បាន​អនុញ្ញាត​ក្នុង​ពាក្យ​សម្ងាត់​ចាក់​សោ​អេក្រង់។"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ពិនិត្យ​ការ​ព្យាយាម​ដោះ​សោ​អេក្រង់"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 9f6c84b41782..69b74e3ad6d1 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"권한을 가진 프로그램이 이동통신사에서 제공한 구성 앱을 호출하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"네트워크 상태에 대한 관측 보고 수신"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"애플리케이션이 네트워크 상태에 대한 관측 보고를 수신하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"비밀번호 규칙 설정"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"화면 잠금해제 비밀번호에 허용되는 길이 및 문자 수를 제어합니다."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"화면 잠금해제 시도 모니터링"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 0dddde73386a..cb71e3141010 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ອະ​ນຸ​ຍາດ​ໃຫ້​ເຈົ້າຂອງຮ້ອງຂໍແອັບຯປັບຄ່າທີ່ສະໜອງໂດຍຜູ່ໃຫ້ບໍລິການ. ບໍ່ໜ້າຈະຕ້ອງການສຳລັບແອັບຯທົ່ວໄປ."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ຕິດຕາມເພື່ອສັງເກດສະພາບຂອງເຄືອຂ່າຍ"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັ່ນຕິດຕາມເພື່ອສັງເກດສະພາບຂອງເຄືອຂ່າຍ. ປົກກະຕິແລ້ວແອັບຯທຳມະດາຈະບໍ່ຕ້ອງການໃຊ້."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"ຕັ້ງຄ່າກົດຂອງລະຫັດຜ່ານ"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ຄວບຄຸມຄວາມຍາວຂອງໂຕອັກສອນທີ່ສາມາດໃຊ້ກັບລະຫັດປົດລັອກໜ້າຈໍ"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ຕິດຕາມການພະຍາຍາມປົດລັອກໜ້າຈໍ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 9fa2070f06a7..fc4fcc22110e 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Turėtojui leidžiama iškviesti operatoriaus pateiktą konfigūravimo programą. Įprastoms programoms to neturėtų prireikti."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"vykdyti tinklo sąlygų stebėjimą"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Leidžiama programai vykdyti tinklo sąlygų stebėjimą. To niekada neturėtų prireikti naudojant įprastas programas."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nustatyti slaptažodžio taisykles"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Valdyti leidžiamą ekrano atrakinimo slaptažodžių ilgį ir leidžiamus naudoti simbolius."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Stebėti bandymus atrakinti ekraną"</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 5d81fc7663b1..beff99fd37e2 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ļauj īpašniekam izsaukt operatora nodrošināto konfigurācijas lietotni. Parastām lietotnēm tas nekad nav nepieciešams."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"iegūt informāciju par tīkla stāvokļa novērojumiem"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ļauj lietojumprogrammai iegūt informāciju par tīkla stāvokļa novērojumiem. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Paroles kārtulu iestatīšana"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolē ekrāna atbloķēšanas parolē atļautās rakstzīmes un garumu."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekrāna atbloķēšanas mēģinājumu pārraudzīšana"</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index 3fe78995a39e..16ba5f5dc28e 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -655,6 +655,8 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Эзэмшигчид үүрэн компанийн нийлүүлсэн тохируулах апп-г өдөөх боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Сүлжээний байдлын талаар ажиглалтуудыг хүлээн авах"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Аппликешнд сүлжээний байдлын талаар ажиглалтуудыг хүлээн авахыг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
+ <string name="permlab_hotwordRecognition" msgid="3225080408746361313">"хотворд таних хүсэлт"</string>
+ <string name="permdesc_hotwordRecognition" msgid="3716741260195364252">"Аппликешнд хотворд таних хүсэлт гаргахыг зөвшөөрнө. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Нууц үгний дүрмийг тохируулах"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Дэлгэц түгжих нууц үгэнд зөвшөөрөгдсөн тэмдэгт болон уртыг удирдах"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Дэлгэц тайлах оролдлогыг хянах"</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 748fc5a80161..d422e32dc4a1 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Membenarkan pemegang menggunakan apl konfigurasi yang diberikan oleh pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"dengar pemerhatian mengenai keadaan rangkaian"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Membenarkan aplikasi mendengar pemerhatian tentang keadaan rangkaian. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Tetapkan peraturan kata laluan"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Mengawal panjang dan aksara yang dibenarkan dalam kata laluan buka kunci skrin."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Memantau percubaan buka kunci skrin"</string>
@@ -1578,8 +1582,8 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN tidak sepadan. Cuba lagi."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN terlalu pendek. Mesti sekurang-kurangnya 4 angka."</string>
<plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Cuba lg dlm 1 st"</item>
- <item quantity="other" msgid="4730868920742952817">"Cuba lg dlm <xliff:g id="COUNT">%d</xliff:g> st"</item>
+ <item quantity="one" msgid="311050995198548675">"Cuba 1 saat lagi"</item>
+ <item quantity="other" msgid="4730868920742952817">"Cuba <xliff:g id="COUNT">%d</xliff:g> saat lagi"</item>
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Cuba sebentar lagi"</string>
<string name="transient_navigation_confirmation" msgid="4907844043611123426">"Leret bhg tepi skrin utk serlah bar"</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index f53f817d0ab9..54687796ba05 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Gir innehaveren tillatelse til å kalle opp den konfigurasjonsappen som ble levert av operatøren. Dette skal ikke være nødvendig for vanlige apper."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lytte etter observasjoner om nettverksforhold"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Gir appen tillatelse til å lytte etter observasjoner om nettverksforhold. Dette skal ikke være nødvendig for vanlige apper."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
diff --git a/core/res/res/values-ne-rNP/strings.xml b/core/res/res/values-ne-rNP/strings.xml
index 67775da5cef0..10f8376fa51b 100644
--- a/core/res/res/values-ne-rNP/strings.xml
+++ b/core/res/res/values-ne-rNP/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"प्रयोगकर्तालाई वाहक-प्रदान विन्यास अनुप्रयोग सुरु गर्न अनुमति दिन्छ। साधारण अनुप्रयोगहरूलाई कहिल्यै आवश्यक पर्ने छैन।"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"सञ्जाल अवस्थाका पर्यवेक्षणका लागि सुन्नुहोस्"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"सञ्जाल अवस्थाका पर्यवेक्षण सुन्नका लागि अनुप्रयोगलाई अनुमति दिन्छ।सामान्य अनुप्रयोगलाई चाँहिदै नचाँहिन सक्छ।"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"पासवर्ड नियमहरू मिलाउनुहोस्"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"स्क्रिन-अनलक पासवर्डहरूमा अनुमति दिइएको लम्बाइ र अक्षरहरू नियन्त्रण गर्नुहोस्।"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"मोनिटर स्क्रिन-अनलक प्रयत्नहरू"</string>
@@ -1568,7 +1572,7 @@
<string name="write_fail_reason_cancelled" msgid="7091258378121627624">"रद्द गरियो"</string>
<string name="write_fail_reason_cannot_write" msgid="8132505417935337724">"सामाग्री लेखनमा त्रुटि"</string>
<string name="reason_unknown" msgid="6048913880184628119">"अज्ञात"</string>
- <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"प्रशासक PIN प्रविष्ट गर्नुहोस्"</string>
+ <string name="restr_pin_enter_admin_pin" msgid="783643731895143970">"प्रशासक PIN प्रविष्टि गर्नुहोस्"</string>
<string name="restr_pin_enter_pin" msgid="3395953421368476103">"PIN प्रविष्टि गर्नुहोस्"</string>
<string name="restr_pin_incorrect" msgid="8571512003955077924">"गलत"</string>
<string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"वर्तमान PIN"</string>
@@ -1578,10 +1582,10 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN हरू मेल खाएनन्। पुनः प्रयास गर्नुहोस्।"</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN अति छोटो भयो। कम्तीमा ४ अङ्क हुन आवश्यक छ।"</string>
<plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"१ सेकेन्ड पछि पुन: प्रयास गर्नुहोला।"</item>
- <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्डमा पुन: प्रयास गर्नुहोस्"</item>
+ <item quantity="one" msgid="311050995198548675">"१ सेकेन्ड पछि पुनः प्रयास गर्नुहोस्।"</item>
+ <item quantity="other" msgid="4730868920742952817">"<xliff:g id="COUNT">%d</xliff:g> सेकेन्डमा पुनः प्रयास गर्नुहोस्"</item>
</plurals>
- <string name="restr_pin_try_later" msgid="973144472490532377">"पछि पुन: प्रयास गर्नुहोस्"</string>
+ <string name="restr_pin_try_later" msgid="973144472490532377">"पछि पुनः प्रयास गर्नुहोस्"</string>
<string name="transient_navigation_confirmation" msgid="4907844043611123426">"पट्टि देखिने बनाउन स्क्रिनको छेउमा स्वाइप गर्नुहोस्"</string>
<string name="transient_navigation_confirmation_long" msgid="8061685920508086697">"प्रणाली पट्टि देखिने बनाउन स्क्रिनको छेउबाट स्वाइप गर्नुहोस्"</string>
</resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index db0c2183600d..f4234da63e38 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Hiermee kan de houder de door de provider geleverde configuratie-app aanroepen. Nooit vereist voor normale apps."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"controleren op waarnemingen met betrekking tot netwerkomstandigheden"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Hiermee kan een app controleren op waarnemingen met betrekking tot netwerkomstandigheden. Nooit vereist voor normale apps."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Wachtwoordregels instellen"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"De lengte en tekens beheren die zijn toegestaan in wachtwoorden voor schermontgrendeling."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Pogingen voor schermontgrendeling bijhouden"</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index d2cf5b8cc197..6c01e1c62f21 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Zezwala na wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora. Nieprzeznaczone dla zwykłych aplikacji."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"śledź stan sieci"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Pozwala aplikacji śledzić stan sieci. Nieprzeznaczone dla zwykłych aplikacji."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Określ reguły hasła"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolowanie długości haseł odblokowania ekranu i dozwolonych w nich znaków"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitoruj próby odblokowania ekranu"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index a21994b6c1fd..31b7e25ccd74 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o titular invoque a aplicação de configuração fornecida pela operadora. Nunca deverá ser necessário para aplicações normais."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ouvir observações sobre as condições da rede"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que uma aplicação ouça observações sobre as condições da rede. Nunca deverá ser necessário para aplicações normais."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras de palavra-passe"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controlar o comprimento e os caracteres permitidos nas palavras-passe de desbloqueio do ecrã."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizar tentativas de desbloqueio do ecrã"</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index 1189c2aa9abc..ee765d569f1e 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o proprietário invoque o aplicativo de configuração fornecido pela operadora. Não deve ser necessário para aplicativos comuns."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar observações nas condições da rede"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite que o aplicativo detecte observações nas condições da rede. Não deve ser necessário para aplicativos comuns."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Definir regras para senha"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Controle o tamanho e os caracteres permitidos nas senhas de desbloqueio de tela."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorar tentativas de desbloqueio da tela"</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 68f0e06f5fc6..f57f82107713 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -1108,6 +1108,10 @@
<skip />
<!-- no translation found for permdesc_accessNetworkConditions (6899102075825272211) -->
<skip />
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<!-- no translation found for policylab_limitPassword (4497420728857585791) -->
<skip />
<!-- no translation found for policydesc_limitPassword (3252114203919510394) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index 0e7ba3aca53a..a2ec3d0bd66e 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite proprietarului să apeleze aplicația de configurare furnizată de operator. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascultă observații despre starea rețelei"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite unei aplicații să asculte observații despre starea rețelei. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Monitorizaţi încercările de deblocare a ecranului"</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index 80e806f93012..7e6645d76e11 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Владелец сможет запускать приложение настроек, предоставленное оператором. Это разрешение не используется обычными приложениями."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Использование данных о состоянии сети"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Приложение сможет использовать данные о состоянии сети. Это разрешение обычно используется только специальными приложениями."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Правила выбора паролей"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролировать длину и символы при вводе паролей для снятия блокировки экрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Отслеживать попытки снятия блокировки экрана"</string>
diff --git a/core/res/res/values-si-rLK/strings.xml b/core/res/res/values-si-rLK/strings.xml
index 9b32bd9b178a..2ec8370b2f7b 100644
--- a/core/res/res/values-si-rLK/strings.xml
+++ b/core/res/res/values-si-rLK/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"වාහකයා ලබාදුන් සැකසුම් යෙදුම් උත්පාදනයට ධාරකයාට අවසර දෙන්න. සාමාන්‍ය යෙදුම් සඳහා කිසිදා අවශ්‍ය නොවෙයි."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ජාල තත්ව මත නිරීක්ෂණ වෙත ඇහුම්කන් දීම"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"යෙදුමකට ජාල තත්ව මත නිරීක්ෂණ වෙත ඇහුම්කන් දීමට අවසර දේ. සාමාන්‍ය යෙදුම් සඳහා කිසිදා අවශ්‍ය නොවේ."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"මුරපද නීති සකස් කිරීම"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"තිරය අගුළු ඇරීමේ මුරපදයට අනුමත අකුරු සහ දිග පාලනය කරන්න."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"තිරය අගුළු ඇරීමේ උත්සාහයන් නිරීක්ෂණය කරන්න"</string>
@@ -1581,7 +1585,7 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN නොගැළපෙයි. නැවත උත්සහ කරන්න."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN කුඩා වැඩිය. ඉලක්කම් 4 වත් විය යුතුය."</string>
<plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"තවත් තත්පර ^1 කින් යළි උත්සාහ කරන්න"</item>
+ <item quantity="one" msgid="311050995198548675">"තවත් තත්පර 1 කින් යළි උත්සාහ කරන්න"</item>
<item quantity="other" msgid="4730868920742952817">"තත්පර <xliff:g id="COUNT">%d</xliff:g> කින් නැවත උත්සහ කරන්න"</item>
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"පසුව නැවත උත්සාහ කරන්න"</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index ea118ce2dd8a..b8f13a285a86 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje držiteľovi vyvolať aplikáciu pre konfiguráciu poskytnutú operátorom. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"zachytávať informácie o stave siete"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Umožňuje aplikácii zachytávať informácie o stave siete. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastaviť pravidlá pre heslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Ovládanie dĺžky hesiel na odomknutie obrazovky a v nich používané znaky."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Sledovať pokusy o odomknutie obrazovky"</string>
@@ -1578,8 +1582,8 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Kódy PIN sa nezhodujú. Skúste to znova."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"Kód PIN je príliš krátky. Musí mať minimálne 4 číslice."</string>
<plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Skúste to znova o 1 s."</item>
- <item quantity="other" msgid="4730868920742952817">"Skúste to znova o <xliff:g id="COUNT">%d</xliff:g> s."</item>
+ <item quantity="one" msgid="311050995198548675">"Skúste to zas o 1 s"</item>
+ <item quantity="other" msgid="4730868920742952817">"Skúste to zas o <xliff:g id="COUNT">%d</xliff:g> s"</item>
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Skúste to znova neskôr"</string>
<string name="transient_navigation_confirmation" msgid="4907844043611123426">"Panel zobraz. prejdením okraja obr."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index a58e47418e7a..191b43871807 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lastniku omogoča sproženje operaterjeve aplikacije za konfiguracijo. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"spremljanje razmer v omrežju"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Aplikaciji omogoča spremljanje razmer v omrežju. Pri navadnih aplikacijah to ne bi smelo biti potrebno."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Nastavitev pravil za geslo"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Nadzor nad dolžino in znaki, ki so dovoljeni v geslih za odklepanje zaslona."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"nadzor nad poskusi odklepanja zaslona"</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index ce4e284fba1f..1c6f893c8ae5 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Дозвољава власнику да позива апликацију са конфигурацијом коју одређује оператер. Уобичајене апликације никада не би требало да је користе."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"праћење података о условима на мрежи"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Дозвољава апликацији да прати податке о условима на мрежи. Не би никада требало да буде потребно за нормалне апликације."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Подешавање правила за лозинку"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролишите дужину и знакове дозвољене у лозинкама за откључавање екрана."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Надгледање покушаја откључавања екрана"</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index 2ea2b0a2dccb..01d2b1540c02 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Innehavaren tillåts att anropa konfigurationsappen från operatören. Ska inte behövas för vanliga appar."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lyssna efter information om nätverksförhållanden"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Tillåter att appen lyssnar efter information om nätverksförhållanden. Vanliga appar bör aldrig behöva den här behörigheten."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Ange lösenordsregler"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Bestäm hur många och vilka tecken som är tillåtna i skärmlåsets lösenord."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Övervaka försök att låsa upp skärmen"</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 2d18ed78dc1a..00e208bcc4c8 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Inaruhusu kishikiliaji kuomba programu ya usakinishaji inayotolewa na mto huduma. Haipaswi kuhitajika kwa programu za kawaida."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"sikiliza matukio katika hali za mtandao"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Huruhusu programu kusikiliza matukio katika hali za mtandao. Haipaswi kuhitajika kamwe kwa programu za kawaida."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Weka kanuni za nenosiri"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Dhibiti urefu na vibambo vinavyoruhusiwa katika manenosiri ya kufungua skrini."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Chunguza majaribio ya kutofun gua skrini"</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index 226b48dfbc9c..d2f334388580 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"อนุญาตให้ผู้ใช้สามารถเรียกใช้แอปการกำหนดค่าของผู้ให้บริการ ซึ่งแอปทั่วไปไม่จำเป็นต้องใช้"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ฟังข้อสังเกตเกี่ยวกับสภาวะของเครือข่าย"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"อนุญาตให้แอปพลิเคชันฟังข้อสังเกตเกี่ยวกับสภาวะของเครือข่าย ไม่จำเป็นสำหรับแอปปกติ"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"ตั้งค่ากฎรหัสผ่าน"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"ควบคุมความยาวและอักขระที่อนุญาตให้ใช้ในรหัสผ่านการปลดล็อกหน้าจอ"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"ตรวจสอบความพยายามในการปลดล็อกหน้าจอ"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 36a3ffeb45aa..fbe1d0a7a3a9 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Nagbibigay-daan sa may-ari na paganahin ang app ng configuration na ibinigay ng carrier. Hindi dapat kailanganin para sa normal na apps kahit kailan."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"makinig sa mga obserbasyon sa mga kundisyon ng network"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Nagbibigay-daan sa isang application na makinig sa mga obserbasyon sa mga kundisyon ng network. Dapat na hindi kailanman kakailanganin para sa normal na apps."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Magtakda ng mga panuntunan sa password"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontrolin ang haba at mga character na pinapayagan sa mga password sa pag-unlock ng screen."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Subaybayan ang mga pagsubok sa pag-unlock ng screen"</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 8fb697ddf9c1..43cffc0ecff4 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"İzin sahibine, operatör tarafından sağlanan yapılandırma uygulamasını çalıştırma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ağ koşullarındaki gözlemleri dinle"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Bir uygulamaya, ağ koşullarındaki gözlemleri dinleme izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Şifre kuralları ayarla"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Ekran kilidini açma şifrelerinde izin verilen uzunluğu ve karakterleri denetleme."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Ekran kilidini açma denemelerini izle"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 94126293db6b..db91e1eadfad 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Дозволяє власнику викликати надану оператором програму конфігурації. Ніколи не застосовується для звичайних програм."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"прослуховувати дані спостережень за станом мережі"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Дозволяє програмі прослуховувати дані спостережень за станом мережі. Ніколи не застосовується для звичайних програм."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Устан. правила пароля"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Контролювати довжину паролів для розблокування екрана та дозволені в них символи."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Відстежув. спроби розблок. екрана"</string>
@@ -1578,8 +1582,8 @@
<string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"PIN-коди не збігаються. Повторіть спробу."</string>
<string name="restr_pin_error_too_short" msgid="8173982756265777792">"PIN-код закороткий. Має бути принаймні 4 цифри."</string>
<plurals name="restr_pin_countdown">
- <item quantity="one" msgid="311050995198548675">"Спробуйте за 1 с"</item>
- <item quantity="other" msgid="4730868920742952817">"Спробуйте за <xliff:g id="COUNT">%d</xliff:g> с"</item>
+ <item quantity="one" msgid="311050995198548675">"Повтор за 1 с"</item>
+ <item quantity="other" msgid="4730868920742952817">"Повтор за <xliff:g id="COUNT">%d</xliff:g> с"</item>
</plurals>
<string name="restr_pin_try_later" msgid="973144472490532377">"Спробуйте пізніше"</string>
<string name="transient_navigation_confirmation" msgid="4907844043611123426">"Гортайте від краю, щоб відкрити панель"</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 4e44cc4a7c24..2c6888e8753a 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Cho phép chủ sở hữu gọi ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp. Không cần thiết cho các ứng dụng thông thường."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"quan sát các điều kiện mạng"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Cho phép ứng dụng quan sát các điều kiện mạng. Không bao giờ cần cho ứng dụng thông thường."</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"Đặt quy tắc mật khẩu"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Kiểm soát độ dài và ký tự được phép trong mật khẩu mở khóa màn hình."</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Giám sát những lần thử mở khóa màn hình"</string>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 895952af924d..d7637acbdde8 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允许应用调用运营商提供的配置应用。普通应用绝不需要此权限。"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"监听网络状况的观测信息"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"允许应用监听网络状况的观测信息。普通应用绝不需要此权限。"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"设置密码规则"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解锁密码所允许的长度和字符。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"监视屏幕解锁尝试次数"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index 7a2298fb8e5d..42fec0d0526b 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式調用流動網絡供應商提供的設定應用程式 (不建議一般應用程式使用)。"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"監聽對網絡狀況的觀察"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"允許應用程式監聽對網絡狀況的觀察 (不建議一般應用程式使用)。"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"控制屏幕解鎖密碼所允許的長度和字元。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"監控屏幕解鎖嘗試次數"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index df6da731ec1d..7b25629d9d52 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -655,6 +655,10 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式叫用行動通訊業者提供的設定應用程式 (一般應用程式並不需要)。"</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"監聽網路狀況觀察資訊"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"允許應用程式監聽網路狀況觀察資訊 (一般應用程式並不需要)。"</string>
+ <!-- no translation found for permlab_hotwordRecognition (3225080408746361313) -->
+ <skip />
+ <!-- no translation found for permdesc_hotwordRecognition (3716741260195364252) -->
+ <skip />
<string name="policylab_limitPassword" msgid="4497420728857585791">"設定密碼規則"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"控制螢幕解鎖密碼所允許的長度和字元。"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"監視螢幕解鎖嘗試次數"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index dd8a7b96e531..e32ef9ffb976 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -655,6 +655,8 @@
<string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ivumela umnikazi ukuthi abuyisele uhlelo lokusebenza lokulungiselelwa. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Lalela okubonwayo kuzimo zenethiwekhi"</string>
<string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Ivumela uhlelo lokusebenza ukuthi lulalele okubonwa kuzimo zenethiwekhi. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
+ <string name="permlab_hotwordRecognition" msgid="3225080408746361313">"cela ukubonwa kwe-hotword"</string>
+ <string name="permdesc_hotwordRecognition" msgid="3716741260195364252">"Ivumela uhlelo lokusebenza ukuthi lucele ukubonwa kwe-hotword. Akumele ifunelwe izinhlelo zokusebenza ezijwayelekile."</string>
<string name="policylab_limitPassword" msgid="4497420728857585791">"Misa imithetho yephasiwedi"</string>
<string name="policydesc_limitPassword" msgid="3252114203919510394">"Lawula ubude nezinhlamvu ezivunyelwe kumaphasiwedi okuvula isikrini"</string>
<string name="policylab_watchLogin" msgid="914130646942199503">"Gaka imizamo yokuvula isikrini"</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index a47e518f2d04..7ddf2e9fbb23 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -6128,8 +6128,4 @@
<attr name="textView" format="reference" />
</declare-styleable>
- <declare-styleable name="DocumentsProviderInfo">
- <attr name="customRoots" format="boolean" />
- </declare-styleable>
-
</resources>
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index 05ca12059547..d2ada7a167ba 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -1379,9 +1379,6 @@
component specific values). -->
<attr name="enabled" />
<attr name="exported" />
- <!-- If set to true, onProvideAssistData will be called on this service when this service
- is running in the foreground. -->
- <attr name="provideAssistData" format="boolean" />
<!-- If set to true, this service with be automatically stopped
when the user remove a task rooted in an activity owned by
the application. The default is false. -->
diff --git a/core/res/res/values/colors.xml b/core/res/res/values/colors.xml
index 604bf4b6f3c7..284f61383d9f 100644
--- a/core/res/res/values/colors.xml
+++ b/core/res/res/values/colors.xml
@@ -195,5 +195,7 @@
<color name="keyguard_avatar_frame_shadow_color">#80000000</color>
<color name="keyguard_avatar_nick_color">#ffffffff</color>
<color name="keyguard_avatar_frame_pressed_color">#ff35b5e5</color>
+
+ <color name="accessibility_focus_highlight">#80ffff00</color>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 6c3856ec1e4b..cd1402c50a16 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2073,11 +2073,9 @@
<public type="attr" name="vendor" />
<public type="attr" name="category" />
<public type="attr" name="isAsciiCapable" />
- <public type="attr" name="customRoots" />
<public type="attr" name="autoMirrored" />
<public type="attr" name="supportsSwitchingToNextInputMethod" />
<public type="attr" name="requireDeviceUnlock" />
<public type="attr" name="apduServiceBanner" />
- <public type="attr" name="provideAssistData" />
</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 68acd8c2dcd4..fa6ecc84a2da 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -831,7 +831,7 @@
<string name="permlab_getTopActivityInfo">get current app info</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_getTopActivityInfo">Allows the holder to retrieve private information
- about the current application and services in the foreground of the screen.</string>
+ about the current application in the foreground of the screen.</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_runSetActivityWatcher">monitor and control all app launching</string>
@@ -1596,6 +1596,14 @@
<string name="permdesc_wakeLock" product="default">Allows the app to prevent the phone from going to sleep.</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_transmitIr">transmit infrared</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_transmitIr" product="tablet">Allows the app to use the tablet\'s infrared transmitter.</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_transmitIr" product="default">Allows the app to use the phone\'s infrared transmitter.</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_devicePower" product="tablet">power tablet on or off</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_devicePower" product="default">power phone on or off</string>
@@ -1911,11 +1919,6 @@
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permdesc_accessNetworkConditions">Allows an application to listen for observations on network conditions. 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_hotwordRecognition">request hotword recognition</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_hotwordRecognition">Allows an application to request for hotword recognition. Should never be needed for normal apps.</string>
-
<!-- Policy administration -->
<!-- Title of policy access to limiting the user's password choices -->
diff --git a/core/tests/ConnectivityManagerTest/AndroidManifest.xml b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
index 54881d53c240..7e0202e32d1e 100644
--- a/core/tests/ConnectivityManagerTest/AndroidManifest.xml
+++ b/core/tests/ConnectivityManagerTest/AndroidManifest.xml
@@ -16,8 +16,7 @@
<!-- package name must be unique so suffix with "tests" so package loader doesn't ignore us -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.android.connectivitymanagertest"
- android:sharedUserId="android.uid.system">
+ package="com.android.connectivitymanagertest">
<!-- We add an application tag here just so that we can indicate that
this package needs to link against the android.test library,
diff --git a/core/tests/coretests/src/android/database/MatrixCursorTest.java b/core/tests/coretests/src/android/database/MatrixCursorTest.java
index fc48c17db839..aa805dca817e 100644
--- a/core/tests/coretests/src/android/database/MatrixCursorTest.java
+++ b/core/tests/coretests/src/android/database/MatrixCursorTest.java
@@ -132,18 +132,18 @@ public class MatrixCursorTest extends TestCase {
MatrixCursor cursor = newMatrixCursor();
cursor.newRow()
- .offer("float", 4.2f)
- .offer("string", "foobar")
- .offer("blob", new byte[] {(byte) 0xaa, (byte) 0x55})
- .offer("lolwat", "kittens");
+ .add("float", 4.2f)
+ .add("string", "foobar")
+ .add("blob", new byte[] {(byte) 0xaa, (byte) 0x55})
+ .add("lolwat", "kittens");
cursor.newRow();
cursor.newRow()
- .offer("string", "zero")
- .offer("string", "one")
- .offer("string", "two")
- .offer("lolwat", "kittens");
+ .add("string", "zero")
+ .add("string", "one")
+ .add("string", "two")
+ .add("lolwat", "kittens");
assertTrue(cursor.moveToFirst());
assertEquals("foobar", cursor.getString(0));
diff --git a/data/fonts/fallback_fonts.xml b/data/fonts/fallback_fonts.xml
index d9170c9e296d..1198aba5f88c 100644
--- a/data/fonts/fallback_fonts.xml
+++ b/data/fonts/fallback_fonts.xml
@@ -175,6 +175,12 @@
</family>
<family>
<fileset>
+ <file>Padauk-book.ttf</file>
+ <file>Padauk-bookbold.ttf</file>
+ </fileset>
+ </family>
+ <family>
+ <fileset>
<file>NotoSansSymbols-Regular.ttf</file>
</fileset>
</family>
diff --git a/docs/html/guide/topics/ui/how-android-draws.jd b/docs/html/guide/topics/ui/how-android-draws.jd
index 6a8cd869e535..168f77b265cf 100644
--- a/docs/html/guide/topics/ui/how-android-draws.jd
+++ b/docs/html/guide/topics/ui/how-android-draws.jd
@@ -4,15 +4,19 @@ parent.link=index.html
@jd:body
-<p>When an Activity receives focus, it will be requested to draw its layout.
-The Android framework will handle the procedure for drawing, but the Activity must provide
+<p>When an {@link android.app.Activity} receives focus, it will be requested to
+draw its layout.
+The Android framework will handle the procedure for drawing, but the
+{@link android.app.Activity} must provide
the root node of its layout hierarchy.</p>
<p>Drawing begins with the root node of the layout. It is requested to measure and
-draw the layout tree. Drawing is handled by walking the tree and rendering each View that
- intersects the invalid region. In turn, each View group is responsible for requesting
-each of its children to be drawn (with the <code>{@link android.view.View#draw(Canvas) draw()}</code> method)
-and each View is responsible for drawing itself.
+draw the layout tree. Drawing is handled by walking the tree and rendering each
+{@link android.view.View} that intersects the invalid region. In turn, each
+{@link android.view.ViewGroup} is responsible for requesting
+each of its children to be drawn
+(with the {@link android.view.View#draw(Canvas) draw()} method)
+and each {@link android.view.View} is responsible for drawing itself.
Because the tree is traversed in-order,
this means that parents will be drawn before (i.e., behind) their children, with
siblings drawn in the order they appear in the tree.
@@ -20,76 +24,107 @@ and each View is responsible for drawing itself.
<div class="sidebox-wrapper">
<div class="sidebox">
- <p>The framework will not draw Views that are not in the invalid region, and also
- will take care of drawing the Views background for you.</p>
- <p>You can force a View to draw, by calling <code>{@link android.view.View#invalidate()}</code>.
+ <p>The framework will not draw {@link android.view.View} objects that are not
+in the invalid region, and also
+ will take care of drawing the {@link android.view.View} background for you.</p>
+ <p>You can force a {@link android.view.View} to draw, by calling
+{@link android.view.View#invalidate()}.
</p>
</div>
</div>
<p>
- Drawing the layout is a two pass process: a measure pass and a layout pass. The measuring
- pass is implemented in <code>{@link android.view.View#measure(int, int)}</code> and is a top-down traversal
- of the View tree. Each View pushes dimension specifications down the tree
- during the recursion. At the end of the measure pass, every View has stored
+ Drawing the layout is a two pass process: a measure pass and a layout pass.
+The measuring pass is implemented in {@link android.view.View#measure(int, int)}
+and is a top-down traversal of the {@link android.view.View} tree. Each {@link android.view.View}
+pushes dimension specifications down the tree
+ during the recursion. At the end of the measure pass, every
+{@link android.view.View} has stored
its measurements. The second pass happens in
- <code>{@link android.view.View#layout(int,int,int,int)}</code> and is also top-down. During
+ {@link android.view.View#layout(int,int,int,int)} and is also top-down. During
this pass each parent is responsible for positioning all of its children
using the sizes computed in the measure pass.
</p>
<p>
- When a View's <code>measure()</code> method returns, its <code>{@link android.view.View#getMeasuredWidth()}</code> and
- <code>{@link android.view.View#getMeasuredHeight()}</code> values must be set, along with those for all of
- that View's descendants. A View's measured width and measured height values
- must respect the constraints imposed by the View's parents. This guarantees
+ When a {@link android.view.View} object's
+{@link android.view.View#measure(int, int) measure()} method
+returns, its {@link android.view.View#getMeasuredWidth()} and
+ {@link android.view.View#getMeasuredHeight()} values must be set, along
+ with those for all of that {@link android.view.View} object's descendants.
+A {@link android.view.View} object's measured width and
+measured height values must respect the constraints imposed by the
+{@link android.view.View} object's parents. This guarantees
that at the end of the measure pass, all parents accept all of their
- children's measurements. A parent View may call <code>measure()</code> more than once on
+ children's measurements. A parent {@link android.view.View} may call
+{@link android.view.View#measure(int, int) measure()} more than once on
its children. For example, the parent may measure each child once with
unspecified dimensions to find out how big they want to be, then call
- <code>measure()</code> on them again with actual numbers if the sum of all the children's
- unconstrained sizes is too big or too small (i.e., if the children don't agree among themselves
- as to how much space they each get, the parent will intervene and set the rules on the second pass).
+ {@link android.view.View#measure(int, int) measure()} on them again with
+actual numbers if the sum of all the children's
+ unconstrained sizes is too big or too small (that is, if the children
+don't agree among themselves
+ as to how much space they each get, the parent will intervene and set
+the rules on the second pass).
</p>
<div class="sidebox-wrapper">
<div class="sidebox"><p>
- To initiate a layout, call <code>{@link android.view.View#requestLayout}</code>. This method is typically
- called by a View on itself when it believes that is can no longer fit within
+ To initiate a layout, call {@link android.view.View#requestLayout}.
+This method is typically
+ called by a {@link android.view.View} on itself
+when it believes that is can no longer fit within
its current bounds.</p>
</div>
</div>
<p>
The measure pass uses two classes to communicate dimensions. The
- {@link android.view.ViewGroup.LayoutParams} class is used by Views to tell their parents how they
- want to be measured and positioned. The base LayoutParams class just
- describes how big the View wants to be for both width and height. For each
+ {@link android.view.ViewGroup.LayoutParams} class is used by
+{@link android.view.View} objects to tell their parents how they
+ want to be measured and positioned. The base
+{@link android.view.ViewGroup.LayoutParams} class just
+ describes how big the {@link android.view.View} wants to be for both
+width and height. For each
dimension, it can specify one of:</p>
<ul>
<li> an exact number
- <li><var>FILL_PARENT</var>, which means the View wants to be as big as its parent
+ <li>{@link android.view.ViewGroup.LayoutParams#MATCH_PARENT MATCH_PARENT},
+which means the {@link android.view.View} wants to be as big as its parent
(minus padding)</li>
- <li><var>WRAP_CONTENT</var>, which means that the View wants to be just big enough to
+ <li>{@link android.view.ViewGroup.LayoutParams#WRAP_CONTENT WRAP_CONTENT},
+which means that the {@link android.view.View} wants to be just big enough to
enclose its content (plus padding).</li>
</ul>
- <p>There are subclasses of LayoutParams for different subclasses of ViewGroup.
- For example, RelativeLayout has its own subclass of LayoutParams, which includes
- the ability to center child Views horizontally and vertically.
+ <p>There are subclasses of {@link android.view.ViewGroup.LayoutParams} for
+different subclasses of {@link android.view.ViewGroup}.
+ For example, {@link android.widget.RelativeLayout} has its own subclass of
+{@link android.view.ViewGroup.LayoutParams}, which includes
+ the ability to center child {@link android.view.View} objects
+horizontally and vertically.
</p>
<p>
- MeasureSpecs are used to push requirements down the tree from parent to
- child. A MeasureSpec can be in one of three modes:</p>
+ {@link android.view.View.MeasureSpec MeasureSpec} objects are used to push
+requirements down the tree from parent to
+ child. A {@link android.view.View.MeasureSpec MeasureSpec} can be in one of
+three modes:</p>
<ul>
- <li><var>UNSPECIFIED</var>: This is used by a parent to determine the desired dimension
- of a child View. For example, a LinearLayout may call <code>measure()</code> on its child
- with the height set to <var>UNSPECIFIED</var> and a width of <var>EXACTLY</var> 240 to find out how
- tall the child View wants to be given a width of 240 pixels.</li>
- <li><var>EXACTLY</var>: This is used by the parent to impose an exact size on the
+ <li>{@link android.view.View.MeasureSpec#UNSPECIFIED UNSPECIFIED}: This is
+used by a parent to determine the desired dimension
+ of a child {@link android.view.View}. For example, a
+{@link android.widget.LinearLayout} may call
+{@link android.view.View#measure(int, int) measure()} on its child
+ with the height set to {@link android.view.View.MeasureSpec#UNSPECIFIED UNSPECIFIED}
+and a width of {@link android.view.View.MeasureSpec#EXACTLY EXACTLY} 240 to
+find out how tall the child {@link android.view.View} wants to be given a
+width of 240 pixels.</li>
+ <li>{@link android.view.View.MeasureSpec#EXACTLY EXACTLY}: This is used
+by the parent to impose an exact size on the
child. The child must use this size, and guarantee that all of its
descendants will fit within this size.</li>
- <li><var>AT_MOST</var>: This is used by the parent to impose a maximum size on the
+ <li>{@link android.view.View.MeasureSpec#AT_MOST AT MOST}: This is used by
+the parent to impose a maximum size on the
child. The child must guarantee that it and all of its descendants will fit
within this size.</li>
</ul>
diff --git a/docs/html/training/id-auth/authenticate.jd b/docs/html/training/id-auth/authenticate.jd
index 3084beac35a9..65dbc3987bd3 100644
--- a/docs/html/training/id-auth/authenticate.jd
+++ b/docs/html/training/id-auth/authenticate.jd
@@ -79,7 +79,7 @@ a valid auth token from the Android Account Manager"/>
<p>To get an auth token you first need to request the
{@link android.Manifest.permission#ACCOUNT_MANAGER}
-to yourmanifest file. To actually do anything useful with the
+to your manifest file. To actually do anything useful with the
token, you'll also need to add the {@link android.Manifest.permission#INTERNET}
permission.</p>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index 4193dbb32449..23606a189424 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -56,15 +56,26 @@ public class BitmapFactory {
* mutable even when decoding a resource which would normally result in
* an immutable bitmap.</p>
*
+ * <p>You should still always use the returned Bitmap of the decode
+ * method and not assume that reusing the bitmap worked, due to the
+ * constraints outlined above and failure situations that can occur.
+ * Checking whether the return value matches the value of the inBitmap
+ * set in the Options structure will indicate if the bitmap was reused,
+ * but in all cases you should use the Bitmap returned by the decoding
+ * function to ensure that you are using the bitmap that was used as the
+ * decode destination.</p>
+ *
+ * <h3>Usage with BitmapFactory</h3>
+ *
* <p>As of {@link android.os.Build.VERSION_CODES#KITKAT}, any
- * mutable bitmap can be reused to decode any other bitmaps as long as
- * the resulting {@link Bitmap#getByteCount() byte count} of the decoded
- * bitmap is less than or equal to the {@link
+ * mutable bitmap can be reused by {@link BitmapFactory} to decode any
+ * other bitmaps as long as the resulting {@link Bitmap#getByteCount()
+ * byte count} of the decoded bitmap is less than or equal to the {@link
* Bitmap#getAllocationByteCount() allocated byte count} of the reused
* bitmap. This can be because the intrinsic size is smaller, or its
* size post scaling (for density / sample size) is smaller.</p>
*
- * <p>Prior to {@link android.os.Build.VERSION_CODES#KITKAT}
+ * <p class="note">Prior to {@link android.os.Build.VERSION_CODES#KITKAT}
* additional constraints apply: The image being decoded (whether as a
* resource or as a stream) must be in jpeg or png format. Only equal
* sized bitmaps are supported, with {@link #inSampleSize} set to 1.
@@ -72,14 +83,17 @@ public class BitmapFactory {
* configuration} of the reused bitmap will override the setting of
* {@link #inPreferredConfig}, if set.</p>
*
- * <p>You should still always use the returned Bitmap of the decode
- * method and not assume that reusing the bitmap worked, due to the
- * constraints outlined above and failure situations that can occur.
- * Checking whether the return value matches the value of the inBitmap
- * set in the Options structure will indicate if the bitmap was reused,
- * but in all cases you should use the Bitmap returned by the decoding
- * function to ensure that you are using the bitmap that was used as the
- * decode destination.</p>
+ * <h3>Usage with BitmapRegionDecoder</h3>
+ *
+ * <p>BitmapRegionDecoder will draw its requested content into the Bitmap
+ * provided, clipping if the output content size (post scaling) is larger
+ * than the provided Bitmap. The provided Bitmap's width, height, and
+ * {@link Bitmap.Config} will not be changed.
+ *
+ * <p class="note">BitmapRegionDecoder support for {@link #inBitmap} was
+ * introduced in {@link android.os.Build.VERSION_CODES#JELLY_BEAN}. All
+ * formats supported by BitmapRegionDecoder support Bitmap reuse via
+ * {@link #inBitmap}.</p>
*
* @see Bitmap#reconfigure(int,int, android.graphics.Bitmap.Config)
*/
@@ -229,6 +243,9 @@ public class BitmapFactory {
* rather than relying on the graphics system scaling it each time it
* is drawn to a Canvas.
*
+ * <p>BitmapRegionDecoder ignores this flag, and will not scale output
+ * based on density. (though {@link #inSampleSize} is supported)</p>
+ *
* <p>This flag is turned on by default and should be turned off if you need
* a non-scaled version of the bitmap. Nine-patch bitmaps ignore this
* flag and are always scaled.
@@ -548,24 +565,10 @@ public class BitmapFactory {
Trace.traceBegin(Trace.TRACE_TAG_GRAPHICS, "decodeBitmap");
try {
- boolean decodeGenericStream = true;
if (is instanceof AssetManager.AssetInputStream) {
final int asset = ((AssetManager.AssetInputStream) is).getAssetInt();
bm = nativeDecodeAsset(asset, outPadding, opts);
- // Do not follow the normal case.
- decodeGenericStream = false;
- } else if (is instanceof FileInputStream) {
- try {
- FileDescriptor fd = ((FileInputStream) is).getFD();
- // decodeFileDescriptor will take care of throwing the IAE and
- // calling setDensityFromOptions.
- return decodeFileDescriptor(fd, outPadding, opts);
- } catch (IOException e) {
- // Fall through to nativeDecodeStream.
- }
- }
-
- if (decodeGenericStream) {
+ } else {
byte [] tempStorage = null;
if (opts != null) tempStorage = opts.inTempStorage;
if (tempStorage == null) tempStorage = new byte[DECODE_BUFFER_SIZE];
diff --git a/graphics/java/android/graphics/PixelFormat.java b/graphics/java/android/graphics/PixelFormat.java
index 0230583c318f..d96d6d841952 100644
--- a/graphics/java/android/graphics/PixelFormat.java
+++ b/graphics/java/android/graphics/PixelFormat.java
@@ -19,16 +19,16 @@ package android.graphics;
public class PixelFormat
{
/* these constants need to match those in hardware/hardware.h */
-
+
public static final int UNKNOWN = 0;
/** System chooses a format that supports translucency (many alpha bits) */
public static final int TRANSLUCENT = -3;
- /**
+ /**
* System chooses a format that supports transparency
- * (at least 1 alpha bit)
- */
+ * (at least 1 alpha bit)
+ */
public static final int TRANSPARENT = -2;
/** System chooses an opaque format (no alpha bits required) */
@@ -54,28 +54,28 @@ public class PixelFormat
/**
- * @deprecated use {@link android.graphics.ImageFormat#NV16
+ * @deprecated use {@link android.graphics.ImageFormat#NV16
* ImageFormat.NV16} instead.
*/
@Deprecated
public static final int YCbCr_422_SP= 0x10;
/**
- * @deprecated use {@link android.graphics.ImageFormat#NV21
+ * @deprecated use {@link android.graphics.ImageFormat#NV21
* ImageFormat.NV21} instead.
*/
@Deprecated
public static final int YCbCr_420_SP= 0x11;
/**
- * @deprecated use {@link android.graphics.ImageFormat#YUY2
+ * @deprecated use {@link android.graphics.ImageFormat#YUY2
* ImageFormat.YUY2} instead.
*/
@Deprecated
public static final int YCbCr_422_I = 0x14;
/**
- * @deprecated use {@link android.graphics.ImageFormat#JPEG
+ * @deprecated use {@link android.graphics.ImageFormat#JPEG
* ImageFormat.JPEG} instead.
*/
@Deprecated
@@ -95,6 +95,7 @@ public class PixelFormat
case RGB_565:
case RGBA_5551:
case RGBA_4444:
+ case LA_88:
info.bitsPerPixel = 16;
info.bytesPerPixel = 2;
break;
@@ -131,7 +132,7 @@ public class PixelFormat
}
return false;
}
-
+
public int bytesPerPixel;
public int bitsPerPixel;
}
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java
index e8d6f1651a6c..b910a24d9292 100644
--- a/graphics/java/android/graphics/SurfaceTexture.java
+++ b/graphics/java/android/graphics/SurfaceTexture.java
@@ -21,6 +21,7 @@ import java.lang.ref.WeakReference;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.view.Surface;
/**
* Captures frames from an image stream as an OpenGL ES texture.
@@ -80,8 +81,12 @@ public class SurfaceTexture {
}
/**
- * Exception thrown when a surface couldn't be created or resized
+ * Exception thrown when a SurfaceTexture couldn't be created or resized.
+ *
+ * @deprecated No longer thrown. {@link Surface.OutOfResourcesException} is used instead.
*/
+ @SuppressWarnings("serial")
+ @Deprecated
public static class OutOfResourcesException extends Exception {
public OutOfResourcesException() {
}
@@ -94,6 +99,8 @@ public class SurfaceTexture {
* Construct a new SurfaceTexture to stream images to a given OpenGL texture.
*
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
+ *
+ * @throws OutOfResourcesException If the SurfaceTexture cannot be created.
*/
public SurfaceTexture(int texName) {
init(texName, false);
@@ -113,6 +120,8 @@ public class SurfaceTexture {
*
* @param texName the OpenGL texture object name (e.g. generated via glGenTextures)
* @param singleBufferMode whether the SurfaceTexture will be in single buffered mode.
+ *
+ * @throws throws OutOfResourcesException If the SurfaceTexture cannot be created.
*/
public SurfaceTexture(int texName, boolean singleBufferMode) {
init(texName, singleBufferMode);
@@ -140,9 +149,9 @@ public class SurfaceTexture {
* android.view.Surface#lockCanvas} is called. For OpenGL ES, the EGLSurface should be
* destroyed (via eglDestroySurface), made not-current (via eglMakeCurrent), and then recreated
* (via eglCreateWindowSurface) to ensure that the new default size has taken effect.
- *
+ *
* The width and height parameters must be no greater than the minimum of
- * GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see
+ * GL_MAX_VIEWPORT_DIMS and GL_MAX_TEXTURE_SIZE (see
* {@link javax.microedition.khronos.opengles.GL10#glGetIntegerv glGetIntegerv}).
* An error due to invalid dimensions might not be reported until
* updateTexImage() is called.
@@ -267,6 +276,7 @@ public class SurfaceTexture {
nativeRelease();
}
+ @Override
protected void finalize() throws Throwable {
try {
nativeFinalize();
@@ -305,7 +315,7 @@ public class SurfaceTexture {
}
}
- private void init(int texName, boolean singleBufferMode) {
+ private void init(int texName, boolean singleBufferMode) throws Surface.OutOfResourcesException {
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(looper);
@@ -317,7 +327,8 @@ public class SurfaceTexture {
nativeInit(texName, singleBufferMode, new WeakReference<SurfaceTexture>(this));
}
- private native void nativeInit(int texName, boolean singleBufferMode, Object weakSelf);
+ private native void nativeInit(int texName, boolean singleBufferMode, Object weakSelf)
+ throws Surface.OutOfResourcesException;
private native void nativeFinalize();
private native void nativeGetTransformMatrix(float[] mtx);
private native long nativeGetTimestamp();
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index ca72c25fb7b9..dca934f82cab 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -269,9 +269,12 @@ public class Allocation extends BaseObj {
mType = t;
mUsage = usage;
- mSize = mType.getCount() * mType.getElement().getBytesSize();
if (t != null) {
+ // TODO: A3D doesn't have Type info during creation, so we can't
+ // calculate the size ahead of time. We can possibly add a method
+ // to update the size in the future if it seems reasonable.
+ mSize = mType.getCount() * mType.getElement().getBytesSize();
updateCacheInfo(t);
}
try {
diff --git a/graphics/jni/android_renderscript_RenderScript.cpp b/graphics/jni/android_renderscript_RenderScript.cpp
index 690493d2aa5c..cbc4e5a96a28 100644
--- a/graphics/jni/android_renderscript_RenderScript.cpp
+++ b/graphics/jni/android_renderscript_RenderScript.cpp
@@ -184,7 +184,7 @@ static jint
nContextCreate(JNIEnv *_env, jobject _this, jint dev, jint ver, jint sdkVer, jint ct)
{
LOG_API("nContextCreate");
- return (jint)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, false, false);
+ return (jint)rsContextCreate((RsDevice)dev, ver, sdkVer, (RsContextType)ct, 0);
}
static jint
diff --git a/libs/androidfw/ZipFileRO.cpp b/libs/androidfw/ZipFileRO.cpp
index b84f3b087631..ec5f95c8b4f7 100644
--- a/libs/androidfw/ZipFileRO.cpp
+++ b/libs/androidfw/ZipFileRO.cpp
@@ -46,31 +46,41 @@ using namespace android;
/*
* Zip file constants.
*/
-#define kEOCDSignature 0x06054b50
-#define kEOCDLen 22
-#define kEOCDNumEntries 8 // offset to #of entries in file
-#define kEOCDSize 12 // size of the central directory
-#define kEOCDFileOffset 16 // offset to central directory
-
-#define kMaxCommentLen 65535 // longest possible in ushort
-#define kMaxEOCDSearch (kMaxCommentLen + kEOCDLen)
-
-#define kLFHSignature 0x04034b50
-#define kLFHLen 30 // excluding variable-len fields
-#define kLFHNameLen 26 // offset to filename length
-#define kLFHExtraLen 28 // offset to extra length
-
-#define kCDESignature 0x02014b50
-#define kCDELen 46 // excluding variable-len fields
-#define kCDEMethod 10 // offset to compression method
-#define kCDEModWhen 12 // offset to modification timestamp
-#define kCDECRC 16 // offset to entry CRC
-#define kCDECompLen 20 // offset to compressed length
-#define kCDEUncompLen 24 // offset to uncompressed length
-#define kCDENameLen 28 // offset to filename length
-#define kCDEExtraLen 30 // offset to extra length
-#define kCDECommentLen 32 // offset to comment length
-#define kCDELocalOffset 42 // offset to local hdr
+#define kEOCDSignature 0x06054b50
+#define kEOCDLen 22
+#define kEOCDDiskNumber 4 // number of the current disk
+#define kEOCDDiskNumberForCD 6 // disk number with the Central Directory
+#define kEOCDNumEntries 8 // offset to #of entries in file
+#define kEOCDTotalNumEntries 10 // offset to total #of entries in spanned archives
+#define kEOCDSize 12 // size of the central directory
+#define kEOCDFileOffset 16 // offset to central directory
+#define kEOCDCommentSize 20 // offset to the length of the file comment
+
+#define kMaxCommentLen 65535 // longest possible in ushort
+#define kMaxEOCDSearch (kMaxCommentLen + kEOCDLen)
+
+#define kLFHSignature 0x04034b50
+#define kLFHLen 30 // excluding variable-len fields
+#define kLFHGPBFlags 6 // offset to GPB flags
+#define kLFHNameLen 26 // offset to filename length
+#define kLFHExtraLen 28 // offset to extra length
+
+#define kCDESignature 0x02014b50
+#define kCDELen 46 // excluding variable-len fields
+#define kCDEGPBFlags 8 // offset to GPB flags
+#define kCDEMethod 10 // offset to compression method
+#define kCDEModWhen 12 // offset to modification timestamp
+#define kCDECRC 16 // offset to entry CRC
+#define kCDECompLen 20 // offset to compressed length
+#define kCDEUncompLen 24 // offset to uncompressed length
+#define kCDENameLen 28 // offset to filename length
+#define kCDEExtraLen 30 // offset to extra length
+#define kCDECommentLen 32 // offset to comment length
+#define kCDELocalOffset 42 // offset to local hdr
+
+/* General Purpose Bit Flag */
+#define kGPFEncryptedFlag (1 << 0)
+#define kGPFUnsupportedMask (kGPFEncryptedFlag)
/*
* The values we return for ZipEntryRO use 0 as an invalid value, so we
@@ -170,6 +180,11 @@ bool ZipFileRO::mapCentralDirectory(void)
if (readAmount > (ssize_t) mFileLength)
readAmount = mFileLength;
+ if (readAmount < kEOCDSize) {
+ ALOGW("File too short to be a zip file");
+ return false;
+ }
+
unsigned char* scanBuf = (unsigned char*) malloc(readAmount);
if (scanBuf == NULL) {
ALOGW("couldn't allocate scanBuf: %s", strerror(errno));
@@ -193,17 +208,11 @@ bool ZipFileRO::mapCentralDirectory(void)
return false;
}
- {
- unsigned int header = get4LE(scanBuf);
- if (header == kEOCDSignature) {
- ALOGI("Found Zip archive, but it looks empty\n");
- free(scanBuf);
- return false;
- } else if (header != kLFHSignature) {
- ALOGV("Not a Zip archive (found 0x%08x)\n", header);
- free(scanBuf);
- return false;
- }
+ unsigned int header = get4LE(scanBuf);
+ if (header != kLFHSignature) {
+ ALOGV("Not a Zip archive (found 0x%08x)\n", header);
+ free(scanBuf);
+ return false;
}
/*
@@ -261,24 +270,38 @@ bool ZipFileRO::mapCentralDirectory(void)
* Grab the CD offset and size, and the number of entries in the
* archive. After that, we can release our EOCD hunt buffer.
*/
+ unsigned int diskNumber = get2LE(eocdPtr + kEOCDDiskNumber);
+ unsigned int diskWithCentralDir = get2LE(eocdPtr + kEOCDDiskNumberForCD);
unsigned int numEntries = get2LE(eocdPtr + kEOCDNumEntries);
- unsigned int dirSize = get4LE(eocdPtr + kEOCDSize);
- unsigned int dirOffset = get4LE(eocdPtr + kEOCDFileOffset);
+ unsigned int totalNumEntries = get2LE(eocdPtr + kEOCDTotalNumEntries);
+ unsigned int centralDirSize = get4LE(eocdPtr + kEOCDSize);
+ unsigned int centralDirOffset = get4LE(eocdPtr + kEOCDFileOffset);
+ unsigned int commentSize = get2LE(eocdPtr + kEOCDCommentSize);
free(scanBuf);
// Verify that they look reasonable.
- if ((long long) dirOffset + (long long) dirSize > (long long) eocdOffset) {
+ if ((long long) centralDirOffset + (long long) centralDirSize > (long long) eocdOffset) {
ALOGW("bad offsets (dir %ld, size %u, eocd %ld)\n",
- (long) dirOffset, dirSize, (long) eocdOffset);
+ (long) centralDirOffset, centralDirSize, (long) eocdOffset);
return false;
}
if (numEntries == 0) {
ALOGW("empty archive?\n");
return false;
+ } else if (numEntries != totalNumEntries || diskNumber != 0 || diskWithCentralDir != 0) {
+ ALOGW("spanned archives not supported");
+ return false;
+ }
+
+ // Check to see if comment is a sane size
+ if ((commentSize > (mFileLength - kEOCDLen))
+ || (eocdOffset > (mFileLength - kEOCDLen) - commentSize)) {
+ ALOGW("comment size runs off end of file");
+ return false;
}
ALOGV("+++ numEntries=%d dirSize=%d dirOffset=%d\n",
- numEntries, dirSize, dirOffset);
+ numEntries, centralDirSize, centralDirOffset);
mDirectoryMap = new FileMap();
if (mDirectoryMap == NULL) {
@@ -286,14 +309,14 @@ bool ZipFileRO::mapCentralDirectory(void)
return false;
}
- if (!mDirectoryMap->create(mFileName, mFd, dirOffset, dirSize, true)) {
+ if (!mDirectoryMap->create(mFileName, mFd, centralDirOffset, centralDirSize, true)) {
ALOGW("Unable to map '%s' (" ZD " to " ZD "): %s\n", mFileName,
- (ZD_TYPE) dirOffset, (ZD_TYPE) (dirOffset + dirSize), strerror(errno));
+ (ZD_TYPE) centralDirOffset, (ZD_TYPE) (centralDirOffset + centralDirSize), strerror(errno));
return false;
}
mNumEntries = numEntries;
- mDirectoryOffset = dirOffset;
+ mDirectoryOffset = centralDirOffset;
return true;
}
@@ -352,17 +375,30 @@ bool ZipFileRO::parseZipArchive(void)
goto bail;
}
- unsigned int fileNameLen, extraLen, commentLen, hash;
+ unsigned int gpbf = get2LE(ptr + kCDEGPBFlags);
+ if ((gpbf & kGPFUnsupportedMask) != 0) {
+ ALOGW("Invalid General Purpose Bit Flag: %d", gpbf);
+ goto bail;
+ }
+
+ unsigned int nameLen = get2LE(ptr + kCDENameLen);
+ unsigned int extraLen = get2LE(ptr + kCDEExtraLen);
+ unsigned int commentLen = get2LE(ptr + kCDECommentLen);
+
+ const char *name = (const char *) ptr + kCDELen;
- fileNameLen = get2LE(ptr + kCDENameLen);
- extraLen = get2LE(ptr + kCDEExtraLen);
- commentLen = get2LE(ptr + kCDECommentLen);
+ /* Check name for NULL characters */
+ if (memchr(name, 0, nameLen) != NULL) {
+ ALOGW("Filename contains NUL byte");
+ goto bail;
+ }
/* add the CDE filename to the hash table */
- hash = computeHash((const char*)ptr + kCDELen, fileNameLen);
- addToHash((const char*)ptr + kCDELen, fileNameLen, hash);
+ unsigned int hash = computeHash(name, nameLen);
+ addToHash(name, nameLen, hash);
- ptr += kCDELen + fileNameLen + extraLen + commentLen;
+ /* We don't care about the comment or extra data. */
+ ptr += kCDELen + nameLen + extraLen + commentLen;
if ((size_t)(ptr - cdPtr) > cdLength) {
ALOGW("bad CD advance (%d vs " ZD ") at entry %d\n",
(int) (ptr - cdPtr), (ZD_TYPE) cdLength, i);
@@ -475,8 +511,10 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
bool ret = false;
const int ent = entryToIndex(entry);
- if (ent < 0)
+ if (ent < 0) {
+ ALOGW("cannot find entry");
return false;
+ }
HashEntry hashEntry = mHashTable[ent];
@@ -585,6 +623,12 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
}
#endif /* HAVE_PREAD */
+ unsigned int gpbf = get2LE(lfhBuf + kLFHGPBFlags);
+ if ((gpbf & kGPFUnsupportedMask) != 0) {
+ ALOGW("Invalid General Purpose Bit Flag: %d", gpbf);
+ return false;
+ }
+
off64_t dataOffset = localHdrOffset + kLFHLen
+ get2LE(lfhBuf + kLFHNameLen) + get2LE(lfhBuf + kLFHExtraLen);
if (dataOffset >= cdOffset) {
@@ -593,14 +637,15 @@ bool ZipFileRO::getEntryInfo(ZipEntryRO entry, int* pMethod, size_t* pUncompLen,
}
/* check lengths */
- if ((off64_t)(dataOffset + compLen) > cdOffset) {
+ if ((dataOffset >= cdOffset) || (compLen > (cdOffset - dataOffset))) {
ALOGW("bad compressed length in zip (%ld + " ZD " > %ld)\n",
(long) dataOffset, (ZD_TYPE) compLen, (long) cdOffset);
return false;
}
if (method == kCompressStored &&
- (off64_t)(dataOffset + uncompLen) > cdOffset)
+ ((dataOffset >= cdOffset) ||
+ (uncompLen > (cdOffset - dataOffset))))
{
ALOGE("ERROR: bad uncompressed length in zip (%ld + " ZD " > %ld)\n",
(long) dataOffset, (ZD_TYPE) uncompLen, (long) cdOffset);
@@ -645,14 +690,24 @@ FileMap* ZipFileRO::createEntryFileMap(ZipEntryRO entry) const
*/
FileMap* newMap;
+ int method;
+ size_t uncompLen;
size_t compLen;
off64_t offset;
- if (!getEntryInfo(entry, NULL, NULL, &compLen, &offset, NULL, NULL))
+ if (!getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL)) {
return NULL;
+ }
+
+ size_t actualLen;
+ if (method == kCompressStored) {
+ actualLen = uncompLen;
+ } else {
+ actualLen = compLen;
+ }
newMap = new FileMap();
- if (!newMap->create(mFileName, mFd, offset, compLen, true)) {
+ if (!newMap->create(mFileName, mFd, offset, actualLen, true)) {
newMap->release();
return NULL;
}
@@ -671,17 +726,21 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, void* buffer) const
const size_t kSequentialMin = 32768;
bool result = false;
int ent = entryToIndex(entry);
- if (ent < 0)
- return -1;
+ if (ent < 0) {
+ return false;
+ }
int method;
size_t uncompLen, compLen;
off64_t offset;
const unsigned char* ptr;
+ FileMap *file;
- getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
+ if (!getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL)) {
+ goto bail;
+ }
- FileMap* file = createEntryFileMap(entry);
+ file = createEntryFileMap(entry);
if (file == NULL) {
goto bail;
}
@@ -731,17 +790,21 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const
{
bool result = false;
int ent = entryToIndex(entry);
- if (ent < 0)
- return -1;
+ if (ent < 0) {
+ return false;
+ }
int method;
size_t uncompLen, compLen;
off64_t offset;
const unsigned char* ptr;
+ FileMap *file;
- getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL);
+ if (!getEntryInfo(entry, &method, &uncompLen, &compLen, &offset, NULL, NULL)) {
+ goto bail;
+ }
- FileMap* file = createEntryFileMap(entry);
+ file = createEntryFileMap(entry);
if (file == NULL) {
goto bail;
}
@@ -761,8 +824,9 @@ bool ZipFileRO::uncompressEntry(ZipEntryRO entry, int fd) const
ALOGI("+++ successful write\n");
}
} else {
- if (!inflateBuffer(fd, ptr, uncompLen, compLen))
+ if (!inflateBuffer(fd, ptr, uncompLen, compLen)) {
goto unmap;
+ }
}
result = true;
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp
index 22b1485eaa45..7e99a5fd44d2 100644
--- a/libs/hwui/FontRenderer.cpp
+++ b/libs/hwui/FontRenderer.cpp
@@ -732,7 +732,7 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int
if (mRs == 0) {
mRs = new RSC::RS();
- if (!mRs->init(true, true)) {
+ if (!mRs->init(RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) {
ALOGE("blur RS failed to init");
}
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 238d9a4955c6..2066f697dca8 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -471,12 +471,14 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
info.height = getSnapshot()->height;
getSnapshot()->transform->copyTo(&info.transform[0]);
+ bool dirtyClip = mDirtyClip;
// setup GL state for functor
if (mDirtyClip) {
- setScissorFromClip();
setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt()
}
- mCaches.enableScissor();
+ if (mCaches.enableScissor() || dirtyClip) {
+ setScissorFromClip();
+ }
interrupt();
// call functor immediately after GL state setup
diff --git a/location/java/android/location/LocationManager.java b/location/java/android/location/LocationManager.java
index 14b812e8b284..ccb4304e9f6c 100644
--- a/location/java/android/location/LocationManager.java
+++ b/location/java/android/location/LocationManager.java
@@ -152,17 +152,18 @@ public class LocationManager {
/**
* Broadcast intent action when the configured location providers
- * change. If you're interacting with the
- * {@link android.provider.Settings.Secure#LOCATION_MODE} API,
- * use {@link #MODE_CHANGED_ACTION} instead.
+ * change. For use with {@link #isProviderEnabled(String)}. If you're interacting with the
+ * {@link android.provider.Settings.Secure#LOCATION_MODE} API, use {@link #MODE_CHANGED_ACTION}
+ * instead.
*/
public static final String PROVIDERS_CHANGED_ACTION =
"android.location.PROVIDERS_CHANGED";
/**
* Broadcast intent action when {@link android.provider.Settings.Secure#LOCATION_MODE} changes.
- * If you're interacting with provider-based APIs such as {@link #getProviders(boolean)}, you
- * use {@link #PROVIDERS_CHANGED_ACTION} instead.
+ * For use with the {@link android.provider.Settings.Secure#LOCATION_MODE} API.
+ * If you're interacting with {@link #isProviderEnabled(String)}, use
+ * {@link #PROVIDERS_CHANGED_ACTION} instead.
*
* In the future, there may be mode changes that do not result in
* {@link #PROVIDERS_CHANGED_ACTION} broadcasts.
@@ -1098,8 +1099,13 @@ public class LocationManager {
* <p>If the user has enabled this provider in the Settings menu, true
* is returned otherwise false is returned
*
+ * <p>Callers should instead use
+ * {@link android.provider.Settings.Secure#LOCATION_MODE}
+ * unless they depend on provider-specific APIs such as
+ * {@link #requestLocationUpdates(String, long, float, LocationListener)}.
+ *
* @param provider the name of the provider
- * @return true if the provider is enabled
+ * @return true if the provider exists and is enabled
*
* @throws IllegalArgumentException if provider is null
* @throws SecurityException if no suitable permission is present
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 1dcf0e92b610..d1f71563295e 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -551,10 +551,10 @@ public class AudioManager {
IAudioService service = getService();
try {
if (mUseMasterVolume) {
- service.adjustMasterVolume(direction, flags, mContext.getBasePackageName());
+ service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
} else {
service.adjustStreamVolume(streamType, direction, flags,
- mContext.getBasePackageName());
+ mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustStreamVolume", e);
@@ -582,9 +582,9 @@ public class AudioManager {
IAudioService service = getService();
try {
if (mUseMasterVolume) {
- service.adjustMasterVolume(direction, flags, mContext.getBasePackageName());
+ service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
} else {
- service.adjustVolume(direction, flags, mContext.getBasePackageName());
+ service.adjustVolume(direction, flags, mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustVolume", e);
@@ -612,10 +612,10 @@ public class AudioManager {
IAudioService service = getService();
try {
if (mUseMasterVolume) {
- service.adjustMasterVolume(direction, flags, mContext.getBasePackageName());
+ service.adjustMasterVolume(direction, flags, mContext.getOpPackageName());
} else {
service.adjustSuggestedStreamVolume(direction, suggestedStreamType, flags,
- mContext.getBasePackageName());
+ mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustSuggestedStreamVolume", e);
@@ -634,7 +634,7 @@ public class AudioManager {
public void adjustMasterVolume(int steps, int flags) {
IAudioService service = getService();
try {
- service.adjustMasterVolume(steps, flags, mContext.getBasePackageName());
+ service.adjustMasterVolume(steps, flags, mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustMasterVolume", e);
}
@@ -786,9 +786,9 @@ public class AudioManager {
IAudioService service = getService();
try {
if (mUseMasterVolume) {
- service.setMasterVolume(index, flags, mContext.getBasePackageName());
+ service.setMasterVolume(index, flags, mContext.getOpPackageName());
} else {
- service.setStreamVolume(streamType, index, flags, mContext.getBasePackageName());
+ service.setStreamVolume(streamType, index, flags, mContext.getOpPackageName());
}
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setStreamVolume", e);
@@ -854,7 +854,7 @@ public class AudioManager {
public void setMasterVolume(int index, int flags) {
IAudioService service = getService();
try {
- service.setMasterVolume(index, flags, mContext.getBasePackageName());
+ service.setMasterVolume(index, flags, mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in setMasterVolume", e);
}
@@ -1569,7 +1569,7 @@ public class AudioManager {
IAudioService service = getService();
try {
service.adjustLocalOrRemoteStreamVolume(streamType, direction,
- mContext.getBasePackageName());
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Dead object in adjustLocalOrRemoteStreamVolume", e);
}
@@ -1996,7 +1996,7 @@ public class AudioManager {
try {
status = service.requestAudioFocus(streamType, durationHint, mICallBack,
mAudioFocusDispatcher, getIdForAudioFocusListener(l),
- mContext.getBasePackageName() /* package name */);
+ mContext.getOpPackageName() /* package name */);
} catch (RemoteException e) {
Log.e(TAG, "Can't call requestAudioFocus() on AudioService due to "+e);
}
@@ -2018,7 +2018,7 @@ public class AudioManager {
try {
service.requestAudioFocus(streamType, durationHint, mICallBack, null,
MediaFocusControl.IN_VOICE_COMM_FOCUS_ID,
- mContext.getBasePackageName());
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Can't call requestAudioFocusForCall() on AudioService due to "+e);
}
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 788257d5ba51..78a37c546979 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -746,31 +746,28 @@ public class AudioTrack
* If you need such features, consider implementing them at application level.
*
* @param timestamp a reference to a non-null AudioTimestamp instance allocated
- * and owned by caller, or null.
- * @return that same instance if timestamp parameter is non-null and a timestamp is available,
- * or a reference to a new AudioTimestamp instance which is now owned by caller
- * if timestamp parameter is null and a timestamp is available,
- * or null if no timestamp is available. In either successful case,
+ * and owned by caller.
+ * @return true if a timestamp is available, or false if no timestamp is available.
+ * If a timestamp if available,
* the AudioTimestamp instance is filled in with a position in frame units, together
* with the estimated time when that frame was presented or is committed to
* be presented.
* In the case that no timestamp is available, any supplied instance is left unaltered.
*/
- public AudioTimestamp getTimestamp(AudioTimestamp timestamp)
+ public boolean getTimestamp(AudioTimestamp timestamp)
{
+ if (timestamp == null) {
+ throw new IllegalArgumentException();
+ }
// It's unfortunate, but we have to either create garbage every time or use synchronized
long[] longArray = new long[2];
int ret = native_get_timestamp(longArray);
- if (ret == SUCCESS) {
- if (timestamp == null) {
- timestamp = new AudioTimestamp();
- }
- timestamp.framePosition = longArray[0];
- timestamp.nanoTime = longArray[1];
- } else {
- timestamp = null;
+ if (ret != SUCCESS) {
+ return false;
}
- return timestamp;
+ timestamp.framePosition = longArray[0];
+ timestamp.nanoTime = longArray[1];
+ return true;
}
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 949a42c07055..71af9ccb92d8 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -197,6 +197,28 @@ public final class MediaFormat {
*/
public static final String KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
+ /**
+ * A key for boolean AUTOSELECT field. Tracks with AUTOSELECT=true are
+ * considered when automatically selecting a track without specific user
+ * choice (as defined by HLS).
+ * @hide
+ */
+ public static final String KEY_AUTOSELECT = "autoselect";
+
+ /**
+ * A key for boolean DEFAULT field. The track with DEFAULT=true is selected
+ * in the absence of a specific user choice (as defined by HLS).
+ * @hide
+ */
+ public static final String KEY_DEFAULT = "default";
+
+ /**
+ * A key for boolean FORCED field for subtitle tracks. True if it is a
+ * forced subtitle track.
+ * @hide
+ */
+ public static final String KEY_FORCED = "forced";
+
/* package private */ MediaFormat(Map<String, Object> map) {
mMap = map;
}
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 774964e4b079..65a9308b70f5 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -92,6 +92,7 @@ final public class MediaMuxer {
Object[] values);
private static native void nativeSetOrientationHint(int nativeObject,
int degrees);
+ private static native void nativeSetLocation(int nativeObject, int latitude, int longitude);
private static native void nativeWriteSampleData(int nativeObject,
int trackIndex, ByteBuffer byteBuf,
int offset, int size, long presentationTimeUs, int flags);
@@ -165,6 +166,41 @@ final public class MediaMuxer {
}
/**
+ * Set and store the geodata (latitude and longitude) in the output file.
+ * This method should be called before {@link #start}. The geodata is stored
+ * in udta box if the output format is
+ * {@link OutputFormat#MUXER_OUTPUT_MPEG_4}, and is ignored for other output
+ * formats. The geodata is stored according to ISO-6709 standard.
+ *
+ * @param latitude Latitude in degrees. Its value must be in the range [-90,
+ * 90].
+ * @param longitude Longitude in degrees. Its value must be in the range
+ * [-180, 180].
+ * @throws IllegalArgumentException If the given latitude or longitude is out
+ * of range.
+ * @throws IllegalStateException If this method is called after {@link #start}.
+ */
+ public void setLocation(float latitude, float longitude) {
+ int latitudex10000 = (int) (latitude * 10000 + 0.5);
+ int longitudex10000 = (int) (longitude * 10000 + 0.5);
+
+ if (latitudex10000 > 900000 || latitudex10000 < -900000) {
+ String msg = "Latitude: " + latitude + " out of range.";
+ throw new IllegalArgumentException(msg);
+ }
+ if (longitudex10000 > 1800000 || longitudex10000 < -1800000) {
+ String msg = "Longitude: " + longitude + " out of range";
+ throw new IllegalArgumentException(msg);
+ }
+
+ if (mState == MUXER_STATE_INITIALIZED && mNativeObject != 0) {
+ nativeSetLocation(mNativeObject, latitudex10000, longitudex10000);
+ } else {
+ throw new IllegalStateException("Can't set location due to wrong state.");
+ }
+ }
+
+ /**
* Starts the muxer.
* <p>Make sure this is called after {@link #addTrack} and before
* {@link #writeSampleData}.</p>
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index ce1896a3b648..bcdc1c810325 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1578,7 +1578,8 @@ public class MediaPlayer implements SubtitleController.Listener
* unknown or could not be determined, null is returned.
*/
public MediaFormat getFormat() {
- if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
+ if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT
+ || mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
return mFormat;
}
return null;
@@ -1602,6 +1603,12 @@ public class MediaPlayer implements SubtitleController.Listener
if (mTrackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
mFormat = MediaFormat.createSubtitleFormat(
MEDIA_MIMETYPE_TEXT_SUBRIP, language);
+ } else if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
+ mFormat = MediaFormat.createSubtitleFormat(
+ MEDIA_MIMETYPE_TEXT_VTT, language);
+ mFormat.setInteger(MediaFormat.KEY_AUTOSELECT, in.readInt());
+ mFormat.setInteger(MediaFormat.KEY_DEFAULT, in.readInt());
+ mFormat.setInteger(MediaFormat.KEY_FORCED, in.readInt());
} else {
mFormat = new MediaFormat();
mFormat.setString(MediaFormat.KEY_LANGUAGE, language);
@@ -1629,6 +1636,12 @@ public class MediaPlayer implements SubtitleController.Listener
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(mTrackType);
dest.writeString(getLanguage());
+
+ if (mTrackType == MEDIA_TRACK_TYPE_SUBTITLE) {
+ dest.writeInt(mFormat.getInteger(MediaFormat.KEY_AUTOSELECT));
+ dest.writeInt(mFormat.getInteger(MediaFormat.KEY_DEFAULT));
+ dest.writeInt(mFormat.getInteger(MediaFormat.KEY_FORCED));
+ }
}
/**
@@ -1693,6 +1706,12 @@ public class MediaPlayer implements SubtitleController.Listener
*/
public static final String MEDIA_MIMETYPE_TEXT_SUBRIP = "application/x-subrip";
+ /**
+ * MIME type for WebVTT subtitle data.
+ * @hide
+ */
+ public static final String MEDIA_MIMETYPE_TEXT_VTT = "text/vtt";
+
/*
* A helper function to check if the mime type is supported by media framework.
*/
@@ -1829,9 +1848,8 @@ public class MediaPlayer implements SubtitleController.Listener
if (i < mInbandSubtitleTracks.length) {
inbandTracks[i] = mInbandSubtitleTracks[i];
} else {
- MediaFormat format = MediaFormat.createSubtitleFormat(
- "text/vtt", tracks[i].getLanguage());
- SubtitleTrack track = mSubtitleController.addTrack(format);
+ SubtitleTrack track = mSubtitleController.addTrack(
+ tracks[i].getFormat());
inbandTracks[i] = track;
}
}
diff --git a/media/java/android/media/SubtitleController.java b/media/java/android/media/SubtitleController.java
index 2cf1b2db71b5..e83c5bae99f3 100644
--- a/media/java/android/media/SubtitleController.java
+++ b/media/java/android/media/SubtitleController.java
@@ -20,8 +20,7 @@ import java.util.Locale;
import java.util.Vector;
import android.content.Context;
-import android.media.MediaPlayer.OnSubtitleDataListener;
-import android.view.View;
+import android.media.SubtitleTrack.RenderingWidget;
import android.view.accessibility.CaptioningManager;
/**
@@ -32,7 +31,6 @@ import android.view.accessibility.CaptioningManager;
* @hide
*/
public class SubtitleController {
- private Context mContext;
private MediaTimeProvider mTimeProvider;
private Vector<Renderer> mRenderers;
private Vector<SubtitleTrack> mTracks;
@@ -50,7 +48,6 @@ public class SubtitleController {
Context context,
MediaTimeProvider timeProvider,
Listener listener) {
- mContext = context;
mTimeProvider = timeProvider;
mListener = listener;
@@ -79,11 +76,11 @@ public class SubtitleController {
return mSelectedTrack;
}
- private View getSubtitleView() {
+ private RenderingWidget getRenderingWidget() {
if (mSelectedTrack == null) {
return null;
}
- return mSelectedTrack.getView();
+ return mSelectedTrack.getRenderingWidget();
}
/**
@@ -110,7 +107,7 @@ public class SubtitleController {
}
mSelectedTrack = track;
- mAnchor.setSubtitleView(getSubtitleView());
+ mAnchor.setSubtitleWidget(getRenderingWidget());
if (mSelectedTrack != null) {
mSelectedTrack.setTimeProvider(mTimeProvider);
@@ -268,17 +265,16 @@ public class SubtitleController {
}
/**
- * Subtitle anchor, an object that is able to display a subtitle view,
+ * Subtitle anchor, an object that is able to display a subtitle renderer,
* e.g. a VideoView.
*/
public interface Anchor {
/**
- * Anchor should set the subtitle view to the supplied view,
- * or none, if the supplied view is null.
- *
- * @param view subtitle view, or null
+ * Anchor should use the supplied subtitle rendering widget, or
+ * none if it is null.
+ * @hide
*/
- public void setSubtitleView(View view);
+ public void setSubtitleWidget(RenderingWidget subtitleWidget);
}
private Anchor mAnchor;
@@ -290,11 +286,11 @@ public class SubtitleController {
}
if (mAnchor != null) {
- mAnchor.setSubtitleView(null);
+ mAnchor.setSubtitleWidget(null);
}
mAnchor = anchor;
if (mAnchor != null) {
- mAnchor.setSubtitleView(getSubtitleView());
+ mAnchor.setSubtitleWidget(getRenderingWidget());
}
}
diff --git a/media/java/android/media/SubtitleTrack.java b/media/java/android/media/SubtitleTrack.java
index 09fb3f21ace3..cb689af7a43e 100644
--- a/media/java/android/media/SubtitleTrack.java
+++ b/media/java/android/media/SubtitleTrack.java
@@ -16,11 +16,11 @@
package android.media;
+import android.graphics.Canvas;
import android.os.Handler;
import android.util.Log;
import android.util.LongSparseArray;
import android.util.Pair;
-import android.view.View;
import java.util.Iterator;
import java.util.NoSuchElementException;
@@ -98,16 +98,16 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList
public abstract void onData(String data, boolean eos, long runID);
/**
- * Called when adding the subtitle rendering view to the view hierarchy, as
- * well as when showing or hiding the subtitle track, or when the video
+ * Called when adding the subtitle rendering widget to the view hierarchy,
+ * as well as when showing or hiding the subtitle track, or when the video
* surface position has changed.
*
- * @return the view object that displays this subtitle track. For most
- * renderers there should be a single shared view instance that is used
- * for all tracks supported by that renderer, as at most one subtitle
- * track is visible at one time.
+ * @return the widget that renders this subtitle track. For most renderers
+ * there should be a single shared instance that is used for all
+ * tracks supported by that renderer, as at most one subtitle track
+ * is visible at one time.
*/
- public abstract View getView();
+ public abstract RenderingWidget getRenderingWidget();
/**
* Called when the active cues have changed, and the contents of the subtitle
@@ -268,7 +268,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList
}
mVisible = true;
- getView().setVisibility(View.VISIBLE);
+ getRenderingWidget().setVisible(true);
if (mTimeProvider != null) {
mTimeProvider.scheduleUpdate(this);
}
@@ -283,7 +283,7 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList
if (mTimeProvider != null) {
mTimeProvider.cancelNotifications(this);
}
- getView().setVisibility(View.INVISIBLE);
+ getRenderingWidget().setVisible(false);
mVisible = false;
}
@@ -645,4 +645,61 @@ public abstract class SubtitleTrack implements MediaTimeProvider.OnMediaTimeList
}
}
}
+
+ /**
+ * Interface for rendering subtitles onto a Canvas.
+ */
+ public interface RenderingWidget {
+ /**
+ * Sets the widget's callback, which is used to send updates when the
+ * rendered data has changed.
+ *
+ * @param callback update callback
+ */
+ public void setOnChangedListener(OnChangedListener callback);
+
+ /**
+ * Sets the widget's size.
+ *
+ * @param width width in pixels
+ * @param height height in pixels
+ */
+ public void setSize(int width, int height);
+
+ /**
+ * Sets whether the widget should draw subtitles.
+ *
+ * @param visible true if subtitles should be drawn, false otherwise
+ */
+ public void setVisible(boolean visible);
+
+ /**
+ * Renders subtitles onto a {@link Canvas}.
+ *
+ * @param c canvas on which to render subtitles
+ */
+ public void draw(Canvas c);
+
+ /**
+ * Called when the widget is attached to a window.
+ */
+ public void onAttachedToWindow();
+
+ /**
+ * Called when the widget is detached from a window.
+ */
+ public void onDetachedFromWindow();
+
+ /**
+ * Callback used to send updates about changes to rendering data.
+ */
+ public interface OnChangedListener {
+ /**
+ * Called when the rendering data has changed.
+ *
+ * @param renderingWidget the widget whose data has changed
+ */
+ public void onChanged(RenderingWidget renderingWidget);
+ }
+ }
}
diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java
index 527c57f6401c..74773a8be437 100644
--- a/media/java/android/media/WebVttRenderer.java
+++ b/media/java/android/media/WebVttRenderer.java
@@ -1,12 +1,37 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
package android.media;
import android.content.Context;
+import android.text.SpannableStringBuilder;
+import android.util.ArrayMap;
import android.util.AttributeSet;
import android.util.Log;
+import android.view.Gravity;
import android.view.View;
-import android.view.ViewGroup.LayoutParams;
-import android.widget.TextView;
+import android.view.ViewGroup;
+import android.view.accessibility.CaptioningManager;
+import android.view.accessibility.CaptioningManager.CaptionStyle;
+import android.view.accessibility.CaptioningManager.CaptioningChangeListener;
+import android.widget.LinearLayout;
+
+import com.android.internal.widget.SubtitleView;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
@@ -14,10 +39,12 @@ import java.util.Vector;
/** @hide */
public class WebVttRenderer extends SubtitleController.Renderer {
- private TextView mMyTextView;
+ private final Context mContext;
- public WebVttRenderer(Context context, AttributeSet attrs) {
- mMyTextView = new WebVttView(context, attrs);
+ private WebVttRenderingWidget mRenderingWidget;
+
+ public WebVttRenderer(Context context) {
+ mContext = context;
}
@Override
@@ -30,19 +57,11 @@ public class WebVttRenderer extends SubtitleController.Renderer {
@Override
public SubtitleTrack createTrack(MediaFormat format) {
- return new WebVttTrack(format, mMyTextView);
- }
-}
+ if (mRenderingWidget == null) {
+ mRenderingWidget = new WebVttRenderingWidget(mContext);
+ }
-/** @hide */
-class WebVttView extends TextView {
- public WebVttView(Context context, AttributeSet attrs) {
- super(context, attrs);
- setTextColor(0xffffff00);
- setTextSize(46);
- setTextAlignment(TextView.TEXT_ALIGNMENT_CENTER);
- setLayoutParams(new LayoutParams(
- LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
+ return new WebVttTrack(mRenderingWidget, format);
}
}
@@ -954,26 +973,26 @@ interface WebVttCueListener {
class WebVttTrack extends SubtitleTrack implements WebVttCueListener {
private static final String TAG = "WebVttTrack";
- private final TextView mTextView;
-
private final WebVttParser mParser = new WebVttParser(this);
private final UnstyledTextExtractor mExtractor =
new UnstyledTextExtractor();
private final Tokenizer mTokenizer = new Tokenizer(mExtractor);
private final Vector<Long> mTimestamps = new Vector<Long>();
+ private final WebVttRenderingWidget mRenderingWidget;
private final Map<String, TextTrackRegion> mRegions =
new HashMap<String, TextTrackRegion>();
private Long mCurrentRunID;
- WebVttTrack(MediaFormat format, TextView textView) {
+ WebVttTrack(WebVttRenderingWidget renderingWidget, MediaFormat format) {
super(format);
- mTextView = textView;
+
+ mRenderingWidget = renderingWidget;
}
@Override
- public View getView() {
- return mTextView;
+ public WebVttRenderingWidget getRenderingWidget() {
+ return mRenderingWidget;
}
@Override
@@ -1051,6 +1070,7 @@ class WebVttTrack extends SubtitleTrack implements WebVttCueListener {
}
}
+ @Override
public void updateView(Vector<SubtitleTrack.Cue> activeCues) {
if (!mVisible) {
// don't keep the state if we are not visible
@@ -1066,29 +1086,737 @@ class WebVttTrack extends SubtitleTrack implements WebVttCueListener {
Log.d(TAG, "at (illegal state) the active cues are:");
}
}
- StringBuilder text = new StringBuilder();
- StringBuilder lineBuilder = new StringBuilder();
- for (Cue o: activeCues) {
- TextTrackCue cue = (TextTrackCue)o;
- if (DEBUG) Log.d(TAG, cue.toString());
- for (TextTrackCueSpan[] line: cue.mLines) {
- for (TextTrackCueSpan span: line) {
- if (!span.mEnabled) {
- continue;
- }
- lineBuilder.append(span.mText);
+
+ mRenderingWidget.setActiveCues(activeCues);
+ }
+}
+
+/**
+ * Widget capable of rendering WebVTT captions.
+ *
+ * @hide
+ */
+class WebVttRenderingWidget extends ViewGroup implements SubtitleTrack.RenderingWidget {
+ private static final boolean DEBUG = false;
+ private static final int DEBUG_REGION_BACKGROUND = 0x800000FF;
+ private static final int DEBUG_CUE_BACKGROUND = 0x80FF0000;
+
+ /** WebVtt specifies line height as 5.3% of the viewport height. */
+ private static final float LINE_HEIGHT_RATIO = 0.0533f;
+
+ /** Map of active regions, used to determine enter/exit. */
+ private final ArrayMap<TextTrackRegion, RegionLayout> mRegionBoxes =
+ new ArrayMap<TextTrackRegion, RegionLayout>();
+
+ /** Map of active cues, used to determine enter/exit. */
+ private final ArrayMap<TextTrackCue, CueLayout> mCueBoxes =
+ new ArrayMap<TextTrackCue, CueLayout>();
+
+ /** Captioning manager, used to obtain and track caption properties. */
+ private final CaptioningManager mManager;
+
+ /** Callback for rendering changes. */
+ private OnChangedListener mListener;
+
+ /** Current caption style. */
+ private CaptionStyle mCaptionStyle;
+
+ /** Current font size, computed from font scaling factor and height. */
+ private float mFontSize;
+
+ /** Whether a caption style change listener is registered. */
+ private boolean mHasChangeListener;
+
+ public WebVttRenderingWidget(Context context) {
+ this(context, null);
+ }
+
+ public WebVttRenderingWidget(Context context, AttributeSet attrs) {
+ this(context, null, 0);
+ }
+
+ public WebVttRenderingWidget(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+
+ // Cannot render text over video when layer type is hardware.
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+
+ mManager = (CaptioningManager) context.getSystemService(Context.CAPTIONING_SERVICE);
+ mCaptionStyle = mManager.getUserStyle();
+ mFontSize = mManager.getFontScale() * getHeight() * LINE_HEIGHT_RATIO;
+ }
+
+ @Override
+ public void setSize(int width, int height) {
+ final int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY);
+ final int heightSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
+
+ measure(widthSpec, heightSpec);
+ layout(0, 0, width, height);
+ }
+
+ @Override
+ public void onAttachedToWindow() {
+ super.onAttachedToWindow();
+
+ manageChangeListener();
+ }
+
+ @Override
+ public void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+
+ manageChangeListener();
+ }
+
+ @Override
+ public void setOnChangedListener(OnChangedListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void setVisible(boolean visible) {
+ if (visible) {
+ setVisibility(View.VISIBLE);
+ } else {
+ setVisibility(View.GONE);
+ }
+
+ manageChangeListener();
+ }
+
+ /**
+ * Manages whether this renderer is listening for caption style changes.
+ */
+ private void manageChangeListener() {
+ final boolean needsListener = isAttachedToWindow() && getVisibility() == View.VISIBLE;
+ if (mHasChangeListener != needsListener) {
+ mHasChangeListener = needsListener;
+
+ if (needsListener) {
+ mManager.addCaptioningChangeListener(mCaptioningListener);
+
+ final CaptionStyle captionStyle = mManager.getUserStyle();
+ final float fontSize = mManager.getFontScale() * getHeight() * LINE_HEIGHT_RATIO;
+ setCaptionStyle(captionStyle, fontSize);
+ } else {
+ mManager.removeCaptioningChangeListener(mCaptioningListener);
+ }
+ }
+ }
+
+ public void setActiveCues(Vector<SubtitleTrack.Cue> activeCues) {
+ final Context context = getContext();
+ final CaptionStyle captionStyle = mCaptionStyle;
+ final float fontSize = mFontSize;
+
+ prepForPrune();
+
+ // Ensure we have all necessary cue and region boxes.
+ final int count = activeCues.size();
+ for (int i = 0; i < count; i++) {
+ final TextTrackCue cue = (TextTrackCue) activeCues.get(i);
+ final TextTrackRegion region = cue.mRegion;
+ if (region != null) {
+ RegionLayout regionBox = mRegionBoxes.get(region);
+ if (regionBox == null) {
+ regionBox = new RegionLayout(context, region, captionStyle, fontSize);
+ mRegionBoxes.put(region, regionBox);
+ addView(regionBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
- if (lineBuilder.length() > 0) {
- text.append(lineBuilder.toString()).append("\n");
- lineBuilder.delete(0, lineBuilder.length());
+ regionBox.put(cue);
+ } else {
+ CueLayout cueBox = mCueBoxes.get(cue);
+ if (cueBox == null) {
+ cueBox = new CueLayout(context, cue, captionStyle, fontSize);
+ mCueBoxes.put(cue, cueBox);
+ addView(cueBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
+ cueBox.update();
+ cueBox.setOrder(i);
+ }
+ }
+
+ prune();
+
+ // Force measurement and layout.
+ final int width = getWidth();
+ final int height = getHeight();
+ setSize(width, height);
+
+ if (mListener != null) {
+ mListener.onChanged(this);
+ }
+ }
+
+ private void setCaptionStyle(CaptionStyle captionStyle, float fontSize) {
+ mCaptionStyle = captionStyle;
+ mFontSize = fontSize;
+
+ final int cueCount = mCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mCueBoxes.valueAt(i);
+ cueBox.setCaptionStyle(captionStyle, fontSize);
+ }
+
+ final int regionCount = mRegionBoxes.size();
+ for (int i = 0; i < regionCount; i++) {
+ final RegionLayout regionBox = mRegionBoxes.valueAt(i);
+ regionBox.setCaptionStyle(captionStyle, fontSize);
+ }
+ }
+
+ /**
+ * Remove inactive cues and regions.
+ */
+ private void prune() {
+ int regionCount = mRegionBoxes.size();
+ for (int i = 0; i < regionCount; i++) {
+ final RegionLayout regionBox = mRegionBoxes.valueAt(i);
+ if (regionBox.prune()) {
+ removeView(regionBox);
+ mRegionBoxes.removeAt(i);
+ regionCount--;
+ i--;
}
}
- if (mTextView != null) {
- if (DEBUG) Log.d(TAG, "updating to " + text.toString());
- mTextView.setText(text.toString());
- mTextView.postInvalidate();
+ int cueCount = mCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mCueBoxes.valueAt(i);
+ if (!cueBox.isActive()) {
+ removeView(cueBox);
+ mCueBoxes.removeAt(i);
+ cueCount--;
+ i--;
+ }
+ }
+ }
+
+ /**
+ * Reset active cues and regions.
+ */
+ private void prepForPrune() {
+ final int regionCount = mRegionBoxes.size();
+ for (int i = 0; i < regionCount; i++) {
+ final RegionLayout regionBox = mRegionBoxes.valueAt(i);
+ regionBox.prepForPrune();
+ }
+
+ final int cueCount = mCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mCueBoxes.valueAt(i);
+ cueBox.prepForPrune();
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ final int regionCount = mRegionBoxes.size();
+ for (int i = 0; i < regionCount; i++) {
+ final RegionLayout regionBox = mRegionBoxes.valueAt(i);
+ regionBox.measureForParent(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ final int cueCount = mCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mCueBoxes.valueAt(i);
+ cueBox.measureForParent(widthMeasureSpec, heightMeasureSpec);
+ }
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
+ final int viewportWidth = r - l;
+ final int viewportHeight = b - t;
+
+ setCaptionStyle(mCaptionStyle,
+ mManager.getFontScale() * LINE_HEIGHT_RATIO * viewportHeight);
+
+ final int regionCount = mRegionBoxes.size();
+ for (int i = 0; i < regionCount; i++) {
+ final RegionLayout regionBox = mRegionBoxes.valueAt(i);
+ layoutRegion(viewportWidth, viewportHeight, regionBox);
+ }
+
+ final int cueCount = mCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mCueBoxes.valueAt(i);
+ layoutCue(viewportWidth, viewportHeight, cueBox);
+ }
+ }
+
+ /**
+ * Lays out a region within the viewport. The region handles layout for
+ * contained cues.
+ */
+ private void layoutRegion(
+ int viewportWidth, int viewportHeight,
+ RegionLayout regionBox) {
+ final TextTrackRegion region = regionBox.getRegion();
+ final int regionHeight = regionBox.getMeasuredHeight();
+ final int regionWidth = regionBox.getMeasuredWidth();
+
+ // TODO: Account for region anchor point.
+ final float x = region.mViewportAnchorPointX;
+ final float y = region.mViewportAnchorPointY;
+ final int left = (int) (x * (viewportWidth - regionWidth) / 100);
+ final int top = (int) (y * (viewportHeight - regionHeight) / 100);
+
+ regionBox.layout(left, top, left + regionWidth, top + regionHeight);
+ }
+
+ /**
+ * Lays out a cue within the viewport.
+ */
+ private void layoutCue(
+ int viewportWidth, int viewportHeight, CueLayout cueBox) {
+ final TextTrackCue cue = cueBox.getCue();
+ final int direction = getLayoutDirection();
+ final int absAlignment = resolveCueAlignment(direction, cue.mAlignment);
+ final boolean cueSnapToLines = cue.mSnapToLines;
+
+ int size = 100 * cueBox.getMeasuredWidth() / viewportWidth;
+
+ // Determine raw x-position.
+ int xPosition;
+ switch (absAlignment) {
+ case TextTrackCue.ALIGNMENT_LEFT:
+ xPosition = cue.mTextPosition;
+ break;
+ case TextTrackCue.ALIGNMENT_RIGHT:
+ xPosition = cue.mTextPosition - size;
+ break;
+ case TextTrackCue.ALIGNMENT_MIDDLE:
+ default:
+ xPosition = cue.mTextPosition - size / 2;
+ break;
+ }
+
+ // Adjust x-position for layout.
+ if (direction == LAYOUT_DIRECTION_RTL) {
+ xPosition = 100 - xPosition;
+ }
+
+ // If the text track cue snap-to-lines flag is set, adjust
+ // x-position and size for padding. This is equivalent to placing the
+ // cue within the title-safe area.
+ if (cueSnapToLines) {
+ final int paddingLeft = 100 * getPaddingLeft() / viewportWidth;
+ final int paddingRight = 100 * getPaddingRight() / viewportWidth;
+ if (xPosition < paddingLeft && xPosition + size > paddingLeft) {
+ xPosition += paddingLeft;
+ size -= paddingLeft;
+ }
+ final float rightEdge = 100 - paddingRight;
+ if (xPosition < rightEdge && xPosition + size > rightEdge) {
+ size -= paddingRight;
+ }
+ }
+
+ // Compute absolute left position and width.
+ final int left = xPosition * viewportWidth / 100;
+ final int width = size * viewportWidth / 100;
+
+ // Determine initial y-position.
+ final int yPosition = calculateLinePosition(cueBox);
+
+ // Compute absolute final top position and height.
+ final int height = cueBox.getMeasuredHeight();
+ final int top;
+ if (yPosition < 0) {
+ // TODO: This needs to use the actual height of prior boxes.
+ top = viewportHeight + yPosition * height;
+ } else {
+ top = yPosition * (viewportHeight - height) / 100;
+ }
+
+ // Layout cue in final position.
+ cueBox.layout(left, top, left + width, top + height);
+ }
+
+ /**
+ * Calculates the line position for a cue.
+ * <p>
+ * If the resulting position is negative, it represents a bottom-aligned
+ * position relative to the number of active cues. Otherwise, it represents
+ * a percentage [0-100] of the viewport height.
+ */
+ private int calculateLinePosition(CueLayout cueBox) {
+ final TextTrackCue cue = cueBox.getCue();
+ final Integer linePosition = cue.mLinePosition;
+ final boolean snapToLines = cue.mSnapToLines;
+ final boolean autoPosition = (linePosition == null);
+
+ if (!snapToLines && !autoPosition && (linePosition < 0 || linePosition > 100)) {
+ // Invalid line position defaults to 100.
+ return 100;
+ } else if (!autoPosition) {
+ // Use the valid, supplied line position.
+ return linePosition;
+ } else if (!snapToLines) {
+ // Automatic, non-snapped line position defaults to 100.
+ return 100;
+ } else {
+ // Automatic snapped line position uses active cue order.
+ return -(cueBox.mOrder + 1);
+ }
+ }
+
+ /**
+ * Resolves cue alignment according to the specified layout direction.
+ */
+ private static int resolveCueAlignment(int layoutDirection, int alignment) {
+ switch (alignment) {
+ case TextTrackCue.ALIGNMENT_START:
+ return layoutDirection == View.LAYOUT_DIRECTION_LTR ?
+ TextTrackCue.ALIGNMENT_LEFT : TextTrackCue.ALIGNMENT_RIGHT;
+ case TextTrackCue.ALIGNMENT_END:
+ return layoutDirection == View.LAYOUT_DIRECTION_LTR ?
+ TextTrackCue.ALIGNMENT_RIGHT : TextTrackCue.ALIGNMENT_LEFT;
+ }
+ return alignment;
+ }
+
+ private final CaptioningChangeListener mCaptioningListener = new CaptioningChangeListener() {
+ @Override
+ public void onFontScaleChanged(float fontScale) {
+ final float fontSize = fontScale * getHeight() * LINE_HEIGHT_RATIO;
+ setCaptionStyle(mCaptionStyle, fontSize);
+ }
+
+ @Override
+ public void onUserStyleChanged(CaptionStyle userStyle) {
+ setCaptionStyle(userStyle, mFontSize);
+ }
+ };
+
+ /**
+ * A text track region represents a portion of the video viewport and
+ * provides a rendering area for text track cues.
+ */
+ private static class RegionLayout extends LinearLayout {
+ private final ArrayList<CueLayout> mRegionCueBoxes = new ArrayList<CueLayout>();
+ private final TextTrackRegion mRegion;
+
+ private CaptionStyle mCaptionStyle;
+ private float mFontSize;
+
+ public RegionLayout(Context context, TextTrackRegion region, CaptionStyle captionStyle,
+ float fontSize) {
+ super(context);
+
+ mRegion = region;
+ mCaptionStyle = captionStyle;
+ mFontSize = fontSize;
+
+ // TODO: Add support for vertical text
+ setOrientation(VERTICAL);
+
+ if (DEBUG) {
+ setBackgroundColor(DEBUG_REGION_BACKGROUND);
+ }
+ }
+
+ public void setCaptionStyle(CaptionStyle captionStyle, float fontSize) {
+ mCaptionStyle = captionStyle;
+ mFontSize = fontSize;
+
+ final int cueCount = mRegionCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mRegionCueBoxes.get(i);
+ cueBox.setCaptionStyle(captionStyle, fontSize);
+ }
+ }
+
+ /**
+ * Performs the parent's measurement responsibilities, then
+ * automatically performs its own measurement.
+ */
+ public void measureForParent(int widthMeasureSpec, int heightMeasureSpec) {
+ final TextTrackRegion region = mRegion;
+ final int specWidth = MeasureSpec.getSize(widthMeasureSpec);
+ final int specHeight = MeasureSpec.getSize(heightMeasureSpec);
+ final int width = (int) region.mWidth;
+
+ // Determine the absolute maximum region size as the requested size.
+ final int size = width * specWidth / 100;
+
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(specHeight, MeasureSpec.AT_MOST);
+ measure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ /**
+ * Prepares this region for pruning by setting all tracks as inactive.
+ * <p>
+ * Tracks that are added or updated using {@link #put(TextTrackCue)}
+ * after this calling this method will be marked as active.
+ */
+ public void prepForPrune() {
+ final int cueCount = mRegionCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mRegionCueBoxes.get(i);
+ cueBox.prepForPrune();
+ }
+ }
+
+ /**
+ * Adds a {@link TextTrackCue} to this region. If the track had already
+ * been added, updates its active state.
+ *
+ * @param cue
+ */
+ public void put(TextTrackCue cue) {
+ final int cueCount = mRegionCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mRegionCueBoxes.get(i);
+ if (cueBox.getCue() == cue) {
+ cueBox.update();
+ return;
+ }
+ }
+
+ final CueLayout cueBox = new CueLayout(getContext(), cue, mCaptionStyle, mFontSize);
+ addView(cueBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+
+ if (getChildCount() > mRegion.mLines) {
+ removeViewAt(0);
+ }
+ }
+
+ /**
+ * Remove all inactive tracks from this region.
+ *
+ * @return true if this region is empty and should be pruned
+ */
+ public boolean prune() {
+ int cueCount = mRegionCueBoxes.size();
+ for (int i = 0; i < cueCount; i++) {
+ final CueLayout cueBox = mRegionCueBoxes.get(i);
+ if (!cueBox.isActive()) {
+ mRegionCueBoxes.remove(i);
+ removeView(cueBox);
+ cueCount--;
+ i--;
+ }
+ }
+
+ return mRegionCueBoxes.isEmpty();
+ }
+
+ /**
+ * @return the region data backing this layout
+ */
+ public TextTrackRegion getRegion() {
+ return mRegion;
+ }
+ }
+
+ /**
+ * A text track cue is the unit of time-sensitive data in a text track,
+ * corresponding for instance for subtitles and captions to the text that
+ * appears at a particular time and disappears at another time.
+ * <p>
+ * A single cue may contain multiple {@link SpanLayout}s, each representing a
+ * single line of text.
+ */
+ private static class CueLayout extends LinearLayout {
+ public final TextTrackCue mCue;
+
+ private CaptionStyle mCaptionStyle;
+ private float mFontSize;
+
+ private boolean mActive;
+ private int mOrder;
+
+ public CueLayout(
+ Context context, TextTrackCue cue, CaptionStyle captionStyle, float fontSize) {
+ super(context);
+
+ mCue = cue;
+ mCaptionStyle = captionStyle;
+ mFontSize = fontSize;
+
+ // TODO: Add support for vertical text.
+ final boolean horizontal = cue.mWritingDirection
+ == TextTrackCue.WRITING_DIRECTION_HORIZONTAL;
+ setOrientation(horizontal ? VERTICAL : HORIZONTAL);
+
+ switch (cue.mAlignment) {
+ case TextTrackCue.ALIGNMENT_END:
+ setGravity(Gravity.END);
+ break;
+ case TextTrackCue.ALIGNMENT_LEFT:
+ setGravity(Gravity.LEFT);
+ break;
+ case TextTrackCue.ALIGNMENT_MIDDLE:
+ setGravity(horizontal
+ ? Gravity.CENTER_HORIZONTAL : Gravity.CENTER_VERTICAL);
+ break;
+ case TextTrackCue.ALIGNMENT_RIGHT:
+ setGravity(Gravity.RIGHT);
+ break;
+ case TextTrackCue.ALIGNMENT_START:
+ setGravity(Gravity.START);
+ break;
+ }
+
+ if (DEBUG) {
+ setBackgroundColor(DEBUG_CUE_BACKGROUND);
+ }
+
+ update();
+ }
+
+ public void setCaptionStyle(CaptionStyle style, float fontSize) {
+ mCaptionStyle = style;
+ mFontSize = fontSize;
+
+ final int n = getChildCount();
+ for (int i = 0; i < n; i++) {
+ final View child = getChildAt(i);
+ if (child instanceof SpanLayout) {
+ ((SpanLayout) child).setCaptionStyle(style, fontSize);
+ }
+ }
+ }
+
+ public void prepForPrune() {
+ mActive = false;
+ }
+
+ public void update() {
+ mActive = true;
+
+ removeAllViews();
+
+ final CaptionStyle captionStyle = mCaptionStyle;
+ final float fontSize = mFontSize;
+ final TextTrackCueSpan[][] lines = mCue.mLines;
+ final int lineCount = lines.length;
+ for (int i = 0; i < lineCount; i++) {
+ final SpanLayout lineBox = new SpanLayout(getContext(), lines[i]);
+ lineBox.setCaptionStyle(captionStyle, fontSize);
+
+ addView(lineBox, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ }
+ }
+
+ @Override
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ /**
+ * Performs the parent's measurement responsibilities, then
+ * automatically performs its own measurement.
+ */
+ public void measureForParent(int widthMeasureSpec, int heightMeasureSpec) {
+ final TextTrackCue cue = mCue;
+ final int specWidth = MeasureSpec.getSize(widthMeasureSpec);
+ final int specHeight = MeasureSpec.getSize(heightMeasureSpec);
+ final int direction = getLayoutDirection();
+ final int absAlignment = resolveCueAlignment(direction, cue.mAlignment);
+
+ // Determine the maximum size of cue based on its starting position
+ // and the direction in which it grows.
+ final int maximumSize;
+ switch (absAlignment) {
+ case TextTrackCue.ALIGNMENT_LEFT:
+ maximumSize = 100 - cue.mTextPosition;
+ break;
+ case TextTrackCue.ALIGNMENT_RIGHT:
+ maximumSize = cue.mTextPosition;
+ break;
+ case TextTrackCue.ALIGNMENT_MIDDLE:
+ if (cue.mTextPosition <= 50) {
+ maximumSize = cue.mTextPosition * 2;
+ } else {
+ maximumSize = (100 - cue.mTextPosition) * 2;
+ }
+ break;
+ default:
+ maximumSize = 0;
+ }
+
+ // Determine absolute maximum cue size as the smaller of the
+ // requested size and the maximum theoretical size.
+ final int size = Math.min(cue.mSize, maximumSize) * specWidth / 100;
+ widthMeasureSpec = MeasureSpec.makeMeasureSpec(size, MeasureSpec.AT_MOST);
+ heightMeasureSpec = MeasureSpec.makeMeasureSpec(specHeight, MeasureSpec.AT_MOST);
+ measure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ /**
+ * Sets the order of this cue in the list of active cues.
+ *
+ * @param order the order of this cue in the list of active cues
+ */
+ public void setOrder(int order) {
+ mOrder = order;
+ }
+
+ /**
+ * @return whether this cue is marked as active
+ */
+ public boolean isActive() {
+ return mActive;
+ }
+
+ /**
+ * @return the cue data backing this layout
+ */
+ public TextTrackCue getCue() {
+ return mCue;
+ }
+ }
+
+ /**
+ * A text track line represents a single line of text within a cue.
+ * <p>
+ * A single line may contain multiple spans, each representing a section of
+ * text that may be enabled or disabled at a particular time.
+ */
+ private static class SpanLayout extends SubtitleView {
+ private final SpannableStringBuilder mBuilder = new SpannableStringBuilder();
+ private final TextTrackCueSpan[] mSpans;
+
+ public SpanLayout(Context context, TextTrackCueSpan[] spans) {
+ super(context);
+
+ mSpans = spans;
+
+ update();
+ }
+
+ public void update() {
+ final SpannableStringBuilder builder = mBuilder;
+ final TextTrackCueSpan[] spans = mSpans;
+
+ builder.clear();
+ builder.clearSpans();
+
+ final int spanCount = spans.length;
+ for (int i = 0; i < spanCount; i++) {
+ final TextTrackCueSpan span = spans[i];
+ if (span.mEnabled) {
+ builder.append(spans[i].mText);
+ }
+ }
+
+ setText(builder);
+ }
+
+ public void setCaptionStyle(CaptionStyle captionStyle, float fontSize) {
+ setBackgroundColor(captionStyle.backgroundColor);
+ setForegroundColor(captionStyle.foregroundColor);
+ setEdgeColor(captionStyle.edgeColor);
+ setEdgeType(captionStyle.edgeType);
+ setTypeface(captionStyle.getTypeface());
+ setTextSize(fontSize);
}
}
}
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 92edb8ab774c..94f20bcb3171 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -738,7 +738,7 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
int outputWidth = buffer->width;
int outputHeight = buffer->height;
- // Correct with/height when crop is set.
+ // Correct width/height when crop is set.
if (buffer->crop.getWidth() > 0) {
outputWidth = buffer->crop.getWidth() + 1;
}
@@ -748,12 +748,19 @@ static jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
int imageReaderWidth = ctx->getBufferWidth();
int imageReaderHeight = ctx->getBufferHeight();
- if (imageReaderWidth != outputWidth
- || imageReaderHeight != outputHeight) {
- // Spew warning for now, since MediaCodec decoder has a bug to setup the right crop
- // TODO: make it throw exception once the decoder bug is fixed.
- ALOGW("Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
- outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
+ if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) &&
+ (imageReaderWidth != outputWidth || imageReaderHeight > outputHeight)) {
+ /**
+ * For video decoder, the buffer height is actually the vertical stride,
+ * which is always >= actual image height. For future, decoder need provide
+ * right crop rectangle to CpuConsumer to indicate the actual image height,
+ * see bug 9563986. After this bug is fixed, we can enforce the height equal
+ * check. Right now, only make sure buffer height is no less than ImageReader
+ * height.
+ */
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
+ outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
}
if (ctx->getBufferFormat() != buffer->format) {
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index 7517e8561a20..457b956e3745 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -164,6 +164,18 @@ static void android_media_MediaMuxer_setOrientationHint(
}
+static void android_media_MediaMuxer_setLocation(
+ JNIEnv *env, jclass clazz, jint nativeObject, jint latitude, jint longitude) {
+ MediaMuxer* muxer = reinterpret_cast<MediaMuxer *>(nativeObject);
+
+ status_t res = muxer->setLocation(latitude, longitude);
+ if (res != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to set location");
+ return;
+ }
+}
+
static void android_media_MediaMuxer_start(JNIEnv *env, jclass clazz,
jint nativeObject) {
sp<MediaMuxer> muxer(reinterpret_cast<MediaMuxer *>(nativeObject));
@@ -216,6 +228,9 @@ static JNINativeMethod gMethods[] = {
{ "nativeSetOrientationHint", "(II)V",
(void *)android_media_MediaMuxer_setOrientationHint},
+ { "nativeSetLocation", "(III)V",
+ (void *)android_media_MediaMuxer_setLocation},
+
{ "nativeStart", "(I)V", (void *)android_media_MediaMuxer_start},
{ "nativeWriteSampleData", "(IILjava/nio/ByteBuffer;IIJI)V",
diff --git a/packages/DocumentsUI/res/drawable/item_background.xml b/packages/DocumentsUI/res/drawable/item_background.xml
index 4fb32fc90c15..7447aa8c0527 100644
--- a/packages/DocumentsUI/res/drawable/item_background.xml
+++ b/packages/DocumentsUI/res/drawable/item_background.xml
@@ -15,12 +15,20 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_activated="true" android:state_pressed="true" android:drawable="@*android:drawable/list_activated_holo" />
- <item android:state_activated="true" android:drawable="@*android:drawable/list_activated_holo" />
- <item android:state_focused="true" android:state_enabled="false" android:state_pressed="true" android:drawable="@*android:drawable/list_selector_disabled_holo_light" />
- <item android:state_focused="true" android:state_enabled="false" android:drawable="@*android:drawable/list_selector_disabled_holo_light" />
- <item android:state_focused="true" android:state_pressed="true" android:drawable="@*android:drawable/list_selector_background_transition_holo_light" />
- <item android:state_focused="false" android:state_pressed="true" android:drawable="@*android:drawable/list_selector_background_transition_holo_light" />
- <item android:state_focused="true" android:drawable="@*android:drawable/list_focused_holo" />
- <item android:drawable="@android:color/transparent" />
+
+ <item android:state_enabled="false" android:state_selected="true" android:drawable="@*android:drawable/list_selector_disabled_holo_light" />
+ <item android:state_enabled="false" android:state_focused="true" android:drawable="@*android:drawable/list_selector_disabled_holo_light" />
+ <item android:state_enabled="false" android:state_pressed="true" android:drawable="@*android:drawable/list_selector_disabled_holo_light" />
+
+ <item android:state_activated="true" android:state_pressed="true" android:drawable="@*android:drawable/list_activated_holo" />
+ <item android:state_activated="true" android:drawable="@*android:drawable/list_activated_holo" />
+
+ <item android:state_focused="true" android:drawable="@*android:drawable/list_focused_holo" />
+ <item android:state_selected="true" android:drawable="@*android:drawable/list_focused_holo" />
+
+ <item android:state_pressed="true" android:state_focused="true" android:drawable="@*android:drawable/list_selector_background_transition_holo_light" />
+ <item android:state_pressed="true" android:drawable="@*android:drawable/list_selector_background_transition_holo_light" />
+
+ <item android:drawable="@android:color/transparent" />
+
</selector>
diff --git a/packages/DocumentsUI/res/layout/fragment_directory.xml b/packages/DocumentsUI/res/layout/fragment_directory.xml
index 881349bf9eea..b4138a5db57a 100644
--- a/packages/DocumentsUI/res/layout/fragment_directory.xml
+++ b/packages/DocumentsUI/res/layout/fragment_directory.xml
@@ -24,8 +24,8 @@
android:layout_height="match_parent"
android:gravity="center"
android:text="@string/empty"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:visibility="gone" />
+ android:visibility="gone"
+ style="@style/TextAppearance.Medium" />
<ListView
android:id="@+id/list"
@@ -40,12 +40,4 @@
android:listSelector="@android:color/transparent"
android:visibility="gone" />
- <Button
- android:id="@+id/more"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="bottom"
- android:text="@string/more"
- android:visibility="gone" />
-
</FrameLayout>
diff --git a/packages/DocumentsUI/res/layout/item_doc_grid.xml b/packages/DocumentsUI/res/layout/item_doc_grid.xml
index 8d1fc9aa34fd..eea90b5ce94f 100644
--- a/packages/DocumentsUI/res/layout/item_doc_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_grid.xml
@@ -32,12 +32,26 @@
android:layout_weight="1"
android:background="#fff">
- <ImageView
+ <FrameLayout
android:id="@android:id/icon"
android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:scaleType="centerInside"
- android:contentDescription="@null" />
+ android:layout_height="match_parent">
+
+ <ImageView
+ android:id="@+id/icon_mime"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:contentDescription="@null" />
+
+ <ImageView
+ android:id="@+id/icon_thumb"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:contentDescription="@null" />
+
+ </FrameLayout>
<ImageView
android:layout_width="match_parent"
@@ -63,8 +77,8 @@
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textAlignment="viewStart" />
+ android:textAlignment="viewStart"
+ style="@style/TextAppearance.Medium" />
<ImageView
android:id="@android:id/icon1"
@@ -93,7 +107,7 @@
android:singleLine="true"
android:ellipsize="marquee"
android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ style="@style/TextAppearance.Small" />
<TextView
android:id="@+id/size"
@@ -105,7 +119,7 @@
android:singleLine="true"
android:ellipsize="marquee"
android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ style="@style/TextAppearance.Small" />
<TextView
android:id="@android:id/summary"
@@ -117,7 +131,7 @@
android:singleLine="true"
android:ellipsize="marquee"
android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ style="@style/TextAppearance.Small" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_doc_list.xml b/packages/DocumentsUI/res/layout/item_doc_list.xml
index 8372eedb56d7..84fda9d36ad3 100644
--- a/packages/DocumentsUI/res/layout/item_doc_list.xml
+++ b/packages/DocumentsUI/res/layout/item_doc_list.xml
@@ -25,15 +25,29 @@
android:paddingBottom="8dip"
android:orientation="horizontal">
- <ImageView
+ <FrameLayout
android:id="@android:id/icon"
android:layout_width="@dimen/icon_size"
android:layout_height="@dimen/icon_size"
android:layout_marginStart="12dp"
android:layout_marginEnd="20dp"
- android:layout_gravity="center_vertical"
- android:scaleType="centerInside"
- android:contentDescription="@null" />
+ android:layout_gravity="center_vertical">
+
+ <ImageView
+ android:id="@+id/icon_mime"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerInside"
+ android:contentDescription="@null" />
+
+ <ImageView
+ android:id="@+id/icon_thumb"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:scaleType="centerCrop"
+ android:contentDescription="@null" />
+
+ </FrameLayout>
<LinearLayout
android:layout_width="0dip"
@@ -54,8 +68,8 @@
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textAlignment="viewStart" />
+ android:textAlignment="viewStart"
+ style="@style/TextAppearance.Medium" />
<ImageView
android:id="@android:id/icon1"
@@ -82,7 +96,7 @@
android:singleLine="true"
android:ellipsize="marquee"
android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ style="@style/TextAppearance.Small" />
<TextView
android:id="@+id/size"
@@ -94,7 +108,7 @@
android:singleLine="true"
android:ellipsize="marquee"
android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ style="@style/TextAppearance.Small" />
<TextView
android:id="@android:id/summary"
@@ -106,7 +120,7 @@
android:singleLine="true"
android:ellipsize="marquee"
android:textAlignment="viewStart"
- android:textAppearance="?android:attr/textAppearanceSmall" />
+ style="@style/TextAppearance.Small" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_loading_grid.xml b/packages/DocumentsUI/res/layout/item_loading_grid.xml
new file mode 100644
index 000000000000..21be13744753
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/item_loading_grid.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 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.
+-->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/grid_height"
+ android:minHeight="?android:attr/listPreferredItemHeight"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
+ android:paddingTop="8dip"
+ android:paddingBottom="8dip"
+ android:orientation="horizontal">
+
+ <ProgressBar
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:indeterminate="true"
+ style="?android:attr/progressBarStyle" />
+
+</FrameLayout>
diff --git a/packages/DocumentsUI/res/layout/item_loading.xml b/packages/DocumentsUI/res/layout/item_loading_list.xml
index 7da71e3cb4f6..7da71e3cb4f6 100644
--- a/packages/DocumentsUI/res/layout/item_loading.xml
+++ b/packages/DocumentsUI/res/layout/item_loading_list.xml
diff --git a/packages/DocumentsUI/res/layout/item_message_grid.xml b/packages/DocumentsUI/res/layout/item_message_grid.xml
index 941340e9d720..b3bdd28c9598 100644
--- a/packages/DocumentsUI/res/layout/item_message_grid.xml
+++ b/packages/DocumentsUI/res/layout/item_message_grid.xml
@@ -16,44 +16,36 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
- android:layout_height="180dip"
+ android:layout_height="@dimen/grid_height"
+ android:paddingTop="?android:attr/listPreferredItemPaddingStart"
+ android:paddingStart="?android:attr/listPreferredItemPaddingStart"
+ android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="?android:attr/listPreferredItemPaddingEnd"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+ android:foreground="@drawable/item_background">
- <FrameLayout
+ <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="@color/chip"
- android:foreground="@drawable/item_background"
- android:duplicateParentState="true">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:paddingBottom="6dp"
- android:orientation="vertical"
- android:gravity="center">
-
- <ImageView
- android:id="@android:id/icon"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:contentDescription="@null" />
-
- <TextView
- android:id="@android:id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:paddingTop="6dp"
- android:paddingStart="?android:attr/listPreferredItemPaddingStart"
- android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textAlignment="viewStart" />
-
- </LinearLayout>
-
- </FrameLayout>
+ android:orientation="vertical"
+ android:gravity="center">
+
+ <ImageView
+ android:id="@android:id/icon"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:contentDescription="@null" />
+
+ <TextView
+ android:id="@android:id/title"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:maxLines="4"
+ android:ellipsize="end"
+ android:paddingTop="6dp"
+ android:textAppearance="?android:attr/textAppearanceSmall"
+ android:textAlignment="viewStart" />
+
+ </LinearLayout>
</FrameLayout>
diff --git a/packages/DocumentsUI/res/layout/item_message_list.xml b/packages/DocumentsUI/res/layout/item_message_list.xml
index dda3c80f2baa..ffda98c1205f 100644
--- a/packages/DocumentsUI/res/layout/item_message_list.xml
+++ b/packages/DocumentsUI/res/layout/item_message_list.xml
@@ -39,9 +39,9 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textAlignment="viewStart" />
+ android:maxLines="2"
+ android:ellipsize="end"
+ android:textAlignment="viewStart"
+ android:textAppearance="?android:attr/textAppearanceSmall" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_root.xml b/packages/DocumentsUI/res/layout/item_root.xml
index ce97b5710427..98d78dac545f 100644
--- a/packages/DocumentsUI/res/layout/item_root.xml
+++ b/packages/DocumentsUI/res/layout/item_root.xml
@@ -43,8 +43,8 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textAlignment="viewStart" />
+ android:textAlignment="viewStart"
+ style="@style/TextAppearance.Medium" />
<TextView
android:id="@android:id/summary"
@@ -52,8 +52,8 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceSmall"
- android:textAlignment="viewStart" />
+ android:textAlignment="viewStart"
+ style="@style/TextAppearance.Small" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/layout/item_root_header.xml b/packages/DocumentsUI/res/layout/item_root_header.xml
index 127b2544abbf..6b9857d77fe0 100644
--- a/packages/DocumentsUI/res/layout/item_root_header.xml
+++ b/packages/DocumentsUI/res/layout/item_root_header.xml
@@ -14,6 +14,14 @@
limitations under the License.
-->
-<TextView xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@android:id/title"
- style="?android:attr/listSeparatorTextViewStyle" />
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingTop="12dp">
+
+ <TextView
+ android:id="@android:id/title"
+ android:textColor="?android:attr/textColorTertiary"
+ style="?android:attr/listSeparatorTextViewStyle" />
+
+</FrameLayout>
diff --git a/packages/DocumentsUI/res/layout/item_title.xml b/packages/DocumentsUI/res/layout/item_title.xml
index 9594e4ea32aa..7eb100a245b0 100644
--- a/packages/DocumentsUI/res/layout/item_title.xml
+++ b/packages/DocumentsUI/res/layout/item_title.xml
@@ -38,7 +38,7 @@
android:layout_height="wrap_content"
android:singleLine="true"
android:ellipsize="marquee"
- android:textAppearance="?android:attr/textAppearanceMedium"
- android:textAlignment="viewStart" />
+ android:textAlignment="viewStart"
+ style="@style/TextAppearance.Medium" />
</LinearLayout>
diff --git a/packages/DocumentsUI/res/menu/mode_directory.xml b/packages/DocumentsUI/res/menu/mode_directory.xml
index 624e0247ed82..0a3645f5c3bd 100644
--- a/packages/DocumentsUI/res/menu/mode_directory.xml
+++ b/packages/DocumentsUI/res/menu/mode_directory.xml
@@ -21,12 +21,12 @@
android:showAsAction="always" />
<item
android:id="@+id/menu_share"
- android:icon="@android:drawable/ic_menu_share"
+ android:icon="@drawable/ic_menu_share"
android:title="@string/menu_share"
android:showAsAction="always" />
<item
android:id="@+id/menu_delete"
- android:icon="@android:drawable/ic_menu_delete"
+ android:icon="@drawable/ic_menu_delete"
android:title="@string/menu_delete"
android:showAsAction="always" />
</menu>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 06ab5ff2498a..e0c996f204d6 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -50,5 +50,5 @@
<string name="toast_failed_delete" msgid="2180678019407244069">"Unele documente nu au putut fi șterse"</string>
<string name="more" msgid="7117420986529297171">"Mai multe"</string>
<string name="loading" msgid="7933681260296021180">"Se încarcă…"</string>
- <string name="share_via" msgid="8966594246261344259">"Distribuiţi prin"</string>
+ <string name="share_via" msgid="8966594246261344259">"Distribuiți prin"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 3b9c3f3b3632..32368d8ce577 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -50,5 +50,5 @@
<string name="toast_failed_delete" msgid="2180678019407244069">"Не удалось удалить некоторые документы"</string>
<string name="more" msgid="7117420986529297171">"Ещё"</string>
<string name="loading" msgid="7933681260296021180">"Загрузка…"</string>
- <string name="share_via" msgid="8966594246261344259">"Способ отправки"</string>
+ <string name="share_via" msgid="8966594246261344259">"Поделиться"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index eaec4e5fb143..1575c5b5c42e 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -50,5 +50,5 @@
<string name="toast_failed_delete" msgid="2180678019407244069">"Није могуће избрисати неке документе"</string>
<string name="more" msgid="7117420986529297171">"Још"</string>
<string name="loading" msgid="7933681260296021180">"Учитавање…"</string>
- <string name="share_via" msgid="8966594246261344259">"Дељење преко"</string>
+ <string name="share_via" msgid="8966594246261344259">"Делите преко"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 7b8f2f917007..8246372c5049 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -50,5 +50,5 @@
<string name="toast_failed_delete" msgid="2180678019407244069">"无法删除部分文档"</string>
<string name="more" msgid="7117420986529297171">"更多"</string>
<string name="loading" msgid="7933681260296021180">"正在加载..."</string>
- <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
+ <string name="share_via" msgid="8966594246261344259">"分享方式"</string>
</resources>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index f4a822d3c4fc..682ae4ab7ef2 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -15,54 +15,83 @@
-->
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Title of the documents application [CHAR LIMIT=32] -->
<string name="app_label">Documents</string>
+ <!-- Action bar title prompting user to choose a location to open a document from [CHAR LIMIT=32] -->
<string name="title_open">Open from</string>
+ <!-- Action bar title prompting user to choose a location to save a document to [CHAR LIMIT=32] -->
<string name="title_save">Save to</string>
+ <!-- Menu item that creates a new directory/folder at the current location [CHAR LIMIT=24] -->
<string name="menu_create_dir">Create folder</string>
+ <!-- Menu item that switches view to show documents as a large-format grid of thumbnails [CHAR LIMIT=24] -->
<string name="menu_grid">Grid view</string>
+ <!-- Menu item that switches view to show documents as a list [CHAR LIMIT=24] -->
<string name="menu_list">List view</string>
+ <!-- Menu item that switches the criteria with which documents are sorted [CHAR LIMIT=24] -->
<string name="menu_sort">Sort by</string>
+ <!-- Menu item that enters a mode to search for documents [CHAR LIMIT=24] -->
<string name="menu_search">Search</string>
+ <!-- Menu item that enters activity to change settings [CHAR LIMIT=24] -->
<string name="menu_settings">Settings</string>
+ <!-- Menu item title that opens the selected documents [CHAR LIMIT=24] -->
<string name="menu_open">Open</string>
+ <!-- Menu item title that saves the current document [CHAR LIMIT=24] -->
<string name="menu_save">Save</string>
+ <!-- Menu item title that shares the selected documents [CHAR LIMIT=24] -->
<string name="menu_share">Share</string>
+ <!-- Menu item title that deletes the selected documents [CHAR LIMIT=24] -->
<string name="menu_delete">Delete</string>
+ <!-- Action mode title summarizing the number of documents selected [CHAR LIMIT=32] -->
<string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string>
+ <!-- Mode that sorts documents by their display name alphabetically [CHAR LIMIT=24] -->
<string name="sort_name">By name</string>
+ <!-- Mode that sorts documents by their last modified time in descending order; most recent first [CHAR LIMIT=24] -->
<string name="sort_date">By date modified</string>
+ <!-- Mode that sorts documents by their file size in descending order; largest first [CHAR LIMIT=24] -->
<string name="sort_size">By size</string>
+ <!-- Accessibility title to open the drawer showing all roots where documents can be stored [CHAR LIMIT=32] -->
<string name="drawer_open">Show roots</string>
+ <!-- Accessibility title to close the drawer showing all roots where documents can be stored [CHAR LIMIT=32] -->
<string name="drawer_close">Hide roots</string>
+ <!-- Toast shown when saving a document failed with an error [CHAR LIMIT=48] -->
<string name="save_error">Failed to save document</string>
+ <!-- Title of storage root location that contains recently modified or used documents [CHAR LIMIT=24] -->
<string name="root_recent">Recent</string>
+ <!-- Subtitle of storage root indicating the total free space available, in bytes [CHAR LIMIT=24] -->
<string name="root_available_bytes"><xliff:g id="size" example="3GB">%1$s</xliff:g> free</string>
- <string name="root_type_service">Services</string>
+ <!-- Header title for list of storage roots that contains cloud services [CHAR LIMIT=24] -->
+ <string name="root_type_service">Storage services</string>
+ <!-- Header title for list of storage roots that contains shortcuts to documents that may be available elsewhere [CHAR LIMIT=24] -->
<string name="root_type_shortcut">Shortcuts</string>
+ <!-- Header title for list of storage roots that contains physical devices [CHAR LIMIT=24] -->
<string name="root_type_device">Devices</string>
+ <!-- Header title for list of additional apps that can provide documents [CHAR LIMIT=24] -->
<string name="root_type_apps">More apps</string>
+ <!-- Title for setting that will show all advanced storage devices [CHAR LIMIT=32] -->
<string name="pref_advanced_devices">Display advanced devices</string>
+ <!-- Title for setting that will show file sizes for all documents [CHAR LIMIT=32] -->
<string name="pref_file_size">Display file size</string>
<string name="pref_device_size">Display device size</string>
+ <!-- Text shown when a directory of documents is empty [CHAR LIMIT=24] -->
<string name="empty">No items</string>
+ <!-- Toast shown when no app can be found to open the selected document [CHAR LIMIT=48] -->
<string name="toast_no_application">Can\'t open file</string>
+ <!-- Toast shown when some of the selected documents failed to be deleted [CHAR LIMIT=48] -->
<string name="toast_failed_delete">Unable to delete some documents</string>
- <string name="more">More</string>
- <string name="loading">Loading\u2026</string>
-
+ <!-- Title of dialog when prompting user to select an app to share documents with [CHAR LIMIT=32] -->
<string name="share_via">Share via</string>
</resources>
diff --git a/packages/DocumentsUI/res/values/styles.xml b/packages/DocumentsUI/res/values/styles.xml
new file mode 100644
index 000000000000..59fbd6f3284b
--- /dev/null
+++ b/packages/DocumentsUI/res/values/styles.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<resources>
+ <style name="TextAppearance" />
+
+ <style name="TextAppearance.Medium">
+ <item name="android:textAppearance">?android:attr/textAppearanceMedium</item>
+ <item name="android:textColor">?android:attr/textColorSecondary</item>
+ </style>
+
+ <style name="TextAppearance.Small">
+ <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
+ <item name="android:textColor">?android:attr/textColorTertiary</item>
+ </style>
+</resources>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
index e0b8d1971a6e..d8e60aa2eed3 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/CreateDirectoryFragment.java
@@ -70,7 +70,7 @@ public class CreateDirectoryFragment extends DialogFragment {
try {
final Uri childUri = DocumentsContract.createDocument(
- resolver, cwd.uri, Document.MIME_TYPE_DIR, displayName);
+ resolver, cwd.derivedUri, Document.MIME_TYPE_DIR, displayName);
// Navigate into newly created child
final DocumentInfo childDoc = DocumentInfo.fromUri(resolver, childUri);
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
index e59443763c72..ba5a511661ab 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryFragment.java
@@ -20,6 +20,8 @@ import static com.android.documentsui.DocumentsActivity.TAG;
import static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE;
import static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
import static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
+import static com.android.documentsui.DocumentsActivity.State.MODE_UNKNOWN;
+import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_UNKNOWN;
import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import static com.android.documentsui.model.DocumentInfo.getCursorLong;
import static com.android.documentsui.model.DocumentInfo.getCursorString;
@@ -29,15 +31,18 @@ import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager.LoaderCallbacks;
import android.content.ContentResolver;
+import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.Point;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.os.CancellationSignal;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
import android.text.format.DateUtils;
@@ -53,6 +58,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.MultiChoiceModeListener;
+import android.widget.AbsListView.RecyclerListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
@@ -63,6 +69,7 @@ import android.widget.TextView;
import android.widget.Toast;
import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.RecentsProvider.StateColumns;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.RootInfo;
import com.android.internal.util.Predicate;
@@ -91,43 +98,48 @@ public class DirectoryFragment extends Fragment {
private int mType = TYPE_NORMAL;
+ private int mLastMode = MODE_UNKNOWN;
+ private int mLastSortOrder = SORT_ORDER_UNKNOWN;
+ private boolean mLastShowSize = false;
+
private Point mThumbSize;
private DocumentsAdapter mAdapter;
private LoaderCallbacks<DirectoryResult> mCallbacks;
private static final String EXTRA_TYPE = "type";
- private static final String EXTRA_AUTHORITY = "authority";
- private static final String EXTRA_ROOT_ID = "rootId";
- private static final String EXTRA_DOC_ID = "docId";
+ private static final String EXTRA_ROOT = "root";
+ private static final String EXTRA_DOC = "doc";
private static final String EXTRA_QUERY = "query";
- private static AtomicInteger sLoaderId = new AtomicInteger(4000);
+ /**
+ * MIME types that should always show thumbnails in list mode.
+ */
+ private static final String[] LIST_THUMBNAIL_MIMES = new String[] { "image/*", "video/*" };
- private int mLastSortOrder = -1;
+ private static AtomicInteger sLoaderId = new AtomicInteger(4000);
private final int mLoaderId = sLoaderId.incrementAndGet();
- public static void showNormal(FragmentManager fm, Uri uri) {
- show(fm, TYPE_NORMAL, uri.getAuthority(), null, DocumentsContract.getDocumentId(uri), null);
+ public static void showNormal(FragmentManager fm, RootInfo root, DocumentInfo doc) {
+ show(fm, TYPE_NORMAL, root, doc, null);
}
- public static void showSearch(FragmentManager fm, Uri uri, String query) {
- show(fm, TYPE_SEARCH, uri.getAuthority(), null, DocumentsContract.getDocumentId(uri),
- query);
+ public static void showSearch(
+ FragmentManager fm, RootInfo root, DocumentInfo doc, String query) {
+ show(fm, TYPE_SEARCH, root, doc, query);
}
public static void showRecentsOpen(FragmentManager fm) {
- show(fm, TYPE_RECENT_OPEN, null, null, null, null);
+ show(fm, TYPE_RECENT_OPEN, null, null, null);
}
- private static void show(FragmentManager fm, int type, String authority, String rootId,
- String docId, String query) {
+ private static void show(
+ FragmentManager fm, int type, RootInfo root, DocumentInfo doc, String query) {
final Bundle args = new Bundle();
args.putInt(EXTRA_TYPE, type);
- args.putString(EXTRA_AUTHORITY, authority);
- args.putString(EXTRA_ROOT_ID, rootId);
- args.putString(EXTRA_DOC_ID, docId);
+ args.putParcelable(EXTRA_ROOT, root);
+ args.putParcelable(EXTRA_DOC, doc);
args.putString(EXTRA_QUERY, query);
final DirectoryFragment fragment = new DirectoryFragment();
@@ -154,10 +166,12 @@ public class DirectoryFragment extends Fragment {
mListView = (ListView) view.findViewById(R.id.list);
mListView.setOnItemClickListener(mItemListener);
mListView.setMultiChoiceModeListener(mMultiListener);
+ mListView.setRecyclerListener(mRecycleListener);
mGridView = (GridView) view.findViewById(R.id.grid);
mGridView.setOnItemClickListener(mItemListener);
mGridView.setMultiChoiceModeListener(mMultiListener);
+ mGridView.setRecyclerListener(mRecycleListener);
return view;
}
@@ -167,6 +181,7 @@ public class DirectoryFragment extends Fragment {
super.onActivityCreated(savedInstanceState);
final Context context = getActivity();
+ final State state = getDisplayState(DirectoryFragment.this);
mAdapter = new DocumentsAdapter();
mType = getArguments().getInt(EXTRA_TYPE);
@@ -174,35 +189,56 @@ public class DirectoryFragment extends Fragment {
mCallbacks = new LoaderCallbacks<DirectoryResult>() {
@Override
public Loader<DirectoryResult> onCreateLoader(int id, Bundle args) {
- final State state = getDisplayState(DirectoryFragment.this);
-
- final String authority = getArguments().getString(EXTRA_AUTHORITY);
- final String rootId = getArguments().getString(EXTRA_ROOT_ID);
- final String docId = getArguments().getString(EXTRA_DOC_ID);
+ final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
+ final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
final String query = getArguments().getString(EXTRA_QUERY);
Uri contentsUri;
switch (mType) {
case TYPE_NORMAL:
- contentsUri = DocumentsContract.buildChildDocumentsUri(authority, docId);
- return new DirectoryLoader(context, rootId, contentsUri, state.sortOrder);
+ contentsUri = DocumentsContract.buildChildDocumentsUri(
+ doc.authority, doc.documentId);
+ if (state.action == ACTION_MANAGE) {
+ contentsUri = DocumentsContract.setManageMode(contentsUri);
+ }
+ return new DirectoryLoader(
+ context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_SEARCH:
contentsUri = DocumentsContract.buildSearchDocumentsUri(
- authority, docId, query);
- return new DirectoryLoader(context, rootId, contentsUri, state.sortOrder);
+ doc.authority, doc.documentId, query);
+ if (state.action == ACTION_MANAGE) {
+ contentsUri = DocumentsContract.setManageMode(contentsUri);
+ }
+ return new DirectoryLoader(
+ context, mType, root, doc, contentsUri, state.userSortOrder);
case TYPE_RECENT_OPEN:
final RootsCache roots = DocumentsApplication.getRootsCache(context);
final List<RootInfo> matchingRoots = roots.getMatchingRoots(state);
- return new RecentLoader(context, matchingRoots);
+ return new RecentLoader(context, matchingRoots, state.acceptMimes);
default:
throw new IllegalStateException("Unknown type " + mType);
-
}
}
@Override
public void onLoadFinished(Loader<DirectoryResult> loader, DirectoryResult result) {
+ if (!isAdded()) return;
+
mAdapter.swapCursor(result.cursor);
+
+ // Push latest state up to UI
+ // TODO: if mode change was racing with us, don't overwrite it
+ state.derivedMode = result.mode;
+ state.derivedSortOrder = result.sortOrder;
+ ((DocumentsActivity) context).onStateChanged();
+
+ updateDisplayState();
+
+ if (mLastSortOrder != state.derivedSortOrder) {
+ mLastSortOrder = state.derivedSortOrder;
+ mListView.smoothScrollToPosition(0);
+ mGridView.smoothScrollToPosition(0);
+ }
}
@Override
@@ -211,6 +247,9 @@ public class DirectoryFragment extends Fragment {
}
};
+ // Kick off loader at least once
+ getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
+
updateDisplayState();
}
@@ -220,22 +259,52 @@ public class DirectoryFragment extends Fragment {
updateDisplayState();
}
- public void updateDisplayState() {
+ public void onUserSortOrderChanged() {
+ // Sort order change always triggers reload; we'll trigger state change
+ // on the flip side.
+ getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
+ }
+
+ public void onUserModeChanged() {
+ final ContentResolver resolver = getActivity().getContentResolver();
final State state = getDisplayState(this);
- if (mLastSortOrder != state.sortOrder) {
- getLoaderManager().restartLoader(mLoaderId, null, mCallbacks);
- mLastSortOrder = state.sortOrder;
- }
+ final RootInfo root = getArguments().getParcelable(EXTRA_ROOT);
+ final DocumentInfo doc = getArguments().getParcelable(EXTRA_DOC);
+
+ final Uri stateUri = RecentsProvider.buildState(
+ root.authority, root.rootId, doc.documentId);
+ final ContentValues values = new ContentValues();
+ values.put(StateColumns.MODE, state.userMode);
+
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... params) {
+ resolver.insert(stateUri, values);
+ return null;
+ }
+ }.execute();
- mListView.smoothScrollToPosition(0);
- mGridView.smoothScrollToPosition(0);
+ // Mode change is just visual change; no need to kick loader, and
+ // deliver change event immediately.
+ state.derivedMode = state.userMode;
+ ((DocumentsActivity) getActivity()).onStateChanged();
- mListView.setVisibility(state.mode == MODE_LIST ? View.VISIBLE : View.GONE);
- mGridView.setVisibility(state.mode == MODE_GRID ? View.VISIBLE : View.GONE);
+ updateDisplayState();
+ }
+
+ private void updateDisplayState() {
+ final State state = getDisplayState(this);
mFilter = new MimePredicate(state.acceptMimes);
+ if (mLastMode == state.derivedMode && mLastShowSize == state.showSize) return;
+ mLastMode = state.derivedMode;
+ mLastShowSize = state.showSize;
+
+ mListView.setVisibility(state.derivedMode == MODE_LIST ? View.VISIBLE : View.GONE);
+ mGridView.setVisibility(state.derivedMode == MODE_GRID ? View.VISIBLE : View.GONE);
+
final int choiceMode;
if (state.allowMultiple) {
choiceMode = ListView.CHOICE_MODE_MULTIPLE_MODAL;
@@ -244,7 +313,7 @@ public class DirectoryFragment extends Fragment {
}
final int thumbSize;
- if (state.mode == MODE_GRID) {
+ if (state.derivedMode == MODE_GRID) {
thumbSize = getResources().getDimensionPixelSize(R.dimen.grid_width);
mListView.setAdapter(null);
mListView.setChoiceMode(ListView.CHOICE_MODE_NONE);
@@ -253,15 +322,15 @@ public class DirectoryFragment extends Fragment {
mGridView.setNumColumns(GridView.AUTO_FIT);
mGridView.setChoiceMode(choiceMode);
mCurrentView = mGridView;
- } else if (state.mode == MODE_LIST) {
- thumbSize = getResources().getDimensionPixelSize(android.R.dimen.app_icon_size);
+ } else if (state.derivedMode == MODE_LIST) {
+ thumbSize = getResources().getDimensionPixelSize(R.dimen.icon_size);
mGridView.setAdapter(null);
mGridView.setChoiceMode(ListView.CHOICE_MODE_NONE);
mListView.setAdapter(mAdapter);
mListView.setChoiceMode(choiceMode);
mCurrentView = mListView;
} else {
- throw new IllegalStateException();
+ throw new IllegalStateException("Unknown state " + state.derivedMode);
}
mThumbSize = new Point(thumbSize, thumbSize);
@@ -271,9 +340,11 @@ public class DirectoryFragment extends Fragment {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
final Cursor cursor = mAdapter.getItem(position);
- final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
- if (mFilter.apply(doc)) {
- ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
+ if (cursor != null) {
+ final DocumentInfo doc = DocumentInfo.fromDirectoryCursor(cursor);
+ if (mFilter.apply(doc)) {
+ ((DocumentsActivity) getActivity()).onDocumentPicked(doc);
+ }
}
}
};
@@ -344,10 +415,20 @@ public class DirectoryFragment extends Fragment {
public void onItemCheckedStateChanged(
ActionMode mode, int position, long id, boolean checked) {
if (checked) {
- // Directories cannot be checked
+ // Directories and footer items cannot be checked
+ boolean valid = false;
+
final Cursor cursor = mAdapter.getItem(position);
- final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
- if (Document.MIME_TYPE_DIR.equals(docMimeType)) {
+ if (cursor != null) {
+ final String docMimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+
+ // Only valid if non-directory matches filter
+ final State state = getDisplayState(DirectoryFragment.this);
+ valid = !Document.MIME_TYPE_DIR.equals(docMimeType)
+ && MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
+ }
+
+ if (!valid) {
mCurrentView.setItemChecked(position, false);
}
}
@@ -357,6 +438,20 @@ public class DirectoryFragment extends Fragment {
}
};
+ private RecyclerListener mRecycleListener = new RecyclerListener() {
+ @Override
+ public void onMovedToScrapHeap(View view) {
+ final ImageView iconThumb = (ImageView) view.findViewById(R.id.icon_thumb);
+ if (iconThumb != null) {
+ final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
+ if (oldTask != null) {
+ oldTask.reallyCancel();
+ iconThumb.setTag(null);
+ }
+ }
+ }
+ };
+
private void onShareDocuments(List<DocumentInfo> docs) {
Intent intent;
if (docs.size() == 1) {
@@ -366,7 +461,7 @@ public class DirectoryFragment extends Fragment {
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setType(doc.mimeType);
- intent.putExtra(Intent.EXTRA_STREAM, doc.uri);
+ intent.putExtra(Intent.EXTRA_STREAM, doc.derivedUri);
} else if (docs.size() > 1) {
intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
@@ -377,7 +472,7 @@ public class DirectoryFragment extends Fragment {
final ArrayList<Uri> uris = Lists.newArrayList();
for (DocumentInfo doc : docs) {
mimeTypes.add(doc.mimeType);
- uris.add(doc.uri);
+ uris.add(doc.derivedUri);
}
intent.setType(findCommonMimeType(mimeTypes));
@@ -403,7 +498,7 @@ public class DirectoryFragment extends Fragment {
continue;
}
- if (!DocumentsContract.deleteDocument(resolver, doc.uri)) {
+ if (!DocumentsContract.deleteDocument(resolver, doc.derivedUri)) {
Log.w(TAG, "Failed to delete " + doc);
hadTrouble = true;
}
@@ -418,27 +513,51 @@ public class DirectoryFragment extends Fragment {
return ((DocumentsActivity) fragment.getActivity()).getDisplayState();
}
- private interface Footer {
- public View getView(View convertView, ViewGroup parent);
+ private static abstract class Footer {
+ private final int mItemViewType;
+
+ public Footer(int itemViewType) {
+ mItemViewType = itemViewType;
+ }
+
+ public abstract View getView(View convertView, ViewGroup parent);
+
+ public int getItemViewType() {
+ return mItemViewType;
+ }
}
- private static class LoadingFooter implements Footer {
+ private class LoadingFooter extends Footer {
+ public LoadingFooter() {
+ super(1);
+ }
+
@Override
public View getView(View convertView, ViewGroup parent) {
final Context context = parent.getContext();
+ final State state = getDisplayState(DirectoryFragment.this);
+
if (convertView == null) {
final LayoutInflater inflater = LayoutInflater.from(context);
- convertView = inflater.inflate(R.layout.item_loading, parent, false);
+ if (state.derivedMode == MODE_LIST) {
+ convertView = inflater.inflate(R.layout.item_loading_list, parent, false);
+ } else if (state.derivedMode == MODE_GRID) {
+ convertView = inflater.inflate(R.layout.item_loading_grid, parent, false);
+ } else {
+ throw new IllegalStateException();
+ }
}
+
return convertView;
}
}
- private class MessageFooter implements Footer {
+ private class MessageFooter extends Footer {
private final int mIcon;
private final String mMessage;
- public MessageFooter(int icon, String message) {
+ public MessageFooter(int itemViewType, int icon, String message) {
+ super(itemViewType);
mIcon = icon;
mMessage = message;
}
@@ -450,9 +569,9 @@ public class DirectoryFragment extends Fragment {
if (convertView == null) {
final LayoutInflater inflater = LayoutInflater.from(context);
- if (state.mode == MODE_LIST) {
+ if (state.derivedMode == MODE_LIST) {
convertView = inflater.inflate(R.layout.item_message_list, parent, false);
- } else if (state.mode == MODE_GRID) {
+ } else if (state.derivedMode == MODE_GRID) {
convertView = inflater.inflate(R.layout.item_message_grid, parent, false);
} else {
throw new IllegalStateException();
@@ -483,11 +602,11 @@ public class DirectoryFragment extends Fragment {
if (extras != null) {
final String info = extras.getString(DocumentsContract.EXTRA_INFO);
if (info != null) {
- mFooters.add(new MessageFooter(R.drawable.ic_dialog_alert, info));
+ mFooters.add(new MessageFooter(2, R.drawable.ic_dialog_alert, info));
}
final String error = extras.getString(DocumentsContract.EXTRA_ERROR);
if (error != null) {
- mFooters.add(new MessageFooter(R.drawable.ic_dialog_alert, error));
+ mFooters.add(new MessageFooter(3, R.drawable.ic_dialog_alert, error));
}
if (extras.getBoolean(DocumentsContract.EXTRA_LOADING, false)) {
mFooters.add(new LoadingFooter());
@@ -509,7 +628,11 @@ public class DirectoryFragment extends Fragment {
return getDocumentView(position, convertView, parent);
} else {
position -= mCursorCount;
- return mFooters.get(position).getView(convertView, parent);
+ convertView = mFooters.get(position).getView(convertView, parent);
+ // Only the view itself is disabled; contents inside shouldn't
+ // be dimmed.
+ convertView.setEnabled(false);
+ return convertView;
}
}
@@ -523,9 +646,9 @@ public class DirectoryFragment extends Fragment {
if (convertView == null) {
final LayoutInflater inflater = LayoutInflater.from(context);
- if (state.mode == MODE_LIST) {
+ if (state.derivedMode == MODE_LIST) {
convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
- } else if (state.mode == MODE_GRID) {
+ } else if (state.derivedMode == MODE_GRID) {
convertView = inflater.inflate(R.layout.item_doc_grid, parent, false);
} else {
throw new IllegalStateException();
@@ -545,7 +668,9 @@ public class DirectoryFragment extends Fragment {
final String docSummary = getCursorString(cursor, Document.COLUMN_SUMMARY);
final long docSize = getCursorLong(cursor, Document.COLUMN_SIZE);
- final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+ final View icon = convertView.findViewById(android.R.id.icon);
+ final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
+ final ImageView iconThumb = (ImageView) convertView.findViewById(R.id.icon_thumb);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
final View line2 = convertView.findViewById(R.id.line2);
final ImageView icon1 = (ImageView) convertView.findViewById(android.R.id.icon1);
@@ -553,26 +678,49 @@ public class DirectoryFragment extends Fragment {
final TextView date = (TextView) convertView.findViewById(R.id.date);
final TextView size = (TextView) convertView.findViewById(R.id.size);
- final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) icon.getTag();
+ final ThumbnailAsyncTask oldTask = (ThumbnailAsyncTask) iconThumb.getTag();
if (oldTask != null) {
- oldTask.cancel(false);
+ oldTask.reallyCancel();
+ iconThumb.setTag(null);
}
- if ((docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0) {
+ iconMime.animate().cancel();
+ iconThumb.animate().cancel();
+
+ final boolean supportsThumbnail = (docFlags & Document.FLAG_SUPPORTS_THUMBNAIL) != 0;
+ final boolean allowThumbnail = (state.derivedMode == MODE_GRID)
+ || MimePredicate.mimeMatches(LIST_THUMBNAIL_MIMES, docMimeType);
+
+ boolean cacheHit = false;
+ if (supportsThumbnail && allowThumbnail) {
final Uri uri = DocumentsContract.buildDocumentUri(docAuthority, docId);
final Bitmap cachedResult = thumbs.get(uri);
if (cachedResult != null) {
- icon.setImageBitmap(cachedResult);
+ iconThumb.setImageBitmap(cachedResult);
+ cacheHit = true;
} else {
- final ThumbnailAsyncTask task = new ThumbnailAsyncTask(icon, mThumbSize);
- icon.setImageBitmap(null);
- icon.setTag(task);
- task.execute(uri);
+ iconThumb.setImageDrawable(null);
+ final ThumbnailAsyncTask task = new ThumbnailAsyncTask(
+ uri, iconMime, iconThumb, mThumbSize);
+ iconThumb.setTag(task);
+ task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
- } else if (docIcon != 0) {
- icon.setImageDrawable(IconUtils.loadPackageIcon(context, docAuthority, docIcon));
+ }
+
+ // Always throw MIME icon into place, even when a thumbnail is being
+ // loaded in background.
+ if (cacheHit) {
+ iconMime.setAlpha(0f);
+ iconThumb.setAlpha(1f);
} else {
- icon.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType));
+ iconMime.setAlpha(1f);
+ iconThumb.setAlpha(0f);
+ if (docIcon != 0) {
+ iconMime.setImageDrawable(
+ IconUtils.loadPackageIcon(context, docAuthority, docIcon));
+ } else {
+ iconMime.setImageDrawable(IconUtils.loadMimeIcon(context, docMimeType));
+ }
}
title.setText(docDisplayName);
@@ -581,12 +729,19 @@ public class DirectoryFragment extends Fragment {
if (mType == TYPE_RECENT_OPEN) {
final RootInfo root = roots.getRoot(docAuthority, docRootId);
+ final Drawable iconDrawable = root.loadIcon(context);
icon1.setVisibility(View.VISIBLE);
- icon1.setImageDrawable(root.loadIcon(context));
- summary.setText(root.getDirectoryString());
- summary.setVisibility(View.VISIBLE);
- summary.setTextAlignment(TextView.TEXT_ALIGNMENT_TEXT_END);
- hasLine2 = true;
+ icon1.setImageDrawable(iconDrawable);
+
+ if (iconDrawable != null && roots.isIconUnique(root)) {
+ // No summary needed if icon speaks for itself
+ summary.setVisibility(View.INVISIBLE);
+ } else {
+ summary.setText(root.getDirectoryString());
+ summary.setVisibility(View.VISIBLE);
+ summary.setTextAlignment(TextView.TEXT_ALIGNMENT_TEXT_END);
+ hasLine2 = true;
+ }
} else {
icon1.setVisibility(View.GONE);
if (docSummary != null) {
@@ -619,6 +774,18 @@ public class DirectoryFragment extends Fragment {
line2.setVisibility(hasLine2 ? View.VISIBLE : View.GONE);
+ final boolean enabled = Document.MIME_TYPE_DIR.equals(docMimeType)
+ || MimePredicate.mimeMatches(state.acceptMimes, docMimeType);
+ if (enabled) {
+ setEnabledRecursive(convertView, true);
+ icon.setAlpha(1f);
+ icon1.setAlpha(1f);
+ } else {
+ setEnabledRecursive(convertView, false);
+ icon.setAlpha(0.5f);
+ icon1.setAlpha(0.5f);
+ }
+
return convertView;
}
@@ -643,52 +810,55 @@ public class DirectoryFragment extends Fragment {
}
@Override
+ public int getViewTypeCount() {
+ return 4;
+ }
+
+ @Override
public int getItemViewType(int position) {
if (position < mCursorCount) {
return 0;
} else {
- return IGNORE_ITEM_VIEW_TYPE;
+ position -= mCursorCount;
+ return mFooters.get(position).getItemViewType();
}
}
-
- @Override
- public boolean areAllItemsEnabled() {
- return false;
- }
-
- @Override
- public boolean isEnabled(int position) {
- return position < mCursorCount;
- }
}
private static class ThumbnailAsyncTask extends AsyncTask<Uri, Void, Bitmap> {
- private final ImageView mTarget;
+ private final Uri mUri;
+ private final ImageView mIconMime;
+ private final ImageView mIconThumb;
private final Point mThumbSize;
+ private final CancellationSignal mSignal;
- public ThumbnailAsyncTask(ImageView target, Point thumbSize) {
- mTarget = target;
+ public ThumbnailAsyncTask(
+ Uri uri, ImageView iconMime, ImageView iconThumb, Point thumbSize) {
+ mUri = uri;
+ mIconMime = iconMime;
+ mIconThumb = iconThumb;
mThumbSize = thumbSize;
+ mSignal = new CancellationSignal();
}
- @Override
- protected void onPreExecute() {
- mTarget.setTag(this);
+ public void reallyCancel() {
+ cancel(false);
+ mSignal.cancel();
}
@Override
protected Bitmap doInBackground(Uri... params) {
- final Context context = mTarget.getContext();
- final Uri uri = params[0];
+ final Context context = mIconThumb.getContext();
Bitmap result = null;
try {
+ // TODO: switch to using unstable provider
result = DocumentsContract.getDocumentThumbnail(
- context.getContentResolver(), uri, mThumbSize, null);
+ context.getContentResolver(), mUri, mThumbSize, mSignal);
if (result != null) {
final ThumbnailCache thumbs = DocumentsApplication.getThumbnailsCache(
context, mThumbSize);
- thumbs.put(uri, result);
+ thumbs.put(mUri, result);
}
} catch (Exception e) {
Log.w(TAG, "Failed to load thumbnail: " + e);
@@ -698,9 +868,14 @@ public class DirectoryFragment extends Fragment {
@Override
protected void onPostExecute(Bitmap result) {
- if (mTarget.getTag() == this) {
- mTarget.setImageBitmap(result);
- mTarget.setTag(null);
+ if (mIconThumb.getTag() == this && result != null) {
+ mIconThumb.setTag(null);
+ mIconThumb.setImageBitmap(result);
+
+ mIconMime.setAlpha(1f);
+ mIconMime.animate().alpha(0f).start();
+ mIconThumb.setAlpha(0f);
+ mIconThumb.animate().alpha(1f).start();
}
}
}
@@ -749,4 +924,16 @@ public class DirectoryFragment extends Fragment {
return commonType[0] + "/" + commonType[1];
}
+
+ private void setEnabledRecursive(View v, boolean enabled) {
+ if (v.isEnabled() == enabled) return;
+ v.setEnabled(enabled);
+
+ if (v instanceof ViewGroup) {
+ final ViewGroup vg = (ViewGroup) v;
+ for (int i = vg.getChildCount() - 1; i >= 0; i--) {
+ setEnabledRecursive(vg.getChildAt(i), enabled);
+ }
+ }
+ }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
index 6ea57d77cfa6..334e26285f6a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DirectoryLoader.java
@@ -16,18 +16,29 @@
package com.android.documentsui;
+import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.DocumentsActivity.State.MODE_UNKNOWN;
import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_DISPLAY_NAME;
import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED;
import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_SIZE;
+import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_UNKNOWN;
+import static com.android.documentsui.model.DocumentInfo.getCursorInt;
import android.content.AsyncTaskLoader;
import android.content.ContentProviderClient;
+import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.CancellationSignal;
import android.os.OperationCanceledException;
import android.provider.DocumentsContract.Document;
+import android.util.Log;
+
+import com.android.documentsui.DocumentsActivity.State;
+import com.android.documentsui.RecentsProvider.StateColumns;
+import com.android.documentsui.model.DocumentInfo;
+import com.android.documentsui.model.RootInfo;
import libcore.io.IoUtils;
@@ -36,6 +47,9 @@ class DirectoryResult implements AutoCloseable {
Cursor cursor;
Exception exception;
+ int mode = MODE_UNKNOWN;
+ int sortOrder = SORT_ORDER_UNKNOWN;
+
@Override
public void close() {
IoUtils.closeQuietly(cursor);
@@ -48,18 +62,23 @@ class DirectoryResult implements AutoCloseable {
public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();
- private final String mRootId;
+ private final int mType;
+ private final RootInfo mRoot;
+ private final DocumentInfo mDoc;
private final Uri mUri;
- private final int mSortOrder;
+ private final int mUserSortOrder;
private CancellationSignal mSignal;
private DirectoryResult mResult;
- public DirectoryLoader(Context context, String rootId, Uri uri, int sortOrder) {
+ public DirectoryLoader(Context context, int type, RootInfo root, DocumentInfo doc, Uri uri,
+ int userSortOrder) {
super(context);
- mRootId = rootId;
+ mType = type;
+ mRoot = root;
+ mDoc = doc;
mUri = uri;
- mSortOrder = sortOrder;
+ mUserSortOrder = userSortOrder;
}
@Override
@@ -70,20 +89,75 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
}
mSignal = new CancellationSignal();
}
- final DirectoryResult result = new DirectoryResult();
+
+ final ContentResolver resolver = getContext().getContentResolver();
final String authority = mUri.getAuthority();
+
+ final DirectoryResult result = new DirectoryResult();
+
+ int userMode = State.MODE_UNKNOWN;
+
+ // Pick up any custom modes requested by user
+ Cursor cursor = null;
try {
- result.client = getContext()
- .getContentResolver().acquireUnstableContentProviderClient(authority);
- final Cursor cursor = result.client.query(
- mUri, null, null, null, getQuerySortOrder(mSortOrder), mSignal);
+ final Uri stateUri = RecentsProvider.buildState(
+ mRoot.authority, mRoot.rootId, mDoc.documentId);
+ cursor = resolver.query(stateUri, null, null, null, null);
+ if (cursor.moveToFirst()) {
+ userMode = getCursorInt(cursor, StateColumns.MODE);
+ }
+ } finally {
+ IoUtils.closeQuietly(cursor);
+ }
+
+ if (userMode != State.MODE_UNKNOWN) {
+ result.mode = userMode;
+ } else {
+ if ((mDoc.flags & Document.FLAG_DIR_PREFERS_GRID) != 0) {
+ result.mode = State.MODE_GRID;
+ } else {
+ result.mode = State.MODE_LIST;
+ }
+ }
+
+ if (mUserSortOrder != State.SORT_ORDER_UNKNOWN) {
+ result.sortOrder = mUserSortOrder;
+ } else {
+ if ((mDoc.flags & Document.FLAG_DIR_PREFERS_LAST_MODIFIED) != 0) {
+ result.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
+ } else {
+ result.sortOrder = State.SORT_ORDER_DISPLAY_NAME;
+ }
+ }
+
+ // Search always uses ranking from provider
+ if (mType == DirectoryFragment.TYPE_SEARCH) {
+ result.sortOrder = State.SORT_ORDER_UNKNOWN;
+ }
+
+ Log.d(TAG, "userMode=" + userMode + ", userSortOrder=" + mUserSortOrder + " --> mode="
+ + result.mode + ", sortOrder=" + result.sortOrder);
+
+ try {
+ result.client = resolver.acquireUnstableContentProviderClient(authority);
+ cursor = result.client.query(
+ mUri, null, null, null, getQuerySortOrder(result.sortOrder), mSignal);
cursor.registerContentObserver(mObserver);
- final Cursor withRoot = new RootCursorWrapper(mUri.getAuthority(), mRootId, cursor, -1);
- final Cursor sorted = new SortingCursorWrapper(withRoot, mSortOrder);
+ cursor = new RootCursorWrapper(mUri.getAuthority(), mRoot.rootId, cursor, -1);
- result.cursor = sorted;
+ if (mType == DirectoryFragment.TYPE_SEARCH) {
+ // Filter directories out of search results, for now
+ cursor = new FilteringCursorWrapper(cursor, null, new String[] {
+ Document.MIME_TYPE_DIR });
+ } else {
+ // Normal directories should have sorting applied
+ cursor = new SortingCursorWrapper(cursor, result.sortOrder);
+ }
+
+ result.cursor = cursor;
} catch (Exception e) {
+ Log.d(TAG, "Failed to query", e);
result.exception = e;
ContentProviderClient.closeQuietly(result.client);
} finally {
@@ -91,6 +165,7 @@ public class DirectoryLoader extends AsyncTaskLoader<DirectoryResult> {
mSignal = null;
}
}
+
return result;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 38b2ee837189..e89d388688f2 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -50,6 +50,7 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
+import android.view.MenuItem.OnActionExpandListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
@@ -60,6 +61,9 @@ import android.widget.SearchView.OnQueryTextListener;
import android.widget.TextView;
import android.widget.Toast;
+import com.android.documentsui.RecentsProvider.RecentColumns;
+import com.android.documentsui.RecentsProvider.ResumeColumns;
+import com.android.documentsui.RecentsProvider.StateColumns;
import com.android.documentsui.model.DocumentInfo;
import com.android.documentsui.model.DocumentStack;
import com.android.documentsui.model.DurableUtils;
@@ -84,6 +88,7 @@ public class DocumentsActivity extends Activity {
private static final String EXTRA_STATE = "state";
private boolean mIgnoreNextNavigation;
+ private boolean mIgnoreNextCollapse;
private RootsCache mRoots;
private State mState;
@@ -168,10 +173,6 @@ public class DocumentsActivity extends Activity {
mState.showAdvanced = SettingsActivity.getDisplayAdvancedDevices(this);
if (mState.action == ACTION_MANAGE) {
- mState.sortOrder = SORT_ORDER_LAST_MODIFIED;
- }
-
- if (mState.action == ACTION_MANAGE) {
final Uri uri = intent.getData();
final String rootId = DocumentsContract.getRootId(uri);
final RootInfo root = mRoots.getRoot(uri.getAuthority(), rootId);
@@ -191,7 +192,7 @@ public class DocumentsActivity extends Activity {
try {
if (cursor.moveToFirst()) {
final byte[] rawStack = cursor.getBlob(
- cursor.getColumnIndex(RecentsProvider.COL_PATH));
+ cursor.getColumnIndex(ResumeColumns.STACK));
DurableUtils.readFromArray(rawStack, mState.stack);
}
} catch (IOException e) {
@@ -204,7 +205,7 @@ public class DocumentsActivity extends Activity {
final RootInfo root = getCurrentRoot();
final List<RootInfo> matchingRoots = mRoots.getMatchingRoots(mState);
if (!matchingRoots.contains(root)) {
- mState.stack.clear();
+ mState.stack.reset();
}
// Only open drawer when showing recents
@@ -235,12 +236,14 @@ public class DocumentsActivity extends Activity {
public void onDrawerOpened(View drawerView) {
mDrawerToggle.onDrawerOpened(drawerView);
updateActionBar();
+ invalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View drawerView) {
mDrawerToggle.onDrawerClosed(drawerView);
updateActionBar();
+ invalidateOptionsMenu();
}
@Override
@@ -306,7 +309,6 @@ public class DocumentsActivity extends Activity {
public boolean onQueryTextSubmit(String query) {
mState.currentSearch = query;
onCurrentDirectoryChanged();
- mSearchView.setIconified(true);
return true;
}
@@ -316,12 +318,22 @@ public class DocumentsActivity extends Activity {
}
});
- mSearchView.setOnCloseListener(new OnCloseListener() {
+ searchMenu.setOnActionExpandListener(new OnActionExpandListener() {
+ @Override
+ public boolean onMenuItemActionExpand(MenuItem item) {
+ return true;
+ }
+
@Override
- public boolean onClose() {
+ public boolean onMenuItemActionCollapse(MenuItem item) {
+ if (mIgnoreNextCollapse) {
+ mIgnoreNextCollapse = false;
+ return true;
+ }
+
mState.currentSearch = null;
onCurrentDirectoryChanged();
- return false;
+ return true;
}
});
@@ -343,11 +355,39 @@ public class DocumentsActivity extends Activity {
final MenuItem list = menu.findItem(R.id.menu_list);
final MenuItem settings = menu.findItem(R.id.menu_settings);
- grid.setVisible(mState.mode != MODE_GRID);
- list.setVisible(mState.mode != MODE_LIST);
+ // Open drawer means we hide most actions
+ if (mDrawerLayout.isDrawerOpen(mRootsContainer)) {
+ createDir.setVisible(false);
+ search.setVisible(false);
+ sort.setVisible(false);
+ grid.setVisible(false);
+ list.setVisible(false);
+ mIgnoreNextCollapse = true;
+ search.collapseActionView();
+ return true;
+ }
+
+ if (cwd != null) {
+ sort.setVisible(true);
+ grid.setVisible(mState.derivedMode != MODE_GRID);
+ list.setVisible(mState.derivedMode != MODE_LIST);
+ } else {
+ sort.setVisible(false);
+ grid.setVisible(false);
+ list.setVisible(false);
+ }
+
+ if (mState.currentSearch != null) {
+ // Search uses backend ranking; no sorting
+ sort.setVisible(false);
+
+ search.expandActionView();
+ mSearchView.setQuery(mState.currentSearch, false);
+ } else {
+ mIgnoreNextCollapse = true;
+ search.collapseActionView();
+ }
- // No sorting in recents
- sort.setVisible(cwd != null);
// Only sort by size when visible
sortSize.setVisible(mState.showSize);
@@ -392,28 +432,19 @@ public class DocumentsActivity extends Activity {
} else if (id == R.id.menu_search) {
return false;
} else if (id == R.id.menu_sort_name) {
- mState.sortOrder = State.SORT_ORDER_DISPLAY_NAME;
- updateDisplayState();
+ setUserSortOrder(State.SORT_ORDER_DISPLAY_NAME);
return true;
} else if (id == R.id.menu_sort_date) {
- mState.sortOrder = State.SORT_ORDER_LAST_MODIFIED;
- updateDisplayState();
+ setUserSortOrder(State.SORT_ORDER_LAST_MODIFIED);
return true;
} else if (id == R.id.menu_sort_size) {
- mState.sortOrder = State.SORT_ORDER_SIZE;
- updateDisplayState();
+ setUserSortOrder(State.SORT_ORDER_SIZE);
return true;
} else if (id == R.id.menu_grid) {
- // TODO: persist explicit user mode for cwd
- mState.mode = MODE_GRID;
- updateDisplayState();
- invalidateOptionsMenu();
+ setUserMode(State.MODE_GRID);
return true;
} else if (id == R.id.menu_list) {
- // TODO: persist explicit user mode for cwd
- mState.mode = MODE_LIST;
- updateDisplayState();
- invalidateOptionsMenu();
+ setUserMode(State.MODE_LIST);
return true;
} else if (id == R.id.menu_settings) {
startActivity(new Intent(this, SettingsActivity.class));
@@ -423,8 +454,36 @@ public class DocumentsActivity extends Activity {
}
}
+ /**
+ * Update UI to reflect internal state changes not from user.
+ */
+ public void onStateChanged() {
+ invalidateOptionsMenu();
+ }
+
+ /**
+ * Set state sort order based on explicit user action.
+ */
+ private void setUserSortOrder(int sortOrder) {
+ mState.userSortOrder = sortOrder;
+ DirectoryFragment.get(getFragmentManager()).onUserSortOrderChanged();
+ }
+
+ /**
+ * Set state mode based on explicit user action.
+ */
+ private void setUserMode(int mode) {
+ mState.userMode = mode;
+ DirectoryFragment.get(getFragmentManager()).onUserModeChanged();
+ }
+
@Override
public void onBackPressed() {
+ if (!mState.stackTouched) {
+ super.onBackPressed();
+ return;
+ }
+
final int size = mState.stack.size();
if (size > 1) {
mState.stack.pop();
@@ -520,6 +579,7 @@ public class DocumentsActivity extends Activity {
}
while (mState.stack.size() > itemPosition + 1) {
+ mState.stackTouched = true;
mState.stack.pop();
}
onCurrentDirectoryChanged();
@@ -528,8 +588,8 @@ public class DocumentsActivity extends Activity {
};
public RootInfo getCurrentRoot() {
- if (mState.stack.size() > 0) {
- return mState.stack.getRoot(mRoots);
+ if (mState.stack.root != null) {
+ return mState.stack.root;
} else {
return mRoots.getRecentsRoot();
}
@@ -545,6 +605,7 @@ public class DocumentsActivity extends Activity {
private void onCurrentDirectoryChanged() {
final FragmentManager fm = getFragmentManager();
+ final RootInfo root = getCurrentRoot();
final DocumentInfo cwd = getCurrentDirectory();
if (cwd == null) {
@@ -557,10 +618,10 @@ public class DocumentsActivity extends Activity {
} else {
if (mState.currentSearch != null) {
// Ongoing search
- DirectoryFragment.showSearch(fm, cwd.uri, mState.currentSearch);
+ DirectoryFragment.showSearch(fm, root, cwd, mState.currentSearch);
} else {
// Normal boring directory
- DirectoryFragment.showNormal(fm, cwd.uri);
+ DirectoryFragment.showNormal(fm, root, cwd);
}
}
@@ -582,19 +643,17 @@ public class DocumentsActivity extends Activity {
dumpStack();
}
- private void updateDisplayState() {
- // TODO: handle multiple directory stacks on tablets
- DirectoryFragment.get(getFragmentManager()).updateDisplayState();
- }
-
public void onStackPicked(DocumentStack stack) {
mState.stack = stack;
+ mState.stackTouched = true;
onCurrentDirectoryChanged();
}
public void onRootPicked(RootInfo root, boolean closeDrawer) {
// Clear entire backstack and start in new root
+ mState.stack.root = root;
mState.stack.clear();
+ mState.stackTouched = true;
if (!mRoots.isRecentsRoot(root)) {
try {
@@ -623,17 +682,12 @@ public class DocumentsActivity extends Activity {
public void onDocumentPicked(DocumentInfo doc) {
final FragmentManager fm = getFragmentManager();
if (doc.isDirectory()) {
- // TODO: query display mode user preference for this dir
- if (doc.isGridPreferred()) {
- mState.mode = MODE_GRID;
- } else {
- mState.mode = MODE_LIST;
- }
mState.stack.push(doc);
+ mState.stackTouched = true;
onCurrentDirectoryChanged();
} else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
// Explicit file picked, return
- onFinished(doc.uri);
+ onFinished(doc.derivedUri);
} else if (mState.action == ACTION_CREATE) {
// Replace selected file
SaveFragment.get(fm).setReplaceTarget(doc);
@@ -641,7 +695,7 @@ public class DocumentsActivity extends Activity {
// First try managing the document; we expect manager to filter
// based on authority, so we don't grant.
final Intent manage = new Intent(DocumentsContract.ACTION_MANAGE_DOCUMENT);
- manage.setData(doc.uri);
+ manage.setData(doc.derivedUri);
try {
startActivity(manage);
@@ -649,7 +703,7 @@ public class DocumentsActivity extends Activity {
// Fall back to viewing
final Intent view = new Intent(Intent.ACTION_VIEW);
view.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- view.setData(doc.uri);
+ view.setData(doc.derivedUri);
try {
startActivity(view);
@@ -665,22 +719,21 @@ public class DocumentsActivity extends Activity {
final int size = docs.size();
final Uri[] uris = new Uri[size];
for (int i = 0; i < size; i++) {
- uris[i] = docs.get(i).uri;
+ uris[i] = docs.get(i).derivedUri;
}
onFinished(uris);
}
}
public void onSaveRequested(DocumentInfo replaceTarget) {
- onFinished(replaceTarget.uri);
+ onFinished(replaceTarget.derivedUri);
}
public void onSaveRequested(String mimeType, String displayName) {
final DocumentInfo cwd = getCurrentDirectory();
- final String authority = cwd.uri.getAuthority();
final Uri childUri = DocumentsContract.createDocument(
- getContentResolver(), cwd.uri, mimeType, displayName);
+ getContentResolver(), cwd.derivedUri, mimeType, displayName);
if (childUri != null) {
onFinished(childUri);
} else {
@@ -698,22 +751,14 @@ public class DocumentsActivity extends Activity {
if (mState.action == ACTION_CREATE) {
// Remember stack for last create
values.clear();
- values.put(RecentsProvider.COL_PATH, rawStack);
- resolver.insert(RecentsProvider.buildRecentCreate(), values);
-
- } else if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
- // Remember opened items
- for (Uri uri : uris) {
- values.clear();
- values.put(RecentsProvider.COL_URI, uri.toString());
- resolver.insert(RecentsProvider.buildRecentOpen(), values);
- }
+ values.put(RecentColumns.STACK, rawStack);
+ resolver.insert(RecentsProvider.buildRecent(), values);
}
// Remember location for next app launch
final String packageName = getCallingPackage();
values.clear();
- values.put(RecentsProvider.COL_PATH, rawStack);
+ values.put(ResumeColumns.STACK, rawStack);
resolver.insert(RecentsProvider.buildResume(packageName), values);
final Intent intent = new Intent();
@@ -742,13 +787,23 @@ public class DocumentsActivity extends Activity {
public static class State implements android.os.Parcelable {
public int action;
- public int mode = MODE_LIST;
public String[] acceptMimes;
- public int sortOrder = SORT_ORDER_DISPLAY_NAME;
+
+ /** Explicit user choice */
+ public int userMode = MODE_UNKNOWN;
+ /** Derived after loader */
+ public int derivedMode = MODE_LIST;
+
+ /** Explicit user choice */
+ public int userSortOrder = SORT_ORDER_UNKNOWN;
+ /** Derived after loader */
+ public int derivedSortOrder = SORT_ORDER_DISPLAY_NAME;
+
public boolean allowMultiple = false;
public boolean showSize = false;
public boolean localOnly = false;
public boolean showAdvanced = false;
+ public boolean stackTouched = false;
/** Current user navigation stack; empty implies recents. */
public DocumentStack stack = new DocumentStack();
@@ -760,12 +815,14 @@ public class DocumentsActivity extends Activity {
public static final int ACTION_GET_CONTENT = 3;
public static final int ACTION_MANAGE = 4;
- public static final int MODE_LIST = 0;
- public static final int MODE_GRID = 1;
+ public static final int MODE_UNKNOWN = 0;
+ public static final int MODE_LIST = 1;
+ public static final int MODE_GRID = 2;
- public static final int SORT_ORDER_DISPLAY_NAME = 0;
- public static final int SORT_ORDER_LAST_MODIFIED = 1;
- public static final int SORT_ORDER_SIZE = 2;
+ public static final int SORT_ORDER_UNKNOWN = 0;
+ public static final int SORT_ORDER_DISPLAY_NAME = 1;
+ public static final int SORT_ORDER_LAST_MODIFIED = 2;
+ public static final int SORT_ORDER_SIZE = 3;
@Override
public int describeContents() {
@@ -775,13 +832,14 @@ public class DocumentsActivity extends Activity {
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeInt(action);
- out.writeInt(mode);
+ out.writeInt(userMode);
out.writeStringArray(acceptMimes);
- out.writeInt(sortOrder);
+ out.writeInt(userSortOrder);
out.writeInt(allowMultiple ? 1 : 0);
out.writeInt(showSize ? 1 : 0);
out.writeInt(localOnly ? 1 : 0);
out.writeInt(showAdvanced ? 1 : 0);
+ out.writeInt(stackTouched ? 1 : 0);
DurableUtils.writeToParcel(out, stack);
out.writeString(currentSearch);
}
@@ -791,13 +849,14 @@ public class DocumentsActivity extends Activity {
public State createFromParcel(Parcel in) {
final State state = new State();
state.action = in.readInt();
- state.mode = in.readInt();
+ state.userMode = in.readInt();
state.acceptMimes = in.readStringArray();
- state.sortOrder = in.readInt();
+ state.userSortOrder = in.readInt();
state.allowMultiple = in.readInt() != 0;
state.showSize = in.readInt() != 0;
state.localOnly = in.readInt() != 0;
state.showAdvanced = in.readInt() != 0;
+ state.stackTouched = in.readInt() != 0;
DurableUtils.readFromParcel(in, state.stack);
state.currentSearch = in.readString();
return state;
@@ -811,9 +870,10 @@ public class DocumentsActivity extends Activity {
}
private void dumpStack() {
- Log.d(TAG, "Current stack:");
+ Log.d(TAG, "Current stack: ");
+ Log.d(TAG, " * " + mState.stack.root);
for (DocumentInfo doc : mState.stack) {
- Log.d(TAG, "--> " + doc);
+ Log.d(TAG, " +-- " + doc);
}
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
index 0a6cbc0d4860..180ddefa9c01 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsApplication.java
@@ -56,7 +56,11 @@ public class DocumentsApplication extends Application {
packageFilter.addAction(Intent.ACTION_PACKAGE_CHANGED);
packageFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
packageFilter.addDataScheme("package");
- registerReceiver(mPackageReceiver, packageFilter);
+ registerReceiver(mCacheReceiver, packageFilter);
+
+ final IntentFilter localeFilter = new IntentFilter();
+ localeFilter.addAction(Intent.ACTION_LOCALE_CHANGED);
+ registerReceiver(mCacheReceiver, localeFilter);
}
@Override
@@ -70,7 +74,7 @@ public class DocumentsApplication extends Application {
}
}
- private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
+ private BroadcastReceiver mCacheReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// TODO: narrow changed/removed to only packages that have backends
diff --git a/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
new file mode 100644
index 000000000000..5f56963ae463
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/FilteringCursorWrapper.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2013 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.documentsui;
+
+import static com.android.documentsui.DocumentsActivity.TAG;
+
+import android.database.AbstractCursor;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.provider.DocumentsContract.Document;
+import android.util.Log;
+
+/**
+ * Cursor wrapper that filters MIME types not matching given list.
+ */
+public class FilteringCursorWrapper extends AbstractCursor {
+ private final Cursor mCursor;
+
+ private final int[] mPosition;
+ private int mCount;
+
+ public FilteringCursorWrapper(Cursor cursor, String[] acceptMimes) {
+ this(cursor, acceptMimes, null);
+ }
+
+ public FilteringCursorWrapper(Cursor cursor, String[] acceptMimes, String[] rejectMimes) {
+ mCursor = cursor;
+
+ final int count = cursor.getCount();
+ mPosition = new int[count];
+
+ cursor.moveToPosition(-1);
+ while (cursor.moveToNext()) {
+ final String mimeType = cursor.getString(
+ cursor.getColumnIndex(Document.COLUMN_MIME_TYPE));
+ if (rejectMimes != null && MimePredicate.mimeMatches(rejectMimes, mimeType)) {
+ continue;
+ }
+ if (MimePredicate.mimeMatches(acceptMimes, mimeType)) {
+ mPosition[mCount++] = cursor.getPosition();
+ }
+ }
+
+ Log.d(TAG, "Before filtering " + cursor.getCount() + ", after " + mCount);
+ }
+
+ @Override
+ public Bundle getExtras() {
+ return mCursor.getExtras();
+ }
+
+ @Override
+ public void close() {
+ super.close();
+ mCursor.close();
+ }
+
+ @Override
+ public boolean onMove(int oldPosition, int newPosition) {
+ return mCursor.moveToPosition(mPosition[newPosition]);
+ }
+
+ @Override
+ public String[] getColumnNames() {
+ return mCursor.getColumnNames();
+ }
+
+ @Override
+ public int getCount() {
+ return mCount;
+ }
+
+ @Override
+ public double getDouble(int column) {
+ return mCursor.getDouble(column);
+ }
+
+ @Override
+ public float getFloat(int column) {
+ return mCursor.getFloat(column);
+ }
+
+ @Override
+ public int getInt(int column) {
+ return mCursor.getInt(column);
+ }
+
+ @Override
+ public long getLong(int column) {
+ return mCursor.getLong(column);
+ }
+
+ @Override
+ public short getShort(int column) {
+ return mCursor.getShort(column);
+ }
+
+ @Override
+ public String getString(int column) {
+ return mCursor.getString(column);
+ }
+
+ @Override
+ public int getType(int column) {
+ return mCursor.getType(column);
+ }
+
+ @Override
+ public boolean isNull(int column) {
+ return mCursor.isNull(column);
+ }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
index 85d0988514c0..b55ce820f25e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/MimePredicate.java
@@ -49,6 +49,18 @@ public class MimePredicate implements Predicate<DocumentInfo> {
return false;
}
+ public static boolean mimeMatches(String filter, String[] tests) {
+ if (tests == null) {
+ return true;
+ }
+ for (String test : tests) {
+ if (mimeMatches(filter, test)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
public static boolean mimeMatches(String[] filters, String test) {
if (filters == null) {
return true;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
index 756a29796039..57442a030697 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentLoader.java
@@ -17,6 +17,9 @@
package com.android.documentsui;
import static com.android.documentsui.DocumentsActivity.TAG;
+import static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
+import static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
+import static com.android.documentsui.DocumentsActivity.State.SORT_ORDER_LAST_MODIFIED;
import android.content.AsyncTaskLoader;
import android.content.ContentProviderClient;
@@ -79,6 +82,7 @@ public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
}
private final List<RootInfo> mRoots;
+ private final String[] mAcceptMimes;
private final HashMap<RootInfo, RecentTask> mTasks = Maps.newHashMap();
@@ -135,9 +139,10 @@ public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
}
}
- public RecentLoader(Context context, List<RootInfo> roots) {
+ public RecentLoader(Context context, List<RootInfo> roots, String[] acceptMimes) {
super(context);
mRoots = roots;
+ mAcceptMimes = acceptMimes;
}
@Override
@@ -171,7 +176,15 @@ public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
for (RecentTask task : mTasks.values()) {
if (task.isDone()) {
try {
- cursors.add(task.get());
+ final Cursor cursor = task.get();
+ final FilteringCursorWrapper filtered = new FilteringCursorWrapper(
+ cursor, mAcceptMimes) {
+ @Override
+ public void close() {
+ // Ignored, since we manage cursor lifecycle internally
+ }
+ };
+ cursors.add(filtered);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
@@ -181,15 +194,14 @@ public class RecentLoader extends AsyncTaskLoader<DirectoryResult> {
}
final DirectoryResult result = new DirectoryResult();
+
+ final boolean acceptImages = MimePredicate.mimeMatches("image/*", mAcceptMimes);
+ result.mode = acceptImages ? MODE_GRID : MODE_LIST;
+ result.sortOrder = SORT_ORDER_LAST_MODIFIED;
+
if (cursors.size() > 0) {
final MergeCursor merged = new MergeCursor(cursors.toArray(new Cursor[cursors.size()]));
- final SortingCursorWrapper sorted = new SortingCursorWrapper(
- merged, State.SORT_ORDER_LAST_MODIFIED) {
- @Override
- public void close() {
- // Ignored, since we manage cursor lifecycle internally
- }
- };
+ final SortingCursorWrapper sorted = new SortingCursorWrapper(merged, result.sortOrder);
result.cursor = sorted;
}
return result;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
index 461c4151936a..140373b0c9eb 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsCreateFragment.java
@@ -26,10 +26,14 @@ import android.content.ContentResolver;
import android.content.Context;
import android.content.Loader;
import android.database.Cursor;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.os.CancellationSignal;
+import android.text.Spannable;
+import android.text.SpannableStringBuilder;
import android.text.TextUtils.TruncateAt;
+import android.text.style.ImageSpan;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
@@ -41,8 +45,8 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
+import com.android.documentsui.RecentsProvider.RecentColumns;
import com.android.documentsui.model.DocumentStack;
-import com.android.documentsui.model.RootInfo;
import com.google.android.collect.Lists;
import libcore.io.IoUtils;
@@ -128,7 +132,7 @@ public class RecentsCreateFragment extends Fragment {
public static class RecentsCreateLoader extends UriDerivativeLoader<Uri, List<DocumentStack>> {
public RecentsCreateLoader(Context context) {
- super(context, RecentsProvider.buildRecentCreate());
+ super(context, RecentsProvider.buildRecent());
}
@Override
@@ -137,14 +141,14 @@ public class RecentsCreateFragment extends Fragment {
final ContentResolver resolver = getContext().getContentResolver();
final Cursor cursor = resolver.query(
- uri, null, null, null, RecentsProvider.COL_TIMESTAMP + " DESC", signal);
+ uri, null, null, null, RecentColumns.TIMESTAMP + " DESC", signal);
try {
while (cursor != null && cursor.moveToNext()) {
- final byte[] raw = cursor.getBlob(
- cursor.getColumnIndex(RecentsProvider.COL_PATH));
+ final byte[] rawStack = cursor.getBlob(
+ cursor.getColumnIndex(RecentColumns.STACK));
try {
final DocumentStack stack = new DocumentStack();
- stack.read(new DataInputStream(new ByteArrayInputStream(raw)));
+ stack.read(new DataInputStream(new ByteArrayInputStream(rawStack)));
result.add(stack);
} catch (IOException e) {
Log.w(TAG, "Failed to resolve stack: " + e);
@@ -179,23 +183,31 @@ public class RecentsCreateFragment extends Fragment {
convertView = inflater.inflate(R.layout.item_doc_list, parent, false);
}
- final ImageView icon = (ImageView) convertView.findViewById(android.R.id.icon);
+ final ImageView iconMime = (ImageView) convertView.findViewById(R.id.icon_mime);
final TextView title = (TextView) convertView.findViewById(android.R.id.title);
+ final View line2 = convertView.findViewById(R.id.line2);
final DocumentStack stack = getItem(position);
- final RootInfo root = stack.getRoot(roots);
- icon.setImageDrawable(root.loadIcon(context));
+ iconMime.setImageDrawable(stack.root.loadIcon(context));
- final StringBuilder builder = new StringBuilder();
- for (int i = stack.size() - 1; i >= 0; i--) {
+ final Drawable crumb = context.getResources()
+ .getDrawable(R.drawable.ic_breadcrumb_arrow);
+ crumb.setBounds(0, 0, crumb.getIntrinsicWidth(), crumb.getIntrinsicHeight());
+
+ final SpannableStringBuilder builder = new SpannableStringBuilder();
+ builder.append(stack.root.title);
+ appendDrawable(builder, crumb);
+ for (int i = stack.size() - 2; i >= 0; i--) {
builder.append(stack.get(i).displayName);
if (i > 0) {
- builder.append(" \u232a ");
+ appendDrawable(builder, crumb);
}
}
- title.setText(builder.toString());
+ title.setText(builder);
title.setEllipsize(TruncateAt.MIDDLE);
+ line2.setVisibility(View.GONE);
+
return convertView;
}
@@ -214,4 +226,10 @@ public class RecentsCreateFragment extends Fragment {
return getItem(position).hashCode();
}
}
+
+ private static void appendDrawable(SpannableStringBuilder b, Drawable d) {
+ final int length = b.length();
+ b.append("\u232a");
+ b.setSpan(new ImageSpan(d), length, b.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
index 0c87783673a9..af79c9364122 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RecentsProvider.java
@@ -25,51 +25,64 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
+import android.provider.DocumentsContract.Document;
+import android.provider.DocumentsContract.Root;
import android.text.format.DateUtils;
import android.util.Log;
public class RecentsProvider extends ContentProvider {
private static final String TAG = "RecentsProvider";
- // TODO: offer view of recents that handles backend root resolution before
- // returning cursor, include extra columns
+ public static final long MAX_HISTORY_IN_MILLIS = DateUtils.DAY_IN_MILLIS * 45;
- public static final String AUTHORITY = "com.android.documentsui.recents";
+ private static final String AUTHORITY = "com.android.documentsui.recents";
private static final UriMatcher sMatcher = new UriMatcher(UriMatcher.NO_MATCH);
- private static final int URI_RECENT_OPEN = 1;
- private static final int URI_RECENT_CREATE = 2;
+ private static final int URI_RECENT = 1;
+ private static final int URI_STATE = 2;
private static final int URI_RESUME = 3;
static {
- sMatcher.addURI(AUTHORITY, "recent_open", URI_RECENT_OPEN);
- sMatcher.addURI(AUTHORITY, "recent_create", URI_RECENT_CREATE);
+ sMatcher.addURI(AUTHORITY, "recent", URI_RECENT);
+ // state/authority/rootId/docId
+ sMatcher.addURI(AUTHORITY, "state/*/*/*", URI_STATE);
+ // resume/packageName
sMatcher.addURI(AUTHORITY, "resume/*", URI_RESUME);
}
- private static final String TABLE_RECENT_OPEN = "recent_open";
- private static final String TABLE_RECENT_CREATE = "recent_create";
- private static final String TABLE_RESUME = "resume";
-
- /**
- * String of URIs pointing at a storage backend, stored as a JSON array,
- * starting with root.
- */
- public static final String COL_PATH = "path";
- public static final String COL_URI = "uri";
- public static final String COL_PACKAGE_NAME = "package_name";
- public static final String COL_TIMESTAMP = "timestamp";
-
- @Deprecated
- public static Uri buildRecentOpen() {
- return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
- .authority(AUTHORITY).appendPath("recent_open").build();
+ public static final String TABLE_RECENT = "recent";
+ public static final String TABLE_STATE = "state";
+ public static final String TABLE_RESUME = "resume";
+
+ public static class RecentColumns {
+ public static final String STACK = "stack";
+ public static final String TIMESTAMP = "timestamp";
+ }
+
+ public static class StateColumns {
+ public static final String AUTHORITY = "authority";
+ public static final String ROOT_ID = Root.COLUMN_ROOT_ID;
+ public static final String DOCUMENT_ID = Document.COLUMN_DOCUMENT_ID;
+ public static final String MODE = "mode";
+ public static final String SORT_ORDER = "sortOrder";
}
- public static Uri buildRecentCreate() {
+ public static class ResumeColumns {
+ public static final String PACKAGE_NAME = "package_name";
+ public static final String STACK = "stack";
+ public static final String TIMESTAMP = "timestamp";
+ }
+
+ public static Uri buildRecent() {
return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
- .authority(AUTHORITY).appendPath("recent_create").build();
+ .authority(AUTHORITY).appendPath("recent").build();
+ }
+
+ public static Uri buildState(String authority, String rootId, String documentId) {
+ return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
+ .appendPath("state").appendPath(authority).appendPath(rootId).appendPath(documentId)
+ .build();
}
public static Uri buildResume(String packageName) {
@@ -83,35 +96,42 @@ public class RecentsProvider extends ContentProvider {
private static final String DB_NAME = "recents.db";
private static final int VERSION_INIT = 1;
+ private static final int VERSION_AS_BLOB = 3;
public DatabaseHelper(Context context) {
- super(context, DB_NAME, null, VERSION_INIT);
+ super(context, DB_NAME, null, VERSION_AS_BLOB);
}
@Override
public void onCreate(SQLiteDatabase db) {
- db.execSQL("CREATE TABLE " + TABLE_RECENT_OPEN + " (" +
- COL_URI + " TEXT PRIMARY KEY ON CONFLICT REPLACE," +
- COL_TIMESTAMP + " INTEGER" +
+
+ db.execSQL("CREATE TABLE " + TABLE_RECENT + " (" +
+ RecentColumns.STACK + " BLOB PRIMARY KEY ON CONFLICT REPLACE," +
+ RecentColumns.TIMESTAMP + " INTEGER" +
")");
- db.execSQL("CREATE TABLE " + TABLE_RECENT_CREATE + " (" +
- COL_PATH + " TEXT PRIMARY KEY ON CONFLICT REPLACE," +
- COL_TIMESTAMP + " INTEGER" +
+ db.execSQL("CREATE TABLE " + TABLE_STATE + " (" +
+ StateColumns.AUTHORITY + " TEXT," +
+ StateColumns.ROOT_ID + " TEXT," +
+ StateColumns.DOCUMENT_ID + " TEXT," +
+ StateColumns.MODE + " INTEGER," +
+ StateColumns.SORT_ORDER + " INTEGER," +
+ "PRIMARY KEY (" + StateColumns.AUTHORITY + ", " + StateColumns.ROOT_ID + ", "
+ + StateColumns.DOCUMENT_ID + ")" +
")");
db.execSQL("CREATE TABLE " + TABLE_RESUME + " (" +
- COL_PACKAGE_NAME + " TEXT PRIMARY KEY ON CONFLICT REPLACE," +
- COL_PATH + " TEXT," +
- COL_TIMESTAMP + " INTEGER" +
+ ResumeColumns.PACKAGE_NAME + " TEXT PRIMARY KEY ON CONFLICT REPLACE," +
+ ResumeColumns.STACK + " BLOB," +
+ ResumeColumns.TIMESTAMP + " INTEGER" +
")");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.w(TAG, "Upgrading database; wiping app data");
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECENT_OPEN);
- db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECENT_CREATE);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_RECENT);
+ db.execSQL("DROP TABLE IF EXISTS " + TABLE_STATE);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_RESUME);
onCreate(db);
}
@@ -128,22 +148,23 @@ public class RecentsProvider extends ContentProvider {
String sortOrder) {
final SQLiteDatabase db = mHelper.getReadableDatabase();
switch (sMatcher.match(uri)) {
- case URI_RECENT_OPEN: {
- return db.query(TABLE_RECENT_OPEN, projection,
- buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null);
- }
- case URI_RECENT_CREATE: {
- return db.query(TABLE_RECENT_CREATE, projection,
- buildWhereYounger(DateUtils.WEEK_IN_MILLIS), null, null, null, null);
- }
- case URI_RESUME: {
+ case URI_RECENT:
+ final long cutoff = System.currentTimeMillis() - MAX_HISTORY_IN_MILLIS;
+ return db.query(TABLE_RECENT, projection, RecentColumns.TIMESTAMP + ">" + cutoff,
+ null, null, null, sortOrder);
+ case URI_STATE:
+ final String authority = uri.getPathSegments().get(1);
+ final String rootId = uri.getPathSegments().get(2);
+ final String documentId = uri.getPathSegments().get(3);
+ return db.query(TABLE_STATE, projection, StateColumns.AUTHORITY + "=? AND "
+ + StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
+ new String[] { authority, rootId, documentId }, null, null, sortOrder);
+ case URI_RESUME:
final String packageName = uri.getPathSegments().get(1);
- return db.query(TABLE_RESUME, projection, COL_PACKAGE_NAME + "=?",
- new String[] { packageName }, null, null, null);
- }
- default: {
+ return db.query(TABLE_RESUME, projection, ResumeColumns.PACKAGE_NAME + "=?",
+ new String[] { packageName }, null, null, sortOrder);
+ default:
throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
}
}
@@ -156,28 +177,37 @@ public class RecentsProvider extends ContentProvider {
public Uri insert(Uri uri, ContentValues values) {
final SQLiteDatabase db = mHelper.getWritableDatabase();
switch (sMatcher.match(uri)) {
- case URI_RECENT_OPEN: {
- values.put(COL_TIMESTAMP, System.currentTimeMillis());
- db.insert(TABLE_RECENT_OPEN, null, values);
- db.delete(TABLE_RECENT_OPEN, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null);
+ case URI_RECENT:
+ values.put(RecentColumns.TIMESTAMP, System.currentTimeMillis());
+ db.insert(TABLE_RECENT, null, values);
+ final long cutoff = System.currentTimeMillis() - MAX_HISTORY_IN_MILLIS;
+ db.delete(TABLE_RECENT, RecentColumns.TIMESTAMP + "<" + cutoff, null);
return uri;
- }
- case URI_RECENT_CREATE: {
- values.put(COL_TIMESTAMP, System.currentTimeMillis());
- db.insert(TABLE_RECENT_CREATE, null, values);
- db.delete(TABLE_RECENT_CREATE, buildWhereOlder(DateUtils.WEEK_IN_MILLIS), null);
+ case URI_STATE:
+ final String authority = uri.getPathSegments().get(1);
+ final String rootId = uri.getPathSegments().get(2);
+ final String documentId = uri.getPathSegments().get(3);
+
+ final ContentValues key = new ContentValues();
+ key.put(StateColumns.AUTHORITY, authority);
+ key.put(StateColumns.ROOT_ID, rootId);
+ key.put(StateColumns.DOCUMENT_ID, documentId);
+
+ // Ensure that row exists, then update with changed values
+ db.insertWithOnConflict(TABLE_STATE, null, key, SQLiteDatabase.CONFLICT_IGNORE);
+ db.update(TABLE_STATE, values, StateColumns.AUTHORITY + "=? AND "
+ + StateColumns.ROOT_ID + "=? AND " + StateColumns.DOCUMENT_ID + "=?",
+ new String[] { authority, rootId, documentId });
+
return uri;
- }
- case URI_RESUME: {
+ case URI_RESUME:
final String packageName = uri.getPathSegments().get(1);
- values.put(COL_PACKAGE_NAME, packageName);
- values.put(COL_TIMESTAMP, System.currentTimeMillis());
+ values.put(ResumeColumns.PACKAGE_NAME, packageName);
+ values.put(ResumeColumns.TIMESTAMP, System.currentTimeMillis());
db.insert(TABLE_RESUME, null, values);
return uri;
- }
- default: {
+ default:
throw new UnsupportedOperationException("Unsupported Uri " + uri);
- }
}
}
@@ -190,12 +220,4 @@ public class RecentsProvider extends ContentProvider {
public int delete(Uri uri, String selection, String[] selectionArgs) {
throw new UnsupportedOperationException("Unsupported Uri " + uri);
}
-
- private static String buildWhereOlder(long deltaMillis) {
- return COL_TIMESTAMP + "<" + (System.currentTimeMillis() - deltaMillis);
- }
-
- private static String buildWhereYounger(long deltaMillis) {
- return COL_TIMESTAMP + ">" + (System.currentTimeMillis() - deltaMillis);
- }
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index d4f1b393f525..b48674cff9c5 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -90,7 +90,6 @@ public class RootsCache {
if (info.metaData != null && info.metaData.containsKey(
DocumentsContract.META_DATA_DOCUMENT_PROVIDER)) {
- // TODO: remove deprecated customRoots flag
// TODO: populate roots on background thread, and cache results
final Uri rootsUri = DocumentsContract.buildRootsUri(info.authority);
final ContentProviderClient client = resolver
@@ -110,6 +109,8 @@ public class RootsCache {
}
}
}
+
+ Log.d(TAG, "Update found " + mRoots.size() + " roots");
}
@Deprecated
@@ -135,6 +136,21 @@ public class RootsCache {
}
@GuardedBy("ActivityThread")
+ public boolean isIconUnique(RootInfo root) {
+ for (RootInfo test : mRoots) {
+ if (Objects.equal(test.authority, root.authority)) {
+ if (Objects.equal(test.rootId, root.rootId)) {
+ continue;
+ }
+ if (test.icon == root.icon) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ @GuardedBy("ActivityThread")
public RootInfo getRecentsRoot() {
return mRecentsRoot;
}
@@ -169,8 +185,9 @@ public class RootsCache {
if (state.localOnly && !localOnly) continue;
// Only include roots that serve requested content
- final boolean overlap = MimePredicate.mimeMatches(root.mimeTypes, state.acceptMimes)
- || MimePredicate.mimeMatches(state.acceptMimes, root.mimeTypes);
+ final boolean overlap =
+ MimePredicate.mimeMatches(root.derivedMimeTypes, state.acceptMimes) ||
+ MimePredicate.mimeMatches(state.acceptMimes, root.derivedMimeTypes);
if (!overlap) {
continue;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
index efb972d44c0a..f3a21c657f6e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsFragment.java
@@ -25,6 +25,7 @@ import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.provider.DocumentsContract.Root;
+import android.text.TextUtils;
import android.text.format.Formatter;
import android.view.LayoutInflater;
import android.view.View;
@@ -168,7 +169,7 @@ public class RootsFragment extends Fragment {
}
summary.setText(summaryText);
- summary.setVisibility(summaryText != null ? View.VISIBLE : View.GONE);
+ summary.setVisibility(TextUtils.isEmpty(summaryText) ? View.GONE : View.VISIBLE);
return convertView;
}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
index a1489a53b4f8..c69103ef5d7e 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentInfo.java
@@ -20,6 +20,8 @@ import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.provider.DocumentsContract;
import android.provider.DocumentsContract.Document;
@@ -32,15 +34,16 @@ import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ProtocolException;
-import java.util.Comparator;
/**
* Representation of a {@link Document}.
*/
-public class DocumentInfo implements Durable {
+public class DocumentInfo implements Durable, Parcelable {
private static final int VERSION_INIT = 1;
+ private static final int VERSION_SPLIT_URI = 2;
- public Uri uri;
+ public String authority;
+ public String documentId;
public String mimeType;
public String displayName;
public long lastModified;
@@ -49,13 +52,17 @@ public class DocumentInfo implements Durable {
public long size;
public int icon;
+ /** Derived fields that aren't persisted */
+ public Uri derivedUri;
+
public DocumentInfo() {
reset();
}
@Override
public void reset() {
- uri = null;
+ authority = null;
+ documentId = null;
mimeType = null;
displayName = null;
lastModified = -1;
@@ -63,6 +70,8 @@ public class DocumentInfo implements Durable {
summary = null;
size = -1;
icon = 0;
+
+ derivedUri = null;
}
@Override
@@ -70,8 +79,10 @@ public class DocumentInfo implements Durable {
final int version = in.readInt();
switch (version) {
case VERSION_INIT:
- final String rawUri = DurableUtils.readNullableString(in);
- uri = rawUri != null ? Uri.parse(rawUri) : null;
+ throw new ProtocolException("Ignored upgrade");
+ case VERSION_SPLIT_URI:
+ authority = DurableUtils.readNullableString(in);
+ documentId = DurableUtils.readNullableString(in);
mimeType = DurableUtils.readNullableString(in);
displayName = DurableUtils.readNullableString(in);
lastModified = in.readLong();
@@ -79,6 +90,7 @@ public class DocumentInfo implements Durable {
summary = DurableUtils.readNullableString(in);
size = in.readLong();
icon = in.readInt();
+ deriveFields();
break;
default:
throw new ProtocolException("Unknown version " + version);
@@ -87,8 +99,9 @@ public class DocumentInfo implements Durable {
@Override
public void write(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_INIT);
- DurableUtils.writeNullableString(out, uri.toString());
+ out.writeInt(VERSION_SPLIT_URI);
+ DurableUtils.writeNullableString(out, authority);
+ DurableUtils.writeNullableString(out, documentId);
DurableUtils.writeNullableString(out, mimeType);
DurableUtils.writeNullableString(out, displayName);
out.writeLong(lastModified);
@@ -98,11 +111,41 @@ public class DocumentInfo implements Durable {
out.writeInt(icon);
}
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ DurableUtils.writeToParcel(dest, this);
+ }
+
+ public static final Creator<DocumentInfo> CREATOR = new Creator<DocumentInfo>() {
+ @Override
+ public DocumentInfo createFromParcel(Parcel in) {
+ final DocumentInfo doc = new DocumentInfo();
+ DurableUtils.readFromParcel(in, doc);
+ return doc;
+ }
+
+ @Override
+ public DocumentInfo[] newArray(int size) {
+ return new DocumentInfo[size];
+ }
+ };
+
public static DocumentInfo fromDirectoryCursor(Cursor cursor) {
- final DocumentInfo doc = new DocumentInfo();
final String authority = getCursorString(cursor, RootCursorWrapper.COLUMN_AUTHORITY);
- final String docId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
- doc.uri = DocumentsContract.buildDocumentUri(authority, docId);
+ return fromCursor(cursor, authority);
+ }
+
+ public static DocumentInfo fromCursor(Cursor cursor, String authority) {
+ final DocumentInfo doc = new DocumentInfo();
+ doc.authority = authority;
+ doc.documentId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
+ doc.mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
+ doc.documentId = getCursorString(cursor, Document.COLUMN_DOCUMENT_ID);
doc.mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
doc.displayName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
doc.lastModified = getCursorLong(cursor, Document.COLUMN_LAST_MODIFIED);
@@ -110,6 +153,7 @@ public class DocumentInfo implements Durable {
doc.summary = getCursorString(cursor, Document.COLUMN_SUMMARY);
doc.size = getCursorLong(cursor, Document.COLUMN_SIZE);
doc.icon = getCursorInt(cursor, Document.COLUMN_ICON);
+ doc.deriveFields();
return doc;
}
@@ -122,16 +166,7 @@ public class DocumentInfo implements Durable {
if (!cursor.moveToFirst()) {
throw new FileNotFoundException("Missing details for " + uri);
}
- final DocumentInfo doc = new DocumentInfo();
- doc.uri = uri;
- doc.mimeType = getCursorString(cursor, Document.COLUMN_MIME_TYPE);
- doc.displayName = getCursorString(cursor, Document.COLUMN_DISPLAY_NAME);
- doc.lastModified = getCursorLong(cursor, Document.COLUMN_LAST_MODIFIED);
- doc.flags = getCursorInt(cursor, Document.COLUMN_FLAGS);
- doc.summary = getCursorString(cursor, Document.COLUMN_SUMMARY);
- doc.size = getCursorLong(cursor, Document.COLUMN_SIZE);
- doc.icon = getCursorInt(cursor, Document.COLUMN_ICON);
- return doc;
+ return fromCursor(cursor, uri.getAuthority());
} catch (Throwable t) {
throw asFileNotFoundException(t);
} finally {
@@ -140,9 +175,13 @@ public class DocumentInfo implements Durable {
}
}
+ private void deriveFields() {
+ derivedUri = DocumentsContract.buildDocumentUri(authority, documentId);
+ }
+
@Override
public String toString() {
- return "Document{name=" + displayName + ", uri=" + uri + "}";
+ return "Document{name=" + displayName + ", docId=" + documentId + "}";
}
public boolean isCreateSupported() {
@@ -189,42 +228,14 @@ public class DocumentInfo implements Durable {
}
}
+ /**
+ * Missing or null values are returned as 0.
+ */
public static int getCursorInt(Cursor cursor, String columnName) {
final int index = cursor.getColumnIndex(columnName);
return (index != -1) ? cursor.getInt(index) : 0;
}
- @Deprecated
- public static class DisplayNameComparator implements Comparator<DocumentInfo> {
- @Override
- public int compare(DocumentInfo lhs, DocumentInfo rhs) {
- final boolean leftDir = lhs.isDirectory();
- final boolean rightDir = rhs.isDirectory();
-
- if (leftDir != rightDir) {
- return leftDir ? -1 : 1;
- } else {
- return compareToIgnoreCaseNullable(lhs.displayName, rhs.displayName);
- }
- }
- }
-
- @Deprecated
- public static class LastModifiedComparator implements Comparator<DocumentInfo> {
- @Override
- public int compare(DocumentInfo lhs, DocumentInfo rhs) {
- return Long.compare(rhs.lastModified, lhs.lastModified);
- }
- }
-
- @Deprecated
- public static class SizeComparator implements Comparator<DocumentInfo> {
- @Override
- public int compare(DocumentInfo lhs, DocumentInfo rhs) {
- return Long.compare(rhs.size, lhs.size);
- }
- }
-
public static FileNotFoundException asFileNotFoundException(Throwable t)
throws FileNotFoundException {
if (t instanceof FileNotFoundException) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java
index 33a1376e2144..254144065f8a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/DocumentStack.java
@@ -16,8 +16,6 @@
package com.android.documentsui.model;
-import com.android.documentsui.RootsCache;
-
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -30,14 +28,13 @@ import java.util.LinkedList;
*/
public class DocumentStack extends LinkedList<DocumentInfo> implements Durable {
private static final int VERSION_INIT = 1;
+ private static final int VERSION_ADD_ROOT = 2;
- public RootInfo getRoot(RootsCache roots) {
- return roots.findRoot(getLast().uri);
- }
+ public RootInfo root;
- public String getTitle(RootsCache roots) {
- if (size() == 1) {
- return getRoot(roots).title;
+ public String getTitle() {
+ if (size() == 1 && root != null) {
+ return root.title;
} else if (size() > 1) {
return peek().displayName;
} else {
@@ -52,6 +49,7 @@ public class DocumentStack extends LinkedList<DocumentInfo> implements Durable {
@Override
public void reset() {
clear();
+ root = null;
}
@Override
@@ -59,6 +57,12 @@ public class DocumentStack extends LinkedList<DocumentInfo> implements Durable {
final int version = in.readInt();
switch (version) {
case VERSION_INIT:
+ throw new ProtocolException("Ignored upgrade");
+ case VERSION_ADD_ROOT:
+ if (in.readBoolean()) {
+ root = new RootInfo();
+ root.read(in);
+ }
final int size = in.readInt();
for (int i = 0; i < size; i++) {
final DocumentInfo doc = new DocumentInfo();
@@ -73,7 +77,13 @@ public class DocumentStack extends LinkedList<DocumentInfo> implements Durable {
@Override
public void write(DataOutputStream out) throws IOException {
- out.writeInt(VERSION_INIT);
+ out.writeInt(VERSION_ADD_ROOT);
+ if (root != null) {
+ out.writeBoolean(true);
+ root.write(out);
+ } else {
+ out.writeBoolean(false);
+ }
final int size = size();
out.writeInt(size);
for (int i = 0; i < size; i++) {
diff --git a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
index a6ddf70d163d..b5a198cd9c9a 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/model/RootInfo.java
@@ -23,28 +23,122 @@ import static com.android.documentsui.model.DocumentInfo.getCursorString;
import android.content.Context;
import android.database.Cursor;
import android.graphics.drawable.Drawable;
+import android.os.Parcel;
+import android.os.Parcelable;
import android.provider.DocumentsContract.Root;
+import android.text.TextUtils;
import com.android.documentsui.IconUtils;
import com.android.documentsui.R;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.net.ProtocolException;
import java.util.Objects;
/**
* Representation of a {@link Root}.
*/
-public class RootInfo {
+public class RootInfo implements Durable, Parcelable {
+ private static final int VERSION_INIT = 1;
+
public String authority;
public String rootId;
public int rootType;
public int flags;
public int icon;
- public int localIcon;
public String title;
public String summary;
public String documentId;
public long availableBytes;
- public String[] mimeTypes;
+ public String mimeTypes;
+
+ /** Derived fields that aren't persisted */
+ public String[] derivedMimeTypes;
+ public int derivedIcon;
+
+ public RootInfo() {
+ reset();
+ }
+
+ @Override
+ public void reset() {
+ authority = null;
+ rootId = null;
+ rootType = 0;
+ flags = 0;
+ icon = 0;
+ title = null;
+ summary = null;
+ documentId = null;
+ availableBytes = -1;
+ mimeTypes = null;
+
+ derivedMimeTypes = null;
+ derivedIcon = 0;
+ }
+
+ @Override
+ public void read(DataInputStream in) throws IOException {
+ final int version = in.readInt();
+ switch (version) {
+ case VERSION_INIT:
+ authority = DurableUtils.readNullableString(in);
+ rootId = DurableUtils.readNullableString(in);
+ rootType = in.readInt();
+ flags = in.readInt();
+ icon = in.readInt();
+ title = DurableUtils.readNullableString(in);
+ summary = DurableUtils.readNullableString(in);
+ documentId = DurableUtils.readNullableString(in);
+ availableBytes = in.readLong();
+ mimeTypes = DurableUtils.readNullableString(in);
+ deriveFields();
+ break;
+ default:
+ throw new ProtocolException("Unknown version " + version);
+ }
+ }
+
+ @Override
+ public void write(DataOutputStream out) throws IOException {
+ out.writeInt(VERSION_INIT);
+ DurableUtils.writeNullableString(out, authority);
+ DurableUtils.writeNullableString(out, rootId);
+ out.writeInt(rootType);
+ out.writeInt(flags);
+ out.writeInt(icon);
+ DurableUtils.writeNullableString(out, title);
+ DurableUtils.writeNullableString(out, summary);
+ DurableUtils.writeNullableString(out, documentId);
+ out.writeLong(availableBytes);
+ DurableUtils.writeNullableString(out, mimeTypes);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {
+ DurableUtils.writeToParcel(dest, this);
+ }
+
+ public static final Creator<RootInfo> CREATOR = new Creator<RootInfo>() {
+ @Override
+ public RootInfo createFromParcel(Parcel in) {
+ final RootInfo root = new RootInfo();
+ DurableUtils.readFromParcel(in, root);
+ return root;
+ }
+
+ @Override
+ public RootInfo[] newArray(int size) {
+ return new RootInfo[size];
+ }
+ };
public static RootInfo fromRootsCursor(String authority, Cursor cursor) {
final RootInfo root = new RootInfo();
@@ -57,31 +151,38 @@ public class RootInfo {
root.summary = getCursorString(cursor, Root.COLUMN_SUMMARY);
root.documentId = getCursorString(cursor, Root.COLUMN_DOCUMENT_ID);
root.availableBytes = getCursorLong(cursor, Root.COLUMN_AVAILABLE_BYTES);
+ root.mimeTypes = getCursorString(cursor, Root.COLUMN_MIME_TYPES);
+ root.deriveFields();
+ return root;
+ }
- final String raw = getCursorString(cursor, Root.COLUMN_MIME_TYPES);
- root.mimeTypes = (raw != null) ? raw.split("\n") : null;
+ private void deriveFields() {
+ derivedMimeTypes = (mimeTypes != null) ? mimeTypes.split("\n") : null;
// TODO: remove these special case icons
if ("com.android.externalstorage.documents".equals(authority)) {
- root.localIcon = R.drawable.ic_root_sdcard;
+ derivedIcon = R.drawable.ic_root_sdcard;
}
if ("com.android.providers.downloads.documents".equals(authority)) {
- root.localIcon = R.drawable.ic_root_download;
+ derivedIcon = R.drawable.ic_root_download;
}
if ("com.android.providers.media.documents".equals(authority)) {
- if ("image".equals(root.rootId)) {
- root.localIcon = R.drawable.ic_doc_image;
- } else if ("audio".equals(root.rootId)) {
- root.localIcon = R.drawable.ic_doc_audio;
+ if ("image".equals(rootId)) {
+ derivedIcon = R.drawable.ic_doc_image;
+ } else if ("audio".equals(rootId)) {
+ derivedIcon = R.drawable.ic_doc_audio;
}
}
+ }
- return root;
+ @Override
+ public String toString() {
+ return "Root{title=" + title + ", rootId=" + rootId + "}";
}
public Drawable loadIcon(Context context) {
- if (localIcon != 0) {
- return context.getResources().getDrawable(localIcon);
+ if (derivedIcon != 0) {
+ return context.getResources().getDrawable(derivedIcon);
} else {
return IconUtils.loadPackageIcon(context, authority, icon);
}
@@ -103,6 +204,6 @@ public class RootInfo {
}
public String getDirectoryString() {
- return (summary != null) ? summary : title;
+ return !TextUtils.isEmpty(summary) ? summary : title;
}
}
diff --git a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
index f53e60dcfcaf..cdb6b3375377 100644
--- a/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
+++ b/packages/DocumentsUI/tests/src/com/android/documentsui/RootsCacheTest.java
@@ -30,7 +30,7 @@ public class RootsCacheTest extends AndroidTestCase {
private static RootInfo buildForMimeTypes(String... mimeTypes) {
final RootInfo root = new RootInfo();
- root.mimeTypes = mimeTypes;
+ root.derivedMimeTypes = mimeTypes;
return root;
}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 226d6351e96f..ada3ad721b40 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -181,12 +181,12 @@ public class ExternalStorageProvider extends DocumentsProvider {
}
final RowBuilder row = result.newRow();
- row.offer(Document.COLUMN_DOCUMENT_ID, docId);
- row.offer(Document.COLUMN_DISPLAY_NAME, displayName);
- row.offer(Document.COLUMN_SIZE, file.length());
- row.offer(Document.COLUMN_MIME_TYPE, mimeType);
- row.offer(Document.COLUMN_LAST_MODIFIED, file.lastModified());
- row.offer(Document.COLUMN_FLAGS, flags);
+ row.add(Document.COLUMN_DOCUMENT_ID, docId);
+ row.add(Document.COLUMN_DISPLAY_NAME, displayName);
+ row.add(Document.COLUMN_SIZE, file.length());
+ row.add(Document.COLUMN_MIME_TYPE, mimeType);
+ row.add(Document.COLUMN_LAST_MODIFIED, file.lastModified());
+ row.add(Document.COLUMN_FLAGS, flags);
}
@Override
@@ -197,13 +197,13 @@ public class ExternalStorageProvider extends DocumentsProvider {
final File path = mIdToPath.get(rootId);
final RowBuilder row = result.newRow();
- row.offer(Root.COLUMN_ROOT_ID, root.rootId);
- row.offer(Root.COLUMN_ROOT_TYPE, root.rootType);
- row.offer(Root.COLUMN_FLAGS, root.flags);
- row.offer(Root.COLUMN_ICON, root.icon);
- row.offer(Root.COLUMN_TITLE, root.title);
- row.offer(Root.COLUMN_DOCUMENT_ID, root.docId);
- row.offer(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
+ row.add(Root.COLUMN_ROOT_ID, root.rootId);
+ row.add(Root.COLUMN_ROOT_TYPE, root.rootType);
+ row.add(Root.COLUMN_FLAGS, root.flags);
+ row.add(Root.COLUMN_ICON, root.icon);
+ row.add(Root.COLUMN_TITLE, root.title);
+ row.add(Root.COLUMN_DOCUMENT_ID, root.docId);
+ row.add(Root.COLUMN_AVAILABLE_BYTES, path.getFreeSpace());
}
return result;
}
@@ -267,16 +267,15 @@ public class ExternalStorageProvider extends DocumentsProvider {
final LinkedList<File> pending = new LinkedList<File>();
pending.add(parent);
- while (!pending.isEmpty() && result.getCount() < 20) {
+ while (!pending.isEmpty() && result.getCount() < 24) {
final File file = pending.removeFirst();
if (file.isDirectory()) {
for (File child : file.listFiles()) {
pending.add(child);
}
- } else {
- if (file.getName().toLowerCase().contains(query)) {
- includeFile(result, null, file);
- }
+ }
+ if (file.getName().toLowerCase().contains(query)) {
+ includeFile(result, null, file);
}
}
return result;
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
index 872974fbfaf5..014c664d1feb 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/TestDocumentsProvider.java
@@ -69,13 +69,13 @@ public class TestDocumentsProvider extends DocumentsProvider {
final MatrixCursor result = new MatrixCursor(resolveRootProjection(projection));
final RowBuilder row = result.newRow();
- row.offer(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
- row.offer(Root.COLUMN_ROOT_TYPE, Root.ROOT_TYPE_SERVICE);
- row.offer(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
- row.offer(Root.COLUMN_TITLE, "_Test title which is really long");
- row.offer(Root.COLUMN_SUMMARY, "_Summary which is also super long text");
- row.offer(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
- row.offer(Root.COLUMN_AVAILABLE_BYTES, 1024);
+ row.add(Root.COLUMN_ROOT_ID, MY_ROOT_ID);
+ row.add(Root.COLUMN_ROOT_TYPE, Root.ROOT_TYPE_SERVICE);
+ row.add(Root.COLUMN_FLAGS, Root.FLAG_SUPPORTS_RECENTS);
+ row.add(Root.COLUMN_TITLE, "_Test title which is really long");
+ row.add(Root.COLUMN_SUMMARY, "_Summary which is also super long text");
+ row.add(Root.COLUMN_DOCUMENT_ID, MY_DOC_ID);
+ row.add(Root.COLUMN_AVAILABLE_BYTES, 1024);
return result;
}
@@ -125,6 +125,9 @@ public class TestDocumentsProvider extends DocumentsProvider {
includeFile(result, "_networkfile1");
includeFile(result, "_networkfile2");
includeFile(result, "_networkfile3");
+ includeFile(result, "_networkfile4");
+ includeFile(result, "_networkfile5");
+ includeFile(result, "_networkfile6");
return true;
} else {
return false;
@@ -162,6 +165,8 @@ public class TestDocumentsProvider extends DocumentsProvider {
includeFile(result, MY_DOC_NULL);
includeFile(result, "localfile1");
includeFile(result, "localfile2");
+ includeFile(result, "localfile3");
+ includeFile(result, "localfile4");
synchronized (this) {
// Try picking up an existing network fetch
@@ -229,16 +234,16 @@ public class TestDocumentsProvider extends DocumentsProvider {
private static void includeFile(MatrixCursor result, String docId) {
final RowBuilder row = result.newRow();
- row.offer(Document.COLUMN_DOCUMENT_ID, docId);
- row.offer(Document.COLUMN_DISPLAY_NAME, docId);
- row.offer(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
+ row.add(Document.COLUMN_DOCUMENT_ID, docId);
+ row.add(Document.COLUMN_DISPLAY_NAME, docId);
+ row.add(Document.COLUMN_LAST_MODIFIED, System.currentTimeMillis());
if (MY_DOC_ID.equals(docId)) {
- row.offer(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
+ row.add(Document.COLUMN_MIME_TYPE, Document.MIME_TYPE_DIR);
} else if (MY_DOC_NULL.equals(docId)) {
// No MIME type
} else {
- row.offer(Document.COLUMN_MIME_TYPE, "application/octet-stream");
+ row.add(Document.COLUMN_MIME_TYPE, "application/octet-stream");
}
}
}
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index d2c82c844835..7d77c48b5636 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -37,8 +37,6 @@
<uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW" />
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
- <!-- Permission to perform hotword recognition -->
- <uses-permission android:name="android.permission.HOTWORD_RECOGNITION" />
<application android:label="@string/app_name"
android:process="com.android.systemui"
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 78b842cd474c..fbe3a9c59e85 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -49,8 +49,6 @@ import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
-import android.speech.hotword.HotwordRecognitionListener;
-import android.speech.hotword.HotwordRecognizer;
import android.telephony.TelephonyManager;
import android.util.AttributeSet;
import android.util.Log;
@@ -68,10 +66,6 @@ import java.util.List;
public class KeyguardHostView extends KeyguardViewBase {
private static final String TAG = "KeyguardHostView";
- // Don't enable hotword on limited-memory devices.
- private static final boolean ENABLE_HOTWORD = !ActivityManager.isLowRamDeviceStatic();
- // Indicates if hotword is enabled, should it also be available on secure keyguard(s).
- private static final boolean ENABLE_HOTWORD_SECURE = false;
// Transport control states.
static final int TRANSPORT_GONE = 0;
@@ -87,13 +81,6 @@ public class KeyguardHostView extends KeyguardViewBase {
// Found in KeyguardAppWidgetPickActivity.java
static final int APPWIDGET_HOST_ID = 0x4B455947;
- // TODO: Fix this to be non-static.
- // We need to be careful here to make stopRecognition calls on the same instance
- // that started it. Since KeyguardHostView is a view, it keeps getting
- // recreated every now and then, and unless we figure out a better way,
- // this needs to be a static field.
- private static HotwordRecognizer sHotwordClient;
-
private final int MAX_WIDGETS = 5;
private AppWidgetHost mAppWidgetHost;
@@ -217,11 +204,6 @@ public class KeyguardHostView extends KeyguardViewBase {
if ((mDisabledFeatures & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0) {
Log.v(TAG, "Keyguard secure camera disabled by DPM");
}
-
- // Create Hotword recognizer, for the first time.
- if (ENABLE_HOTWORD && sHotwordClient == null) {
- sHotwordClient = HotwordRecognizer.createHotwordRecognizer(getContext());
- }
}
private void getInitialTransportState() {
@@ -319,21 +301,6 @@ public class KeyguardHostView extends KeyguardViewBase {
}
}
}
- @Override
- public void onPhoneStateChanged(int phoneState) {
- // We need to stop hotword detection when a call state is not idle anymore.
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)
- && TelephonyManager.CALL_STATE_IDLE != phoneState) {
- if (DEBUG) Log.d(TAG, "Stopping due to call state not being idle");
- maybeStopHotwordDetector();
- }
- }
- @Override
- public void onUserSwitching(int userId) {
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)) {
- maybeStopHotwordDetector();
- }
- }
};
private static final boolean isMusicPlaying(int playbackState) {
@@ -817,9 +784,6 @@ public class KeyguardHostView extends KeyguardViewBase {
// If the alternate unlock was suppressed, it can now be safely
// enabled because the user has left keyguard.
KeyguardUpdateMonitor.getInstance(mContext).setAlternateUnlockEnabled(true);
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)){
- maybeStopHotwordDetector();
- }
// If there's a pending runnable because the user interacted with a widget
// and we're leaving keyguard, then run it.
@@ -984,9 +948,6 @@ public class KeyguardHostView extends KeyguardViewBase {
// Emulate Activity life cycle
if (oldView != null) {
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)) {
- maybeStopHotwordDetector();
- }
oldView.onPause();
oldView.setKeyguardCallback(mNullCallback); // ignore requests from old view
}
@@ -1040,11 +1001,6 @@ public class KeyguardHostView extends KeyguardViewBase {
mViewStateManager.showUsabilityHints();
}
- // Start hotword detection on insecure Keyguard.
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)) {
- maybeStartHotwordDetector();
- }
-
requestFocus();
}
@@ -1067,11 +1023,6 @@ public class KeyguardHostView extends KeyguardViewBase {
cameraPage.onScreenTurnedOff();
}
- // Stop hotword detection on insecure Keyguard.
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)) {
- maybeStopHotwordDetector();
- }
-
clearFocus();
}
@@ -1156,9 +1107,6 @@ public class KeyguardHostView extends KeyguardViewBase {
new CameraWidgetFrame.Callbacks() {
@Override
public void onLaunchingCamera() {
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)) {
- maybeStopHotwordDetector();
- }
setSliderHandleAlpha(0);
}
@@ -1688,9 +1636,6 @@ public class KeyguardHostView extends KeyguardViewBase {
}
public void showAssistant() {
- if (shouldRunHotwordInSecurityMode(mCurrentSecuritySelection)) {
- maybeStopHotwordDetector();
- }
final Intent intent = ((SearchManager) mContext.getSystemService(Context.SEARCH_SERVICE))
.getAssistIntent(mContext, true, UserHandle.USER_CURRENT);
@@ -1705,123 +1650,4 @@ public class KeyguardHostView extends KeyguardViewBase {
mActivityLauncher.launchActivityWithAnimation(
intent, false, opts.toBundle(), null, null);
}
-
-
- /**
- * Start the hotword detector if:
- * <li> ENABLE_HOTWORD is true and
- * <li> Hotword detection is not already running and
- * <li> TelephonyManager is in CALL_STATE_IDLE
- * <li> and Screen is turned on.
- */
- private void maybeStartHotwordDetector() {
- if (!ENABLE_HOTWORD) return;
-
- if (sHotwordClient != null) {
- if (DEBUG) Log.d(TAG, "maybeStartHotwordDetector()");
- // Don't start hotword detection if the screen is off.
- if (!mIsScreenOn) {
- if (DEBUG) Log.d(TAG, "screen was off, not starting");
- return;
- }
-
- KeyguardUpdateMonitor monitor = KeyguardUpdateMonitor.getInstance(getContext());
- if (monitor.getPhoneState() != TelephonyManager.CALL_STATE_IDLE) {
- if (DEBUG) Log.d(TAG, "Call underway, not starting");
- return;
- }
-
- try {
- sHotwordClient.startRecognition(mHotwordCallback);
- } catch(Exception ex) {
- // Don't allow hotword errors to make the keyguard unusable
- Log.e(TAG, "Failed to start hotword recognition", ex);
- sHotwordClient = null;
- }
- }
- }
-
- /**
- * Stop hotword detector if:
- * <li> ENABLE_HOTWORD is true
- * <li> and hotword is running.
- */
- private void maybeStopHotwordDetector() {
- if (!ENABLE_HOTWORD) return;
-
- if (sHotwordClient != null) {
- if (DEBUG) Log.d(TAG, "maybeStopHotwordDetector()");
- try {
- sHotwordClient.stopRecognition();
- } catch(Exception ex) {
- // Don't allow hotword errors to make the keyguard unusable
- Log.e(TAG, "Failed to start hotword recognition", ex);
- } finally {
- sHotwordClient = null;
- }
- }
- }
-
- private final HotwordRecognitionListener mHotwordCallback = new HotwordRecognitionListener() {
- private static final String TAG = "HotwordRecognitionListener";
-
- public void onHotwordRecognitionStarted() {
- if (DEBUG) Log.d(TAG, "onHotwordRecognitionStarted()");
- }
-
- public void onHotwordRecognitionStopped() {
- if (DEBUG) Log.d(TAG, "onHotwordRecognitionStopped()");
- }
-
- public void onHotwordEvent(int eventType, Bundle eventBundle) {
- if (DEBUG) Log.d(TAG, "onHotwordEvent: " + eventType);
- if (eventType == HotwordRecognizer.EVENT_TYPE_STATE_CHANGED) {
- if (eventBundle != null && eventBundle.containsKey(HotwordRecognizer.PROMPT_TEXT)) {
- new KeyguardMessageArea.Helper(
- (View) getSecurityView(mCurrentSecuritySelection))
- .setMessage(eventBundle.getString(HotwordRecognizer.PROMPT_TEXT),true);
- }
- }
- }
-
- public void onHotwordRecognized(final Intent intent) {
- if (DEBUG) Log.d(TAG, "onHotwordRecognized");
- maybeStopHotwordDetector();
- // See if an activity can handle this intent.
- if (getContext().getPackageManager().resolveActivity(intent, 0) == null)
- return;
- if (SecurityMode.None == mCurrentSecuritySelection) {
- if (intent != null) {
- mActivityLauncher.launchActivity(intent, true, true, null, null);
- }
- mCallback.userActivity(0);
- } else if (ENABLE_HOTWORD_SECURE && mLockPatternUtils.isSecure()) {
- setOnDismissAction(new OnDismissAction() {
- @Override
- public boolean onDismiss() {
- if (intent != null) {
- mActivityLauncher.launchActivity(intent, true, true, null, null);
- }
- return false;
- }
- });
- getSecurityView(mCurrentSecuritySelection).showBouncer(0);
- }
- }
-
- public void onHotwordError(int errorCode) {
- if (DEBUG) Log.d(TAG, "onHotwordError: " + errorCode);
- // TODO: Inspect the error code and handle the errors appropriately
- // instead of blindly failing.
- maybeStopHotwordDetector();
- }
- };
-
- private boolean shouldRunHotwordInSecurityMode(SecurityMode mode) {
- // Enable hotoword for insecure keyguard,
- // and for pattern unlock if ENABLE_HOTWORD_SECURE is true.
- return ENABLE_HOTWORD
- && ((SecurityMode.None == mode)
- || (ENABLE_HOTWORD_SECURE && mLockPatternUtils.isSecure()));
- }
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
index 3f044708d5a0..344446f14bdd 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsBackupAgent.java
@@ -738,10 +738,12 @@ public class SettingsBackupAgent extends BackupAgentHelper {
}
}
+ // Intercept the keys and see if they need special handling
+ value = mSettingsHelper.onBackupValue(key, value);
+
if (value == null) {
continue;
}
-
// Write the key and value in the intermediary array.
byte[] keyBytes = key.getBytes();
totalSize += INTEGER_BYTE_COUNT + keyBytes.length;
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index a446e40f925d..dd7a828626f4 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -23,6 +23,8 @@ import android.content.Context;
import android.content.res.Configuration;
import android.location.LocationManager;
import android.media.AudioManager;
+import android.media.RingtoneManager;
+import android.net.Uri;
import android.os.IPowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
@@ -33,6 +35,7 @@ import android.text.TextUtils;
import java.util.Locale;
public class SettingsHelper {
+ private static final String SILENT_RINGTONE = "_silent";
private Context mContext;
private AudioManager mAudioManager;
@@ -63,10 +66,60 @@ public class SettingsHelper {
setAutoRestore(Integer.parseInt(value) == 1);
} else if (isAlreadyConfiguredCriticalAccessibilitySetting(name)) {
return false;
+ } else if (Settings.System.RINGTONE.equals(name)
+ || Settings.System.NOTIFICATION_SOUND.equals(name)) {
+ setRingtone(name, value);
+ return false;
}
return true;
}
+ public String onBackupValue(String name, String value) {
+ // Special processing for backing up ringtones
+ if (Settings.System.RINGTONE.equals(name)
+ || Settings.System.NOTIFICATION_SOUND.equals(name)) {
+ if (value == null) {
+ // Silent ringtone
+ return SILENT_RINGTONE;
+ } else {
+ return getCanonicalRingtoneValue(value);
+ }
+ }
+ // Return the original value
+ return value;
+ }
+
+ /**
+ * Sets the ringtone of type specified by the name.
+ *
+ * @param name should be Settings.System.RINGTONE or Settings.System.NOTIFICATION_SOUND.
+ * @param value can be a canonicalized uri or "_silent" to indicate a silent (null) ringtone.
+ */
+ private void setRingtone(String name, String value) {
+ // If it's null, don't change the default
+ if (value == null) return;
+ Uri ringtoneUri = null;
+ if (SILENT_RINGTONE.equals(value)) {
+ ringtoneUri = null;
+ } else {
+ Uri canonicalUri = Uri.parse(value);
+ ringtoneUri = mContext.getContentResolver().uncanonicalize(canonicalUri);
+ if (ringtoneUri == null) {
+ // Unrecognized or invalid Uri, don't restore
+ return;
+ }
+ }
+ final int ringtoneType = Settings.System.RINGTONE.equals(name)
+ ? RingtoneManager.TYPE_RINGTONE : RingtoneManager.TYPE_NOTIFICATION;
+ RingtoneManager.setActualDefaultRingtoneUri(mContext, ringtoneType, ringtoneUri);
+ }
+
+ private String getCanonicalRingtoneValue(String value) {
+ final Uri ringtoneUri = Uri.parse(value);
+ final Uri canonicalUri = mContext.getContentResolver().canonicalize(ringtoneUri);
+ return canonicalUri == null ? null : canonicalUri.toString();
+ }
+
private boolean isAlreadyConfiguredCriticalAccessibilitySetting(String name) {
// These are the critical accessibility settings that are required for a
// blind user to be able to interact with the device. If these settings are
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.png
index 645ee4a39e85..b226694e8623 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.png
index 24d26c3a2ea9..1e9fbfde4105 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.png
index b1cd0e3eeca6..0676919f7db4 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.png
index def0e23a6284..3ad9e76725f2 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..6ff215b4aaf0
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..cf5e825df48a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..5d8fd070fb7c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.png
index ac660753b346..c50069186a65 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.png
index 0a49702df168..ae878961cfd2 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.png
index 380b1ebae7c9..e47ef7afd381 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.png
index 756ff1f4ed88..9fd1ae678c43 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_in.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_in.png
new file mode 100644
index 000000000000..ebd2001f5edd
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_inout.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_inout.png
new file mode 100644
index 000000000000..cf5e825df48a
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.png
new file mode 100644
index 000000000000..5d8fd070fb7c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/ic_qs_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
index c779e7e8df63..c971443da621 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
index cf07aae81803..717711f9dddc 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
index 50aa77fbaca5..cdf35b638a85 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
index 045182c19d4d..ce90eb426021 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
index 5232169c729b..39a109c54f60 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
index 2b0da2cb78c6..22f18a04b1ea 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
index 24755d999ee0..f7f0159246e1 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
index 3f30896aa52e..86b250c98065 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
index 87da72bc5956..f70634355e84 100644
--- a/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-hdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
index eeee60fb687e..42c773d9bea1 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..e6a2f17b5b8b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..fd40015de368
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..0a6d20acc26b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_1.png
index 395adadf1dbd..79d314583f06 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_2.png
index 4ded92394645..d83696f40209 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_3.png
index 568c29671e90..b6b84a1eb91c 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_4.png
index 000f93dd5f41..35de22dc2e25 100644
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-ldrtl-hdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..9c8f3e7c7cd1
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..7e773f026652
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..2ecfd0b89f6d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_1.png
index 33a35d055037..e432210f79be 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_2.png
index 71e396e2f25c..fc4dbb019269 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_3.png
index b61b1e037c9b..410e8f3a53b2 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_4.png
index 7121abba0663..e222ffd340b0 100644
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-ldrtl-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..f3245a0956b7
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..9f02b9d60d3f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..8452087f3853
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_1.png
index ef913284a6a4..584a73a262ac 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_2.png
index ffb3b559dd57..b90b421a2d20 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_3.png
index 85eef224ac2d..5fdf834867b9 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_4.png
index 5aeb91327f38..ada740a11943 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..61b0df9372d5
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..e450506ab37b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..f8b63cbadfb6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_1.png
index dc4a01e6da95..8103f4d30299 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_2.png
index bb6fd30f245e..22d7a1c8b676 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_3.png
index b77c83385e25..29d3ab06fc10 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_4.png
index 448d79b0d3d5..6aa4854a13b5 100644
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.png
index ae51eca4507d..2994632711d6 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.png
index 77dcdcee5613..b11193956fd0 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.png
index aff279cd6edc..98c8e2539228 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.png
index e64d314b23ca..625dbd9289ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..da4ffa277a9f
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..e1c797260804
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..b8c8b4e8838c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.png
index cafb93d7858d..60e38adad6b4 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.png
index 55eccf058dd8..89833802fb98 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.png
index 989427b53734..ff652df155b4 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.png
index f2d7963c774d..8dd9c43ee3ec 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_in.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_in.png
new file mode 100644
index 000000000000..5d0ad7c05681
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_inout.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_inout.png
new file mode 100644
index 000000000000..e1c797260804
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.png
new file mode 100644
index 000000000000..b8c8b4e8838c
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/ic_qs_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
index 62807cdc1271..b1b675bf492a 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
index c3c6b9326b6a..f3232a292313 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
index bb2e9baec648..8dbee4bfef99 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
index 6583922bf443..bef1f187e35e 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
index 9b1cbcce9c96..163c740ab246 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
index 3fb4427342db..33ee9a63e6ed 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
index abcc317ddbb4..0b7cbdeb5ca9 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
index a3b267806aa2..a2aa04588eef 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
index b4278f2c6ab6..de79d19d0f9f 100644
--- a/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-mdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
index c73ff354d726..20c8785de780 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-nodpi/lightning.png b/packages/SystemUI/res/drawable-nodpi/lightning.png
deleted file mode 100644
index 29de3085a533..000000000000
--- a/packages/SystemUI/res/drawable-nodpi/lightning.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.png
index 3bbfb4ed4c29..abc935884374 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.png
index 7fc9bd48d9f2..0419144287ae 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.png
index 56a9a13a24a4..515ffe7536c0 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.png
index ad06e6249ea0..118de2dc3d81 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..46fd826dfb25
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..c824b9760fa2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..fb9ecd01f399
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.png
index 94666a1994be..715e60a2195b 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.png
index 8e19afd6e9b4..ed7f5b963337 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.png
index 62933b054822..8f1464bd4fea 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.png
index e93292bc9167..b32c676de4ca 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_in.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_in.png
new file mode 100644
index 000000000000..6cf0a4b2e815
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_inout.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_inout.png
new file mode 100644
index 000000000000..c824b9760fa2
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.png
new file mode 100644
index 000000000000..fb9ecd01f399
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_qs_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
index 1e68ac7846f9..94605c9c726c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
index 23288de8e0d9..ac18139f8b8c 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
index 32e05feb06c8..587d93c213b4 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
index f2f88a12d5fa..656d6d004596 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
index 7a38994b24d1..e8033c8316c8 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
index a93e3a87bef1..1253a41460e3 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
index 24b47b2c9c53..bcb20af6dec9 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
index b4b3f0265747..ca70a29ebaf5 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
index 758ebe7117b8..8ce2ae931014 100644
--- a/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-xhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
index e9313148d1a2..b4e129c00a77 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_1.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_1.png
index 4a243cab82a9..746b9ea9732b 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_1.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_2.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_2.png
index 37841afe6011..55ba5abd6d76 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_2.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_3.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_3.png
index 39be463f9f82..547f875b2f93 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_3.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_4.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_4.png
index 5b9b7af9b4b9..1f65ad52838c 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_4.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_in.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_in.png
new file mode 100644
index 000000000000..1094bc31a5a8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_inout.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_inout.png
new file mode 100644
index 000000000000..1037b02bef4b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_out.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_out.png
new file mode 100644
index 000000000000..f5595e3b79b3
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_signal_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_1.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_1.png
index 10818ba79f0d..01274a6f552d 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_1.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_2.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_2.png
index 752fee1fa8c5..a02832dde1d8 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_2.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_3.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_3.png
index 684372adea96..7e55bbb8d988 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_3.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_4.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_4.png
index 9b4b8c71cbc2..eeb898998e8b 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_4.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_in.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_in.png
new file mode 100644
index 000000000000..7183a07cbb8e
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_in.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_inout.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_inout.png
new file mode 100644
index 000000000000..374632860f71
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_inout.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_out.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_out.png
new file mode 100644
index 000000000000..dbf54ce62a0b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_wifi_out.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.png
index d02693668a7f..a2bab6d58274 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_battery_15.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png
index afacef534517..ee2013032f32 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png
index 1b1c86351bf0..362d06da02d6 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png
index 99094e3624f4..b1fd4135d96c 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png
index 8aff99988a94..1a1862a0ae29 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_1.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_1.png
index 3fe77d0838eb..57a422810fd0 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_1.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_1.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_2.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_2.png
index dec522d9c991..c536e7ba03f8 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_2.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_2.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_3.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_3.png
index 9e679c229e32..01ff1b9faf91 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_3.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_3.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_4.png b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_4.png
index f4c7250cb64d..f8280686a421 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_4.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/stat_sys_wifi_signal_4.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml b/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
index 34506b161ff7..cabfaa505560 100644
--- a/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
+++ b/packages/SystemUI/res/layout/quick_settings_tile_rssi.xml
@@ -13,32 +13,49 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<LinearLayout
+<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_gravity="top"
- android:orientation="vertical">
+ android:layout_gravity="top">
<FrameLayout
+ android:id="@+id/rssi_images"
android:layout_marginTop="@dimen/qs_tile_margin_above_icon"
android:layout_marginBottom="@dimen/qs_tile_margin_below_icon"
android:layout_width="@dimen/qs_tile_icon_size"
android:layout_height="@dimen/qs_tile_icon_size"
android:layout_gravity="top|center_horizontal"
+ android:layout_centerHorizontal="true"
>
<ImageView
android:id="@+id/rssi_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_centerInParent="true"
/>
<ImageView
android:id="@+id/rssi_overlay_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:layout_gravity="center"
+ android:layout_centerInParent="true"
/>
</FrameLayout>
+ <ImageView
+ android:id="@+id/activity_in"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_qs_signal_in"
+ android:layout_toRightOf="@id/rssi_images"
+ android:layout_alignBottom="@id/rssi_images"
+ />
+ <ImageView
+ android:id="@+id/activity_out"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_qs_signal_out"
+ android:layout_toRightOf="@id/rssi_images"
+ android:layout_alignBottom="@id/rssi_images"
+ />
<TextView
style="@style/TextAppearance.QuickSettings.TileView"
android:id="@+id/rssi_textview"
@@ -47,5 +64,7 @@
android:layout_gravity="top|center_horizontal"
android:gravity="top|center_horizontal"
android:text="@string/quick_settings_rssi_label"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/rssi_images"
/>
-</LinearLayout> \ No newline at end of file
+</RelativeLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_tile_wifi.xml b/packages/SystemUI/res/layout/quick_settings_tile_wifi.xml
new file mode 100644
index 000000000000..e61c5956c941
--- /dev/null
+++ b/packages/SystemUI/res/layout/quick_settings_tile_wifi.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2013 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_gravity="top">
+ <ImageView
+ android:id="@+id/image"
+ android:layout_marginTop="@dimen/qs_tile_margin_above_icon"
+ android:layout_marginBottom="@dimen/qs_tile_margin_below_icon"
+ android:layout_width="@dimen/qs_tile_icon_size"
+ android:layout_height="@dimen/qs_tile_icon_size"
+ android:layout_gravity="top|center_horizontal"
+ android:layout_centerHorizontal="true"
+ android:scaleType="centerInside"
+ />
+ <ImageView
+ android:id="@+id/activity_in"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_qs_wifi_in"
+ android:layout_toRightOf="@id/image"
+ android:layout_alignBottom="@id/image"
+ />
+ <ImageView
+ android:id="@+id/activity_out"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:src="@drawable/ic_qs_wifi_out"
+ android:layout_toRightOf="@id/image"
+ android:layout_alignBottom="@id/image"
+ />
+ <TextView
+ style="@style/TextAppearance.QuickSettings.TileView"
+ android:id="@+id/text"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="top|center_horizontal"
+ android:gravity="top|center_horizontal"
+ android:layout_centerHorizontal="true"
+ android:layout_below="@id/image"
+ />
+</RelativeLayout> \ No newline at end of file
diff --git a/packages/SystemUI/res/values/arrays.xml b/packages/SystemUI/res/values/arrays.xml
index 0812e80f67f5..69f4b4fbef05 100644
--- a/packages/SystemUI/res/values/arrays.xml
+++ b/packages/SystemUI/res/values/arrays.xml
@@ -47,9 +47,18 @@
<item>100</item>
</array>
<array name="batterymeter_color_values">
- <item>#FFFF3300</item>
- <item>#FFFF3300</item>
+ <item>#FFF75D00</item>
+ <item>#FFF75D00</item>
<item>#FFFFFFFF</item>
</array>
-
+ <array name="batterymeter_bolt_points">
+ <item>88</item> <item>0</item>
+ <item>459</item><item>1</item>
+ <item>238</item><item>333</item>
+ <item>525</item><item>310</item>
+ <item>120</item><item>840</item>
+ <item>82</item> <item>818</item>
+ <item>246</item><item>373</item>
+ <item>0</item> <item>408</item>
+ </array>
</resources>
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index be5c3267bab4..2257617b5429 100755
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -23,12 +23,13 @@ import android.content.IntentFilter;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
-import android.graphics.LightingColorFilter;
import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Typeface;
-import android.graphics.drawable.Drawable;
import android.os.BatteryManager;
import android.os.Bundle;
import android.provider.Settings;
@@ -43,26 +44,27 @@ public class BatteryMeterView extends View implements DemoMode {
public static final boolean SINGLE_DIGIT_PERCENT = false;
public static final boolean SHOW_100_PERCENT = false;
- private static final LightingColorFilter LIGHTNING_FILTER_OPAQUE =
- new LightingColorFilter(0x00000000, 0x00000000);
- private static final LightingColorFilter LIGHTNING_FILTER_TRANS =
- new LightingColorFilter(0x00999999, 0x00000000);
-
public static final int FULL = 96;
public static final int EMPTY = 4;
int[] mColors;
boolean mShowPercent = true;
- Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint;
+ Paint mFramePaint, mBatteryPaint, mWarningTextPaint, mTextPaint, mBoltPaint;
int mButtonHeight;
private float mTextHeight, mWarningTextHeight;
- Drawable mLightning;
private int mHeight;
private int mWidth;
private String mWarningString;
private final int mChargeColor;
+ private final float[] mBoltPoints;
+ private final Path mBoltPath = new Path();
+
+ private final RectF mFrame = new RectF();
+ private final RectF mButtonFrame = new RectF();
+ private final RectF mClipFrame = new RectF();
+ private final Rect mBoltFrame = new Rect();
private class BatteryTracker extends BroadcastReceiver {
// current battery status
@@ -175,7 +177,8 @@ public class BatteryMeterView extends View implements DemoMode {
mColors[2*i] = levels.getInt(i, 0);
mColors[2*i+1] = colors.getColor(i, 0);
}
-
+ levels.recycle();
+ colors.recycle();
mShowPercent = ENABLE_PERCENT && 0 != Settings.System.getInt(
context.getContentResolver(), "status_bar_show_battery_percent", 0);
@@ -198,8 +201,28 @@ public class BatteryMeterView extends View implements DemoMode {
mWarningTextPaint.setTypeface(font);
mWarningTextPaint.setTextAlign(Paint.Align.CENTER);
- mLightning = getResources().getDrawable(R.drawable.lightning);
mChargeColor = getResources().getColor(R.color.batterymeter_charge_color);
+
+ mBoltPaint = new Paint();
+ mBoltPaint.setAntiAlias(true);
+ mBoltPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); // punch hole
+ setLayerType(LAYER_TYPE_HARDWARE, null);
+ mBoltPoints = loadBoltPoints(res);
+ }
+
+ private static float[] loadBoltPoints(Resources res) {
+ final int[] pts = res.getIntArray(R.array.batterymeter_bolt_points);
+ int maxX = 0, maxY = 0;
+ for (int i = 0; i < pts.length; i += 2) {
+ maxX = Math.max(maxX, pts[i]);
+ maxY = Math.max(maxY, pts[i + 1]);
+ }
+ final float[] ptsF = new float[pts.length];
+ for (int i = 0; i < pts.length; i += 2) {
+ ptsF[i] = (float)pts[i] / maxX;
+ ptsF[i + 1] = (float)pts[i + 1] / maxY;
+ }
+ return ptsF;
}
@Override
@@ -220,15 +243,6 @@ public class BatteryMeterView extends View implements DemoMode {
return color;
}
- // TODO jspurlock - remove once we draw hollow bolt in code
- public void setBarTransparent(boolean isTransparent) {
- mLightning.setColorFilter(isTransparent ? LIGHTNING_FILTER_TRANS : LIGHTNING_FILTER_OPAQUE);
- BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
- if (tracker.plugged) {
- postInvalidate();
- }
- }
-
@Override
public void draw(Canvas c) {
BatteryTracker tracker = mDemoMode ? mDemoTracker : mTracker;
@@ -243,22 +257,19 @@ public class BatteryMeterView extends View implements DemoMode {
mButtonHeight = (int) (height * 0.12f);
- final RectF frame = new RectF(0, 0, width, height);
- frame.offset(pl, pt);
-
- // Log.v("BatteryGauge", String.format("canvas: %dx%d frame: %s",
- // c.getWidth(), c.getHeight(), frame.toString()));
+ mFrame.set(0, 0, width, height);
+ mFrame.offset(pl, pt);
- final RectF buttonframe = new RectF(
- frame.left + width * 0.25f,
- frame.top,
- frame.right - width * 0.25f,
- frame.top + mButtonHeight);
+ mButtonFrame.set(
+ mFrame.left + width * 0.25f,
+ mFrame.top,
+ mFrame.right - width * 0.25f,
+ mFrame.top + mButtonHeight);
- frame.top += mButtonHeight;
+ mFrame.top += mButtonHeight;
// first, draw the battery shape
- c.drawRect(frame, mFramePaint);
+ c.drawRect(mFrame, mFramePaint);
// fill 'er up
final int pct = tracker.level;
@@ -271,15 +282,14 @@ public class BatteryMeterView extends View implements DemoMode {
drawFrac = 0f;
}
- c.drawRect(buttonframe,
- drawFrac == 1f ? mBatteryPaint : mFramePaint);
+ c.drawRect(mButtonFrame, drawFrac == 1f ? mBatteryPaint : mFramePaint);
- RectF clip = new RectF(frame);
- clip.top += (frame.height() * (1f - drawFrac));
+ mClipFrame.set(mFrame);
+ mClipFrame.top += (mFrame.height() * (1f - drawFrac));
c.save(Canvas.CLIP_SAVE_FLAG);
- c.clipRect(clip);
- c.drawRect(frame, mBatteryPaint);
+ c.clipRect(mClipFrame);
+ c.drawRect(mFrame, mBatteryPaint);
c.restore();
if (level <= EMPTY) {
@@ -287,11 +297,28 @@ public class BatteryMeterView extends View implements DemoMode {
final float y = (mHeight + mWarningTextHeight) * 0.48f;
c.drawText(mWarningString, x, y, mWarningTextPaint);
} else if (tracker.plugged) {
- final Rect r = new Rect(
- (int)frame.left + width / 4, (int)frame.top + height / 5,
- (int)frame.right - width / 4, (int)frame.bottom - height / 6);
- mLightning.setBounds(r);
- mLightning.draw(c);
+ // draw the bolt
+ final int bl = (int)(mFrame.left + width / 4f);
+ final int bt = (int)(mFrame.top + height / 6f);
+ final int br = (int)(mFrame.right - width / 5f);
+ final int bb = (int)(mFrame.bottom - height / 6f);
+ if (mBoltFrame.left != bl || mBoltFrame.top != bt
+ || mBoltFrame.right != br || mBoltFrame.bottom != bb) {
+ mBoltFrame.set(bl, bt, br, bb);
+ mBoltPath.reset();
+ mBoltPath.moveTo(
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ for (int i = 2; i < mBoltPoints.length; i += 2) {
+ mBoltPath.lineTo(
+ mBoltFrame.left + mBoltPoints[i] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[i + 1] * mBoltFrame.height());
+ }
+ mBoltPath.lineTo(
+ mBoltFrame.left + mBoltPoints[0] * mBoltFrame.width(),
+ mBoltFrame.top + mBoltPoints[1] * mBoltFrame.height());
+ }
+ c.drawPath(mBoltPath, mBoltPaint);
} else if (mShowPercent && !(tracker.level == 100 && !SHOW_100_PERCENT)) {
mTextPaint.setTextSize(height *
(SINGLE_DIGIT_PERCENT ? 0.75f
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 119299f8d082..2063563447ca 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -196,7 +196,8 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
// Create screenshot directory if it doesn't exist
mScreenshotDir.mkdirs();
- // media provider uses seconds, not milliseconds
+ // media provider uses seconds for DATE_MODIFIED and DATE_ADDED, but milliseconds
+ // for DATE_TAKEN
long dateSeconds = mImageTime / 1000;
// Save the screenshot to the MediaStore
@@ -205,7 +206,7 @@ class SaveImageInBackgroundTask extends AsyncTask<SaveImageInBackgroundData, Voi
values.put(MediaStore.Images.ImageColumns.DATA, mImageFilePath);
values.put(MediaStore.Images.ImageColumns.TITLE, mImageFileName);
values.put(MediaStore.Images.ImageColumns.DISPLAY_NAME, mImageFileName);
- values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, dateSeconds);
+ values.put(MediaStore.Images.ImageColumns.DATE_TAKEN, mImageTime);
values.put(MediaStore.Images.ImageColumns.DATE_ADDED, dateSeconds);
values.put(MediaStore.Images.ImageColumns.DATE_MODIFIED, dateSeconds);
values.put(MediaStore.Images.ImageColumns.MIME_TYPE, "image/png");
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 9db28051d294..814f5db7ba9e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1349,8 +1349,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
};
boolean panelsEnabled() {
- return ((mDisabled & StatusBarManager.DISABLE_EXPAND) == 0
- && mStatusBarWindowState != StatusBarManager.WINDOW_STATE_HIDING);
+ return (mDisabled & StatusBarManager.DISABLE_EXPAND) == 0;
}
void makeExpandedVisible() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index f8b6ca6d2103..b263a6ecbd04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.app.ActivityManager;
import android.content.Context;
@@ -28,7 +29,6 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.accessibility.AccessibilityEvent;
-import com.android.systemui.BatteryMeterView;
import com.android.systemui.EventLogTags;
import com.android.systemui.R;
@@ -53,9 +53,7 @@ public class PhoneStatusBarView extends PanelBar {
private final int mTransparent;
private final float mAlphaWhenOpaque;
private final float mAlphaWhenTransparent = 1;
- private View mLeftSide;
- private View mRightSide;
- private BatteryMeterView mBattery;
+ private View mLeftSide, mStatusIcons, mSignalCluster, mClock;
public StatusBarTransitions(Context context) {
super(context, PhoneStatusBarView.this);
@@ -66,8 +64,9 @@ public class PhoneStatusBarView extends PanelBar {
public void init() {
mLeftSide = findViewById(R.id.notification_icon_area);
- mRightSide = findViewById(R.id.system_icon_area);
- mBattery = (BatteryMeterView) findViewById(R.id.battery);
+ mStatusIcons = findViewById(R.id.statusIcons);
+ mSignalCluster = findViewById(R.id.signal_battery_cluster);
+ mClock = findViewById(R.id.clock);
applyMode(getMode(), false /*animate*/);
}
@@ -96,17 +95,22 @@ public class PhoneStatusBarView extends PanelBar {
}
private void applyMode(int mode, boolean animate) {
- if (mLeftSide == null || mRightSide == null) return;
- mBattery.setBarTransparent(isTransparent(mode));
+ if (mLeftSide == null) return; // pre-init
float newAlpha = getAlphaFor(mode);
if (animate) {
- ObjectAnimator lhs = animateTransitionTo(mLeftSide, newAlpha);
- lhs.start();
- // TODO jspurlock - fix conflicting rhs animations on tablets
- mRightSide.setAlpha(newAlpha);
+ AnimatorSet anims = new AnimatorSet();
+ anims.playTogether(
+ animateTransitionTo(mLeftSide, newAlpha),
+ animateTransitionTo(mStatusIcons, newAlpha),
+ animateTransitionTo(mSignalCluster, newAlpha),
+ animateTransitionTo(mClock, newAlpha)
+ );
+ anims.start();
} else {
mLeftSide.setAlpha(newAlpha);
- mRightSide.setAlpha(newAlpha);
+ mStatusIcons.setAlpha(newAlpha);
+ mSignalCluster.setAlpha(newAlpha);
+ mClock.setAlpha(newAlpha);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index 0d591ba3c016..68ee2b56c8ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.phone;
+import android.animation.ValueAnimator;
import android.app.ActivityManagerNative;
import android.app.AlertDialog;
import android.app.Dialog;
@@ -62,6 +63,7 @@ import android.widget.ImageView;
import android.widget.TextView;
import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.QuickSettingsModel.ActivityState;
import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
import com.android.systemui.statusbar.phone.QuickSettingsModel.State;
@@ -401,8 +403,9 @@ class QuickSettings {
private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
// Wi-fi
- final QuickSettingsBasicTile wifiTile
- = new QuickSettingsBasicTile(mContext);
+ final QuickSettingsTileView wifiTile = (QuickSettingsTileView)
+ inflater.inflate(R.layout.quick_settings_tile, parent, false);
+ wifiTile.setContent(R.layout.quick_settings_tile_wifi, inflater);
wifiTile.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -433,12 +436,15 @@ class QuickSettings {
return true;
}} );
}
- mModel.addWifiTile(wifiTile, new QuickSettingsModel.RefreshCallback() {
+ mModel.addWifiTile(wifiTile, new NetworkActivityCallback() {
@Override
- public void refreshView(QuickSettingsTileView unused, State state) {
+ public void refreshView(QuickSettingsTileView view, State state) {
WifiState wifiState = (WifiState) state;
- wifiTile.setImageResource(wifiState.iconId);
- wifiTile.setText(wifiState.label);
+ ImageView iv = (ImageView) view.findViewById(R.id.image);
+ iv.setImageResource(wifiState.iconId);
+ setActivity(view, wifiState);
+ TextView tv = (TextView) view.findViewById(R.id.text);
+ tv.setText(wifiState.label);
wifiTile.setContentDescription(mContext.getString(
R.string.accessibility_quick_settings_wifi,
wifiState.signalContentDescription,
@@ -462,7 +468,7 @@ class QuickSettings {
startSettingsActivity(intent);
}
});
- mModel.addRSSITile(rssiTile, new QuickSettingsModel.RefreshCallback() {
+ mModel.addRSSITile(rssiTile, new NetworkActivityCallback() {
@Override
public void refreshView(QuickSettingsTileView view, State state) {
RSSIState rssiState = (RSSIState) state;
@@ -478,6 +484,8 @@ class QuickSettings {
} else {
iov.setImageDrawable(null);
}
+ setActivity(view, rssiState);
+
tv.setText(state.label);
view.setContentDescription(mContext.getResources().getString(
R.string.accessibility_quick_settings_mobile,
@@ -942,4 +950,25 @@ class QuickSettings {
}
};
+
+ private abstract static class NetworkActivityCallback
+ implements QuickSettingsModel.RefreshCallback {
+ private final long mDefaultDuration = new ValueAnimator().getDuration();
+ private final long mShortDuration = mDefaultDuration / 3;
+
+ public void setActivity(View view, ActivityState state) {
+ setVisibility(view.findViewById(R.id.activity_in), state.activityIn);
+ setVisibility(view.findViewById(R.id.activity_out), state.activityOut);
+ }
+
+ private void setVisibility(View view, boolean visible) {
+ final float newAlpha = visible ? 1 : 0;
+ if (view.getAlpha() != newAlpha) {
+ view.animate()
+ .setDuration(visible ? mShortDuration : mDefaultDuration)
+ .alpha(newAlpha)
+ .start();
+ }
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index b9e3059d4f28..9d0418dab44d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -70,13 +70,17 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
int batteryLevel;
boolean pluggedIn;
}
- static class RSSIState extends State {
+ static class ActivityState extends State {
+ boolean activityIn;
+ boolean activityOut;
+ }
+ static class RSSIState extends ActivityState {
int signalIconId;
String signalContentDescription;
int dataTypeIconId;
String dataContentDescription;
}
- static class WifiState extends State {
+ static class WifiState extends ActivityState {
String signalContentDescription;
boolean connected;
}
@@ -430,6 +434,7 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
// NetworkSignalChanged callback
@Override
public void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
+ boolean activityIn, boolean activityOut,
String wifiSignalContentDescription, String enabledDesc) {
// TODO: If view is in awaiting state, disable
Resources r = mContext.getResources();
@@ -438,6 +443,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
boolean wifiNotConnected = (wifiSignalIconId > 0) && (enabledDesc == null);
mWifiState.enabled = enabled;
mWifiState.connected = wifiConnected;
+ mWifiState.activityIn = enabled && activityIn;
+ mWifiState.activityOut = enabled && activityOut;
if (wifiConnected) {
mWifiState.iconId = wifiSignalIconId;
mWifiState.label = removeDoubleQuotes(enabledDesc);
@@ -468,7 +475,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
@Override
public void onMobileDataSignalChanged(
boolean enabled, int mobileSignalIconId, String signalContentDescription,
- int dataTypeIconId, String dataContentDescription, String enabledDesc) {
+ int dataTypeIconId, boolean activityIn, boolean activityOut,
+ String dataContentDescription,String enabledDesc) {
if (deviceHasMobileData()) {
// TODO: If view is in awaiting state, disable
Resources r = mContext.getResources();
@@ -481,6 +489,8 @@ class QuickSettingsModel implements BluetoothStateChangeCallback,
mRSSIState.dataTypeIconId = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
? dataTypeIconId
: 0;
+ mRSSIState.activityIn = enabled && activityIn;
+ mRSSIState.activityOut = enabled && activityOut;
mRSSIState.dataContentDescription = enabled && (dataTypeIconId > 0) && !mWifiState.enabled
? dataContentDescription
: r.getString(R.string.accessibility_no_data);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
index 1e7e6927b2e6..a7154503697f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkController.java
@@ -165,9 +165,11 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
public interface NetworkSignalChangedCallback {
void onWifiSignalChanged(boolean enabled, int wifiSignalIconId,
- String wifitSignalContentDescriptionId, String description);
+ boolean activityIn, boolean activityOut,
+ String wifiSignalContentDescriptionId, String description);
void onMobileDataSignalChanged(boolean enabled, int mobileSignalIconId,
String mobileSignalContentDescriptionId, int dataTypeIconId,
+ boolean activityIn, boolean activityOut,
String dataTypeContentDescriptionId, String description);
void onAirplaneModeChanged(boolean enabled);
}
@@ -313,22 +315,33 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
boolean wifiEnabled = mWifiEnabled && (mWifiConnected || !mHasMobileDataFeature);
String wifiDesc = wifiEnabled ?
mWifiSsid : null;
- cb.onWifiSignalChanged(wifiEnabled, mQSWifiIconId, mContentDescriptionWifi, wifiDesc);
-
+ boolean wifiIn = wifiEnabled && mWifiSsid != null
+ && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT
+ || mWifiActivity == WifiManager.DATA_ACTIVITY_IN);
+ boolean wifiOut = wifiEnabled && mWifiSsid != null
+ && (mWifiActivity == WifiManager.DATA_ACTIVITY_INOUT
+ || mWifiActivity == WifiManager.DATA_ACTIVITY_OUT);
+ cb.onWifiSignalChanged(wifiEnabled, mQSWifiIconId, wifiIn, wifiOut,
+ mContentDescriptionWifi, wifiDesc);
+
+ boolean mobileIn = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT
+ || mDataActivity == TelephonyManager.DATA_ACTIVITY_IN);
+ boolean mobileOut = mDataConnected && (mDataActivity == TelephonyManager.DATA_ACTIVITY_INOUT
+ || mDataActivity == TelephonyManager.DATA_ACTIVITY_OUT);
if (isEmergencyOnly()) {
cb.onMobileDataSignalChanged(false, mQSPhoneSignalIconId,
- mContentDescriptionPhoneSignal, mQSDataTypeIconId, mContentDescriptionDataType,
- null);
+ mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
+ mContentDescriptionDataType, null);
} else {
if (mIsWimaxEnabled && mWimaxConnected) {
// Wimax is special
cb.onMobileDataSignalChanged(true, mQSPhoneSignalIconId,
- mContentDescriptionPhoneSignal, mQSDataTypeIconId,
+ mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
mContentDescriptionDataType, mNetworkName);
} else {
// Normal mobile data
cb.onMobileDataSignalChanged(mHasMobileDataFeature, mQSPhoneSignalIconId,
- mContentDescriptionPhoneSignal, mQSDataTypeIconId,
+ mContentDescriptionPhoneSignal, mQSDataTypeIconId, mobileIn, mobileOut,
mContentDescriptionDataType, mNetworkName);
}
}
@@ -1125,6 +1138,11 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
+ " mBluetoothTetherIconId=0x" + Integer.toHexString(mBluetoothTetherIconId));
}
+ // update QS
+ for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
+ notifySignalsChangedCallbacks(cb);
+ }
+
if (mLastPhoneSignalIconId != mPhoneSignalIconId
|| mLastWifiIconId != mWifiIconId
|| mLastWimaxIconId != mWimaxIconId
@@ -1136,9 +1154,6 @@ public class NetworkController extends BroadcastReceiver implements DemoMode {
for (SignalCluster cluster : mSignalClusters) {
refreshSignalCluster(cluster);
}
- for (NetworkSignalChangedCallback cb : mSignalsChangedCallbacks) {
- notifySignalsChangedCallbacks(cb);
- }
}
if (mLastAirplaneMode != mAirplaneMode) {
diff --git a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
index 7e760251ac8a..c6b76f173ff3 100644
--- a/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
+++ b/packages/services/PacProcessor/src/com/android/pacprocessor/PacService.java
@@ -25,6 +25,9 @@ import android.util.Log;
import com.android.net.IProxyService;
+import java.net.MalformedURLException;
+import java.net.URL;
+
public class PacService extends Service {
private static final String TAG = "PacService";
@@ -68,7 +71,18 @@ public class PacService extends Service {
@Override
public String resolvePacFile(String host, String url) throws RemoteException {
- return mPacNative.makeProxyRequest(url, host);
+ try {
+ // Check for characters that could be used for an injection attack.
+ new URL(url);
+ for (char c : host.toCharArray()) {
+ if (!Character.isLetterOrDigit(c) && (c != '.') && (c != '-')) {
+ throw new RemoteException("Invalid host was passed");
+ }
+ }
+ return mPacNative.makeProxyRequest(url, host);
+ } catch (MalformedURLException e) {
+ throw new RemoteException("Invalid URL was passed");
+ }
}
@Override
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 27bf38cc3d9f..8a285e30e7f9 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -3637,7 +3637,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
? AudioManager.ADJUST_RAISE
: AudioManager.ADJUST_LOWER,
0,
- mContext.getBasePackageName());
+ mContext.getOpPackageName());
} catch (RemoteException e) {
Log.w(TAG, "IAudioService.adjustStreamVolume() threw RemoteException " + e);
} finally {
@@ -4964,7 +4964,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
owningPackage = win.getOwningPackage();
} else {
owningUid = android.os.Process.myUid();
- owningPackage = mContext.getBasePackageName();
+ owningPackage = mContext.getOpPackageName();
}
if (pattern.length == 1) {
// One-shot vibration
diff --git a/preloaded-classes b/preloaded-classes
index 064ca3a12d75..cb2ace388398 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -663,8 +663,8 @@ android.net.wifi.IWifiManager$Stub$Proxy
android.net.wifi.WifiManager
android.net.wifi.WifiManager$ServiceHandler
android.net.wifi.WifiNative
-android.nfc.INdefPushCallback
-android.nfc.INdefPushCallback$Stub
+android.nfc.IAppCallback
+android.nfc.IAppCallback$Stub
android.nfc.INfcAdapter
android.nfc.INfcAdapter$Stub
android.nfc.INfcAdapter$Stub$Proxy
@@ -1209,13 +1209,9 @@ android.webkit.BrowserFrame
android.webkit.BrowserFrame$ConfigCallback
android.webkit.CallbackProxy
android.webkit.CookieManager
-android.webkit.CookieManagerClassic
android.webkit.CookieSyncManager
android.webkit.DeviceMotionAndOrientationManager
android.webkit.GeolocationPermissions
-android.webkit.GeolocationPermissionsClassic
-android.webkit.GeolocationPermissionsClassic$1
-android.webkit.GeolocationPermissionsClassic$2
android.webkit.HTML5Audio
android.webkit.HTML5VideoViewProxy
android.webkit.JWebCoreJavaBridge
@@ -1231,42 +1227,19 @@ android.webkit.ViewManager$2
android.webkit.ViewManager$3
android.webkit.ViewStateSerializer
android.webkit.WebBackForwardList
-android.webkit.WebBackForwardListClassic
android.webkit.WebCoreThreadWatchdog
android.webkit.WebHistoryItem
-android.webkit.WebHistoryItemClassic
android.webkit.WebIconDatabase
-android.webkit.WebIconDatabaseClassic
-android.webkit.WebIconDatabaseClassic$EventHandler
-android.webkit.WebIconDatabaseClassic$EventHandler$1
android.webkit.WebSettings
android.webkit.WebSettings$LayoutAlgorithm
android.webkit.WebSettings$PluginState
android.webkit.WebSettings$RenderPriority
android.webkit.WebSettings$ZoomDensity
-android.webkit.WebSettingsClassic
-android.webkit.WebSettingsClassic$AutoFillProfile
-android.webkit.WebSettingsClassic$EventHandler
-android.webkit.WebSettingsClassic$EventHandler$1
android.webkit.WebStorage
-android.webkit.WebStorageClassic
-android.webkit.WebStorageClassic$1
-android.webkit.WebStorageClassic$2
android.webkit.WebSyncManager
android.webkit.WebSyncManager$SyncHandler
android.webkit.WebView
android.webkit.WebView$PrivateAccess
-android.webkit.WebViewClassic
-android.webkit.WebViewClassic$Factory
-android.webkit.WebViewClassic$OnTrimMemoryListener
-android.webkit.WebViewClassic$PackageListener
-android.webkit.WebViewClassic$PageSwapDelegate
-android.webkit.WebViewClassic$PrivateHandler
-android.webkit.WebViewClassic$ProxyReceiver
-android.webkit.WebViewClassic$SelectionHandleAlpha
-android.webkit.WebViewClassic$TitleBarDelegate
-android.webkit.WebViewClassic$TrustStorageListener
-android.webkit.WebViewClassic$ViewSizeData
android.webkit.WebViewClient
android.webkit.WebViewCore$AutoFillData
android.webkit.WebViewCore$DrawData
@@ -1278,8 +1251,6 @@ android.webkit.WebViewCore$ViewState
android.webkit.WebViewCore$WebCoreThread
android.webkit.WebViewCore$WebCoreThread$1
android.webkit.WebViewDatabase
-android.webkit.WebViewDatabaseClassic
-android.webkit.WebViewDatabaseClassic$1
android.webkit.WebViewFactory
android.webkit.WebViewFactory$Preloader
android.webkit.WebViewFactoryProvider
diff --git a/services/input/InputDispatcher.cpp b/services/input/InputDispatcher.cpp
index 795ab4740a78..9e7a15dbce24 100644
--- a/services/input/InputDispatcher.cpp
+++ b/services/input/InputDispatcher.cpp
@@ -3405,6 +3405,7 @@ void InputDispatcher::onANRLocked(
& InputDispatcher::doNotifyANRLockedInterruptible);
commandEntry->inputApplicationHandle = applicationHandle;
commandEntry->inputWindowHandle = windowHandle;
+ commandEntry->reason = reason;
}
void InputDispatcher::doNotifyConfigurationChangedInterruptible(
@@ -3434,7 +3435,8 @@ void InputDispatcher::doNotifyANRLockedInterruptible(
mLock.unlock();
nsecs_t newTimeout = mPolicy->notifyANR(
- commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle);
+ commandEntry->inputApplicationHandle, commandEntry->inputWindowHandle,
+ commandEntry->reason);
mLock.lock();
diff --git a/services/input/InputDispatcher.h b/services/input/InputDispatcher.h
index 0273dc4d62d7..190e7b221058 100644
--- a/services/input/InputDispatcher.h
+++ b/services/input/InputDispatcher.h
@@ -202,7 +202,8 @@ public:
/* Notifies the system that an application is not responding.
* Returns a new timeout to continue waiting, or 0 to abort dispatch. */
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle) = 0;
+ const sp<InputWindowHandle>& inputWindowHandle,
+ const String8& reason) = 0;
/* Notifies the system that an input channel is unrecoverably broken. */
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle) = 0;
@@ -596,6 +597,7 @@ private:
KeyEntry* keyEntry;
sp<InputApplicationHandle> inputApplicationHandle;
sp<InputWindowHandle> inputWindowHandle;
+ String8 reason;
int32_t userActivityEventType;
uint32_t seq;
bool handled;
diff --git a/services/input/tests/InputDispatcher_test.cpp b/services/input/tests/InputDispatcher_test.cpp
index ed2b4a5ebf22..26b4fab794d8 100644
--- a/services/input/tests/InputDispatcher_test.cpp
+++ b/services/input/tests/InputDispatcher_test.cpp
@@ -50,7 +50,8 @@ private:
}
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle) {
+ const sp<InputWindowHandle>& inputWindowHandle,
+ const String8& reason) {
return 0;
}
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 02a78dea3320..3f8d7ebccae4 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -58,8 +58,8 @@ import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.LinkQualityInfo;
import android.net.LinkProperties.CompareResult;
+import android.net.LinkQualityInfo;
import android.net.MobileDataStateTracker;
import android.net.NetworkConfig;
import android.net.NetworkInfo;
@@ -89,7 +89,6 @@ import android.os.ParcelFileDescriptor;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
-import android.os.ResultReceiver;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.SystemProperties;
@@ -114,7 +113,6 @@ import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.XmlUtils;
-import com.android.net.IProxyService;
import com.android.server.am.BatteryStatsService;
import com.android.server.connectivity.DataConnectionStats;
import com.android.server.connectivity.Nat464Xlat;
@@ -3209,12 +3207,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return mTethering.getTetheredIfaces();
}
- @Override
- public String[] getTetheredIfacePairs() {
- enforceTetherAccessPermission();
- return mTethering.getTetheredIfacePairs();
- }
-
public String[] getTetheringErroredIfaces() {
enforceTetherAccessPermission();
return mTethering.getErroredIfaces();
@@ -4681,6 +4673,21 @@ public class ConnectivityService extends IConnectivityManager.Stub {
setProvNotificationVisible(visible, networkType, extraInfo, url);
}
+ @Override
+ public void setAirplaneMode(boolean enable) {
+ enforceConnectivityInternalPermission();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ final ContentResolver cr = mContext.getContentResolver();
+ Settings.Global.putInt(cr, Settings.Global.AIRPLANE_MODE_ON, enable ? 1 : 0);
+ Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
+ intent.putExtra("state", enable);
+ mContext.sendBroadcast(intent);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
private void onUserStart(int userId) {
synchronized(mVpns) {
Vpn userVpn = mVpns.get(userId);
diff --git a/services/java/com/android/server/ConsumerIrService.java b/services/java/com/android/server/ConsumerIrService.java
new file mode 100644
index 000000000000..07f2a413259d
--- /dev/null
+++ b/services/java/com/android/server/ConsumerIrService.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2013 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;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.hardware.input.InputManager;
+import android.hardware.IConsumerIrService;
+import android.os.Handler;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.IBinder;
+import android.os.Binder;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.os.WorkSource;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Slog;
+import android.view.InputDevice;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+public class ConsumerIrService extends IConsumerIrService.Stub {
+ private static final String TAG = "ConsumerIrService";
+
+ private static final int MAX_XMIT_TIME = 2000000; /* in microseconds */
+
+ private static native int halOpen();
+ private static native int halTransmit(int halObject, int carrierFrequency, int[] pattern);
+ private static native int[] halGetCarrierFrequencies(int halObject);
+
+ private final Context mContext;
+ private final PowerManager.WakeLock mWakeLock;
+ private final int mHal;
+ private final Object mHalLock = new Object();
+
+ ConsumerIrService(Context context) {
+ mContext = context;
+ PowerManager pm = (PowerManager)context.getSystemService(
+ Context.POWER_SERVICE);
+ mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
+ mWakeLock.setReferenceCounted(true);
+
+ mHal = halOpen();
+ if (mHal == 0) {
+ Slog.w(TAG, "No IR HAL loaded");
+ }
+ }
+
+ @Override
+ public boolean hasIrEmitter() {
+ return mHal != 0;
+ }
+
+ private void throwIfNoIrEmitter() {
+ if (mHal == 0) {
+ throw new UnsupportedOperationException("IR emitter not available");
+ }
+ }
+
+
+ @Override
+ public void transmit(String packageName, int carrierFrequency, int[] pattern) {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires TRANSMIT_IR permission");
+ }
+
+ long totalXmitTime = 0;
+
+ for (int slice : pattern) {
+ if (slice <= 0) {
+ throw new IllegalArgumentException("Non-positive IR slice");
+ }
+ totalXmitTime += slice;
+ }
+
+ if (totalXmitTime > MAX_XMIT_TIME ) {
+ throw new IllegalArgumentException("IR pattern too long");
+ }
+
+ throwIfNoIrEmitter();
+
+ // Right now there is no mechanism to ensure fair queing of IR requests
+ synchronized (mHalLock) {
+ int err = halTransmit(mHal, carrierFrequency, pattern);
+
+ if (err < 0) {
+ Slog.e(TAG, "Error transmitting: " + err);
+ }
+ }
+ }
+
+ @Override
+ public int[] getCarrierFrequencies() {
+ if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.TRANSMIT_IR)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Requires TRANSMIT_IR permission");
+ }
+
+ throwIfNoIrEmitter();
+
+ synchronized(mHalLock) {
+ return halGetCarrierFrequencies(mHal);
+ }
+ }
+}
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index de29155a8f95..f70f4dbd00e5 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -1773,8 +1773,12 @@ public class LocationManagerService extends ILocationManager.Stub {
@Override
public boolean isProviderEnabled(String provider) {
+ // TODO: remove this check in next release, see b/10696351
checkResolutionLevelIsSufficientForProviderUse(getCallerAllowedResolutionLevel(),
provider);
+
+ // Fused provider is accessed indirectly via criteria rather than the provider-based APIs,
+ // so we discourage its use
if (LocationManager.FUSED_PROVIDER.equals(provider)) return false;
int uid = Binder.getCallingUid();
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index 82cc54007e4d..92f99c2e4aec 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -24,15 +24,15 @@ import static android.net.NetworkStats.TAG_NONE;
import static android.net.NetworkStats.UID_ALL;
import static android.net.TrafficStats.UID_TETHERING;
import static com.android.server.NetworkManagementService.NetdResponseCode.ClatdStatusResult;
+import static com.android.server.NetworkManagementService.NetdResponseCode.GetMarkResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceGetCfgResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.InterfaceListResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.IpFwdStatusResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.TetherDnsFwdTgtListResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.TetherInterfaceListResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.TetherStatusResult;
-import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsResult;
+import static com.android.server.NetworkManagementService.NetdResponseCode.TetheringStatsListResult;
import static com.android.server.NetworkManagementService.NetdResponseCode.TtyListResult;
-import static com.android.server.NetworkManagementService.NetdResponseCode.GetMarkResult;
import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENABLED;
import android.content.Context;
@@ -118,6 +118,7 @@ public class NetworkManagementService extends INetworkManagementService.Stub
public static final int TetherInterfaceListResult = 111;
public static final int TetherDnsFwdTgtListResult = 112;
public static final int TtyListResult = 113;
+ public static final int TetheringStatsListResult = 114;
public static final int TetherStatusResult = 210;
public static final int IpFwdStatusResult = 211;
@@ -523,7 +524,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
throw new IllegalStateException(msg);
}
- int flags, scope;
+ int flags;
+ int scope;
try {
flags = Integer.parseInt(cooked[5]);
scope = Integer.parseInt(cooked[6]);
@@ -1373,55 +1375,42 @@ public class NetworkManagementService extends INetworkManagementService.Stub
}
@Override
- public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
+ public NetworkStats getNetworkStatsTethering() {
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
- if (ifacePairs.length % 2 != 0) {
- throw new IllegalArgumentException(
- "unexpected ifacePairs; length=" + ifacePairs.length);
- }
-
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
- for (int i = 0; i < ifacePairs.length; i += 2) {
- final String ifaceIn = ifacePairs[i];
- final String ifaceOut = ifacePairs[i + 1];
- if (ifaceIn != null && ifaceOut != null) {
- stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
- }
- }
- return stats;
- }
-
- private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
- final NativeDaemonEvent event;
try {
- event = mConnector.execute("bandwidth", "gettetherstats", ifaceIn, ifaceOut);
+ final NativeDaemonEvent[] events = mConnector.executeForList(
+ "bandwidth", "gettetherstats");
+ for (NativeDaemonEvent event : events) {
+ if (event.getCode() != TetheringStatsListResult) continue;
+
+ // 114 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
+ final StringTokenizer tok = new StringTokenizer(event.getMessage());
+ try {
+ final String ifaceIn = tok.nextToken();
+ final String ifaceOut = tok.nextToken();
+
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+ entry.iface = ifaceOut;
+ entry.uid = UID_TETHERING;
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = Long.parseLong(tok.nextToken());
+ entry.rxPackets = Long.parseLong(tok.nextToken());
+ entry.txBytes = Long.parseLong(tok.nextToken());
+ entry.txPackets = Long.parseLong(tok.nextToken());
+ stats.combineValues(entry);
+ } catch (NoSuchElementException e) {
+ throw new IllegalStateException("problem parsing tethering stats: " + event);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("problem parsing tethering stats: " + event);
+ }
+ }
} catch (NativeDaemonConnectorException e) {
throw e.rethrowAsParcelableException();
}
-
- event.checkCode(TetheringStatsResult);
-
- // 221 ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets
- final StringTokenizer tok = new StringTokenizer(event.getMessage());
- tok.nextToken();
- tok.nextToken();
-
- try {
- final NetworkStats.Entry entry = new NetworkStats.Entry();
- entry.iface = ifaceIn;
- entry.uid = UID_TETHERING;
- entry.set = SET_DEFAULT;
- entry.tag = TAG_NONE;
- entry.rxBytes = Long.parseLong(tok.nextToken());
- entry.rxPackets = Long.parseLong(tok.nextToken());
- entry.txBytes = Long.parseLong(tok.nextToken());
- entry.txPackets = Long.parseLong(tok.nextToken());
- return entry;
- } catch (NumberFormatException e) {
- throw new IllegalStateException(
- "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
- }
+ return stats;
}
@Override
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 0bbdcfb230e3..d38756f6fb13 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -154,6 +154,7 @@ class ServerThread {
CommonTimeManagementService commonTimeMgmtService = null;
InputManagerService inputManager = null;
TelephonyRegistry telephonyRegistry = null;
+ ConsumerIrService consumerIr = null;
// Create a handler thread just for the window manager to enjoy.
HandlerThread wmHandlerThread = new HandlerThread("WindowManager");
@@ -284,6 +285,10 @@ class ServerThread {
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
+ Slog.i(TAG, "Consumer IR Service");
+ consumerIr = new ConsumerIrService(context);
+ ServiceManager.addService(Context.CONSUMER_IR_SERVICE, consumerIr);
+
// only initialize the power service after we have started the
// lights service, content providers and the battery service.
power.init(context, lights, ActivityManagerService.self(), battery,
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 75cf5d03c8a4..96b7030dba4b 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -187,7 +187,6 @@ import java.io.StringWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -314,10 +313,6 @@ public final class ActivityManagerService extends ActivityManagerNative
// to respond with the result.
static final int PENDING_ASSIST_EXTRAS_TIMEOUT = 500;
- // Index for assist context bundle pertaining to the top activity. Non-negative indices
- // correspond to assist context bundles from foreground services.
- static final int TOP_ACTIVITY_ASSIST_EXTRAS_INDEX = -1;
-
static final int MY_PID = Process.myPid();
static final String[] EMPTY_STRING_ARRAY = new String[0];
@@ -394,30 +389,16 @@ public final class ActivityManagerService extends ActivityManagerNative
public class PendingAssistExtras extends Binder implements Runnable {
public final ActivityRecord activity;
- public final List<ServiceRecord> services;
- public int numPending;
- public int numRespondedServices = 0;
- public Bundle activityExtras = null;
- public Bundle[] servicesExtras;
- public PendingAssistExtras(ActivityRecord _activity, List<ServiceRecord> _services) {
+ public boolean haveResult = false;
+ public Bundle result = null;
+ public PendingAssistExtras(ActivityRecord _activity) {
activity = _activity;
- services = _services;
- numPending = services.size() + 1;
}
@Override
public void run() {
- if (activityExtras == null) {
- Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from activtity "
- + activity);
- }
- for (int i = 0; i < services.size(); i++) {
- if (servicesExtras[i] == null) {
- Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from service "
- + i + " " + services.get(i));
- }
- }
+ Slog.w(TAG, "getAssistContextExtras failed: timeout retrieving from " + activity);
synchronized (this) {
- numPending = 0;
+ haveResult = true;
notifyAll();
}
}
@@ -1574,12 +1555,12 @@ public final class ActivityManagerService extends ActivityManagerNative
mSystemThread.installSystemApplicationInfo(info);
synchronized (mSelf) {
- ProcessRecord app = mSelf.newProcessRecordLocked(
- mSystemThread.getApplicationThread(), info,
+ ProcessRecord app = mSelf.newProcessRecordLocked(info,
info.processName, false);
app.persistent = true;
app.pid = MY_PID;
app.maxAdj = ProcessList.SYSTEM_ADJ;
+ app.makeActive(mSystemThread.getApplicationThread(), mSelf.mProcessStats);
mSelf.mProcessNames.put(app.processName, app.uid, app);
synchronized (mSelf.mPidsSelfLocked) {
mSelf.mPidsSelfLocked.put(app.pid, app);
@@ -2282,7 +2263,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (app == null) {
- app = newProcessRecordLocked(null, info, processName, isolated);
+ app = newProcessRecordLocked(info, processName, isolated);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
@@ -3628,6 +3609,7 @@ public final class ActivityManagerService extends ActivityManagerNative
info.append(" (").append(activity.shortComponentName).append(")");
}
info.append("\n");
+ info.append("PID: ").append(app.pid).append("\n");
if (annotation != null) {
info.append("Reason: ").append(annotation).append("\n");
}
@@ -4487,7 +4469,7 @@ public final class ActivityManagerService extends ActivityManagerNative
EventLog.writeEvent(EventLogTags.AM_PROC_BOUND, app.userId, app.pid, app.processName);
- app.thread = thread;
+ app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
@@ -7544,8 +7526,8 @@ public final class ActivityManagerService extends ActivityManagerNative
// GLOBAL MANAGEMENT
// =========================================================
- final ProcessRecord newProcessRecordLocked(IApplicationThread thread,
- ApplicationInfo info, String customProcess, boolean isolated) {
+ final ProcessRecord newProcessRecordLocked(ApplicationInfo info, String customProcess,
+ boolean isolated) {
String proc = customProcess != null ? customProcess : info.processName;
BatteryStatsImpl.Uid.Proc ps = null;
BatteryStatsImpl stats = mBatteryStatsService.getActiveStatistics();
@@ -7573,8 +7555,7 @@ public final class ActivityManagerService extends ActivityManagerNative
synchronized (stats) {
ps = stats.getProcessStatsLocked(info.uid, proc);
}
- return new ProcessRecord(ps, thread, info, proc, uid,
- mProcessStats.getProcessStateLocked(info.packageName, info.uid, proc));
+ return new ProcessRecord(ps, info, proc, uid);
}
final ProcessRecord addAppLocked(ApplicationInfo info, boolean isolated) {
@@ -7586,7 +7567,7 @@ public final class ActivityManagerService extends ActivityManagerNative
}
if (app == null) {
- app = newProcessRecordLocked(null, info, null, isolated);
+ app = newProcessRecordLocked(info, null, isolated);
mProcessNames.put(info.processName, app.uid, app);
if (isolated) {
mIsolatedProcesses.put(app.uid, app);
@@ -7970,8 +7951,8 @@ public final class ActivityManagerService extends ActivityManagerNative
return KEY_DISPATCHING_TIMEOUT;
}
-
- public long inputDispatchingTimedOut(int pid, final boolean aboveSystem) {
+ @Override
+ public long inputDispatchingTimedOut(int pid, final boolean aboveSystem, String reason) {
if (checkCallingPermission(android.Manifest.permission.FILTER_EVENTS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
@@ -7986,7 +7967,7 @@ public final class ActivityManagerService extends ActivityManagerNative
timeout = getInputDispatchingTimeoutLocked(proc);
}
- if (!inputDispatchingTimedOut(proc, null, null, aboveSystem)) {
+ if (!inputDispatchingTimedOut(proc, null, null, aboveSystem, reason)) {
return -1;
}
@@ -7999,13 +7980,20 @@ public final class ActivityManagerService extends ActivityManagerNative
*/
public boolean inputDispatchingTimedOut(final ProcessRecord proc,
final ActivityRecord activity, final ActivityRecord parent,
- final boolean aboveSystem) {
+ final boolean aboveSystem, String reason) {
if (checkCallingPermission(android.Manifest.permission.FILTER_EVENTS)
!= PackageManager.PERMISSION_GRANTED) {
throw new SecurityException("Requires permission "
+ android.Manifest.permission.FILTER_EVENTS);
}
+ final String annotation;
+ if (reason == null) {
+ annotation = "Input dispatching timed out";
+ } else {
+ annotation = "Input dispatching timed out (" + reason + ")";
+ }
+
if (proc != null) {
synchronized (this) {
if (proc.debugging) {
@@ -8021,7 +8009,7 @@ public final class ActivityManagerService extends ActivityManagerNative
if (proc.instrumentationClass != null) {
Bundle info = new Bundle();
info.putString("shortMsg", "keyDispatchingTimedOut");
- info.putString("longMsg", "Timed out while dispatching key event");
+ info.putString("longMsg", annotation);
finishInstrumentationLocked(proc, Activity.RESULT_CANCELED, info);
return true;
}
@@ -8029,7 +8017,7 @@ public final class ActivityManagerService extends ActivityManagerNative
mHandler.post(new Runnable() {
@Override
public void run() {
- appNotResponding(proc, activity, parent, aboveSystem, "keyDispatchingTimedOut");
+ appNotResponding(proc, activity, parent, aboveSystem, annotation);
}
});
}
@@ -8042,81 +8030,41 @@ public final class ActivityManagerService extends ActivityManagerNative
"getAssistContextExtras()");
PendingAssistExtras pae;
Bundle extras = new Bundle();
- List<ServiceRecord> foregroundServices;
synchronized (this) {
- Collection<ServiceRecord> allServices = mServices.mServiceMap.getAllServices(
- Binder.getCallingUid());
- foregroundServices = new ArrayList<ServiceRecord>();
- for (ServiceRecord record : allServices) {
- if ((record.serviceInfo.flags & ServiceInfo.FLAG_PROVIDE_ASSIST_DATA) > 0 &&
- record.isForeground) {
- if (record.app == null || record.app.thread == null) {
- Slog.w(TAG, "getAssistContextExtras error: no process for " + record);
- continue;
- }
- if (record.app.pid == Binder.getCallingPid()) {
- Slog.w(TAG, "getAssistContextExtras error: request process same as " +
- record);
- continue;
- }
- foregroundServices.add(record);
- }
- }
-
ActivityRecord activity = getFocusedStack().mResumedActivity;
- boolean validActivity = true;
if (activity == null) {
- Slog.w(TAG, "getAssistContextExtras error: no resumed activity");
- validActivity = false;
- } else if (activity.app == null || activity.app.thread == null) {
- Slog.w(TAG, "getAssistContextExtras error: no process for " + activity);
- validActivity = false;
- } else if (activity.app.pid == Binder.getCallingPid()) {
- Slog.w(TAG, "getAssistContextExtras error: request process same as " + activity);
- validActivity = false;
+ Slog.w(TAG, "getAssistContextExtras failed: no resumed activity");
+ return null;
}
-
- pae = new PendingAssistExtras(activity, foregroundServices);
+ extras.putString(Intent.EXTRA_ASSIST_PACKAGE, activity.packageName);
+ if (activity.app == null || activity.app.thread == null) {
+ Slog.w(TAG, "getAssistContextExtras failed: no process for " + activity);
+ return extras;
+ }
+ if (activity.app.pid == Binder.getCallingPid()) {
+ Slog.w(TAG, "getAssistContextExtras failed: request process same as " + activity);
+ return extras;
+ }
+ pae = new PendingAssistExtras(activity);
try {
- if (validActivity) {
- activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
- requestType, -1);
- }
- for (int i = 0; i < foregroundServices.size(); i++) {
- ServiceRecord record = foregroundServices.get(i);
- record.app.thread.requestAssistContextExtras(record, pae, requestType, i);
- }
+ activity.app.thread.requestAssistContextExtras(activity.appToken, pae,
+ requestType);
mPendingAssistExtras.add(pae);
mHandler.postDelayed(pae, PENDING_ASSIST_EXTRAS_TIMEOUT);
} catch (RemoteException e) {
- Slog.w(TAG, "getAssistContextExtras failed: crash fetching extras.", e);
+ Slog.w(TAG, "getAssistContextExtras failed: crash calling " + activity);
+ return extras;
}
}
synchronized (pae) {
- while (pae.numPending > 0) {
+ while (!pae.haveResult) {
try {
pae.wait();
} catch (InterruptedException e) {
}
}
- if (pae.activityExtras != null) {
- extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.activityExtras);
- extras.putString(Intent.EXTRA_ASSIST_PACKAGE, pae.activity.packageName);
- }
- if (pae.numRespondedServices > 0) {
- Bundle[] servicesExtras = new Bundle[pae.numRespondedServices];
- String[] servicesPackages = new String[pae.numRespondedServices];
- int extrasIndex = 0;
- for (int i = 0; i < foregroundServices.size(); i++) {
- if (pae.servicesExtras[i] != null) {
- servicesExtras[extrasIndex] = pae.servicesExtras[i];
- ServiceRecord record = foregroundServices.get(i);
- servicesPackages[extrasIndex] = record.packageName;
- extrasIndex++;
- }
- }
- extras.putParcelableArray(Intent.EXTRA_ASSIST_SERVICES_CONTEXTS, servicesExtras);
- extras.putStringArray(Intent.EXTRA_ASSIST_SERVICES_PACKAGES, servicesPackages);
+ if (pae.result != null) {
+ extras.putBundle(Intent.EXTRA_ASSIST_CONTEXT, pae.result);
}
}
synchronized (this) {
@@ -8126,19 +8074,12 @@ public final class ActivityManagerService extends ActivityManagerNative
return extras;
}
- public void reportAssistContextExtras(IBinder token, Bundle extras, int index) {
+ public void reportAssistContextExtras(IBinder token, Bundle extras) {
PendingAssistExtras pae = (PendingAssistExtras)token;
synchronized (pae) {
- if (index == TOP_ACTIVITY_ASSIST_EXTRAS_INDEX) {
- pae.activityExtras = extras;
- } else {
- pae.servicesExtras[index] = extras;
- pae.numRespondedServices++;
- }
- pae.numPending--;
- if (pae.numPending == 0) {
- pae.notifyAll();
- }
+ pae.result = extras;
+ pae.haveResult = true;
+ pae.notifyAll();
}
}
@@ -11788,7 +11729,7 @@ public final class ActivityManagerService extends ActivityManagerNative
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
- app.thread = null;
+ app.makeInactive(mProcessStats);
app.forcingToForeground = null;
app.foregroundServices = false;
app.foregroundActivities = false;
@@ -14692,7 +14633,9 @@ public final class ActivityManagerService extends ActivityManagerNative
}
private final void setProcessTrackerState(ProcessRecord proc, int memFactor, long now) {
- proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList);
+ if (proc.thread != null) {
+ proc.baseProcessTracker.setState(proc.repProcState, memFactor, now, proc.pkgList);
+ }
}
private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
diff --git a/services/java/com/android/server/am/ActivityRecord.java b/services/java/com/android/server/am/ActivityRecord.java
index bf3713b3b538..6e50808ae122 100644
--- a/services/java/com/android/server/am/ActivityRecord.java
+++ b/services/java/com/android/server/am/ActivityRecord.java
@@ -305,9 +305,9 @@ final class ActivityRecord {
}
}
- @Override public boolean keyDispatchingTimedOut() {
+ @Override public boolean keyDispatchingTimedOut(String reason) {
ActivityRecord activity = weakActivity.get();
- return activity != null && activity.keyDispatchingTimedOut();
+ return activity != null && activity.keyDispatchingTimedOut(reason);
}
@Override public long getKeyDispatchingTimeout() {
@@ -960,14 +960,14 @@ final class ActivityRecord {
return r;
}
- public boolean keyDispatchingTimedOut() {
+ public boolean keyDispatchingTimedOut(String reason) {
ActivityRecord r;
ProcessRecord anrApp;
synchronized(service) {
r = getWaitingHistoryRecordLocked();
anrApp = r != null ? r.app : null;
}
- return service.inputDispatchingTimedOut(anrApp, r, this, false);
+ return service.inputDispatchingTimedOut(anrApp, r, this, false, reason);
}
/** Returns the key dispatching timeout for this application token. */
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 8d27c5cb39b4..e994c23b3530 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -620,7 +620,13 @@ final class ActivityStack {
}
void clearLaunchTime(ActivityRecord r) {
- r.displayStartTime = r.fullyDrawnStartTime = 0;
+ // Make sure that there is no activity waiting for this to launch.
+ if (mStackSupervisor.mWaitingActivityLaunched.isEmpty()) {
+ r.displayStartTime = r.fullyDrawnStartTime = 0;
+ } else {
+ mStackSupervisor.removeTimeoutsForActivityLocked(r);
+ mStackSupervisor.scheduleIdleTimeoutLocked(r);
+ }
}
void awakeFromSleepingLocked() {
@@ -1110,8 +1116,10 @@ final class ActivityStack {
case PAUSED:
// This case created for transitioning activities from
// translucent to opaque {@link Activity#convertToOpaque}.
- mStackSupervisor.mStoppingActivities.remove(r);
- stopActivityLocked(r);
+ if (!mStackSupervisor.mStoppingActivities.contains(r)) {
+ mStackSupervisor.mStoppingActivities.add(r);
+ }
+ mStackSupervisor.scheduleIdleLocked();
break;
default:
diff --git a/services/java/com/android/server/am/ProcessRecord.java b/services/java/com/android/server/am/ProcessRecord.java
index f1a030e731da..283d122c8c02 100644
--- a/services/java/com/android/server/am/ProcessRecord.java
+++ b/services/java/com/android/server/am/ProcessRecord.java
@@ -52,13 +52,13 @@ final class ProcessRecord {
final int uid; // uid of process; may be different from 'info' if isolated
final int userId; // user of process.
final String processName; // name of the process
- final ProcessStats.ProcessState baseProcessTracker;
// List of packages running in the process
final ArrayMap<String, ProcessStats.ProcessState> pkgList
= new ArrayMap<String, ProcessStats.ProcessState>();
IApplicationThread thread; // the actual proc... may be null only if
// 'persistent' is true (in which case we
// are in the process of launching the app)
+ ProcessStats.ProcessState baseProcessTracker;
int pid; // The process of this application; 0 if none
boolean starting; // True if the process is being started
long lastActivityTime; // For managing the LRU list
@@ -349,18 +349,15 @@ final class ProcessRecord {
}
}
- ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, IApplicationThread _thread,
- ApplicationInfo _info, String _processName, int _uid,
- ProcessStats.ProcessState tracker) {
+ ProcessRecord(BatteryStatsImpl.Uid.Proc _batteryStats, ApplicationInfo _info,
+ String _processName, int _uid) {
batteryStats = _batteryStats;
info = _info;
isolated = _info.uid != _uid;
uid = _uid;
userId = UserHandle.getUserId(_uid);
processName = _processName;
- baseProcessTracker = tracker;
- pkgList.put(_info.packageName, tracker);
- thread = _thread;
+ pkgList.put(_info.packageName, null);
maxAdj = ProcessList.UNKNOWN_ADJ;
curRawAdj = setRawAdj = -100;
curAdj = setAdj = -100;
@@ -374,7 +371,53 @@ final class ProcessRecord {
shortStringName = null;
stringName = null;
}
-
+
+ public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
+ if (thread == null) {
+ final ProcessStats.ProcessState origBase = baseProcessTracker;
+ if (origBase != null) {
+ origBase.setState(ProcessStats.STATE_NOTHING,
+ tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList);
+ origBase.makeInactive();
+ }
+ baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid,
+ processName);
+ baseProcessTracker.makeActive();
+ for (int i=0; i<pkgList.size(); i++) {
+ ProcessStats.ProcessState ps = pkgList.valueAt(i);
+ if (ps != null && ps != origBase) {
+ ps.makeInactive();
+ }
+ ps = tracker.getProcessStateLocked(pkgList.keyAt(i), info.uid, processName);
+ if (ps != baseProcessTracker) {
+ ps.makeActive();
+ }
+ pkgList.setValueAt(i, ps);
+ }
+ }
+ thread = _thread;
+ }
+
+ public void makeInactive(ProcessStatsService tracker) {
+ if (thread != null) {
+ thread = null;
+ final ProcessStats.ProcessState origBase = baseProcessTracker;
+ if (origBase != null) {
+ origBase.setState(ProcessStats.STATE_NOTHING,
+ tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList);
+ origBase.makeInactive();
+ }
+ baseProcessTracker = null;
+ for (int i=0; i<pkgList.size(); i++) {
+ ProcessStats.ProcessState ps = pkgList.valueAt(i);
+ if (ps != null && ps != origBase) {
+ ps.makeInactive();
+ }
+ pkgList.setValueAt(i, null);
+ }
+ }
+ }
+
/**
* This method returns true if any of the activities within the process record are interesting
* to the user. See HistoryRecord.isInterestingToUserLocked()
@@ -518,10 +561,22 @@ final class ProcessRecord {
long now = SystemClock.uptimeMillis();
baseProcessTracker.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), now, pkgList);
- if (pkgList.size() != 1) {
+ final int N = pkgList.size();
+ if (N != 1) {
+ for (int i=0; i<N; i++) {
+ ProcessStats.ProcessState ps = pkgList.valueAt(i);
+ if (ps != null && ps != baseProcessTracker) {
+ ps.makeInactive();
+ }
+
+ }
pkgList.clear();
- pkgList.put(info.packageName, tracker.getProcessStateLocked(
- info.packageName, info.uid, processName));
+ ProcessStats.ProcessState ps = tracker.getProcessStateLocked(
+ info.packageName, info.uid, processName);
+ pkgList.put(info.packageName, ps);
+ if (thread != null && ps != baseProcessTracker) {
+ ps.makeActive();
+ }
}
}
diff --git a/services/java/com/android/server/am/ProcessStatsService.java b/services/java/com/android/server/am/ProcessStatsService.java
index 43ae46fd33c4..c180f6e38b28 100644
--- a/services/java/com/android/server/am/ProcessStatsService.java
+++ b/services/java/com/android/server/am/ProcessStatsService.java
@@ -54,12 +54,12 @@ public final class ProcessStatsService extends IProcessStats.Stub {
// exists in and the offset into the array to find it. The constants below
// define the encoding of that data in an integer.
- static final int MAX_HISTORIC_STATES = 4; // Maximum number of historic states we will keep.
+ static final int MAX_HISTORIC_STATES = 6; // Maximum number of historic states we will keep.
static final String STATE_FILE_PREFIX = "state-"; // Prefix to use for state filenames.
static final String STATE_FILE_SUFFIX = ".bin"; // Suffix to use for state filenames.
static final String STATE_FILE_CHECKIN_SUFFIX = ".ci"; // State files that have checked in.
static long WRITE_PERIOD = 30*60*1000; // Write file every 30 minutes or so.
- static long COMMIT_PERIOD = 24*60*60*1000; // Commit current stats every day.
+ static long COMMIT_PERIOD = 12*60*60*1000; // Commit current stats every 12 hours.
final ActivityManagerService mAm;
final File mBaseDir;
@@ -132,7 +132,7 @@ public final class ProcessStatsService extends IProcessStats.Stub {
ArrayMap<String, ProcessStats.ServiceState> services = pkg.mServices;
for (int k=0; k<services.size(); k++) {
ProcessStats.ServiceState service = services.valueAt(k);
- if (service.isActive()) {
+ if (service.isInUse()) {
if (service.mStartedState != ProcessStats.STATE_NOTHING) {
service.setStarted(true, memFactor, now);
}
diff --git a/services/java/com/android/server/am/ServiceRecord.java b/services/java/com/android/server/am/ServiceRecord.java
index 39756c349feb..8293bb8a2a37 100644
--- a/services/java/com/android/server/am/ServiceRecord.java
+++ b/services/java/com/android/server/am/ServiceRecord.java
@@ -318,6 +318,7 @@ final class ServiceRecord extends Binder {
if ((serviceInfo.applicationInfo.flags&ApplicationInfo.FLAG_PERSISTENT) == 0) {
tracker = ams.mProcessStats.getServiceStateLocked(serviceInfo.packageName,
serviceInfo.applicationInfo.uid, serviceInfo.processName, serviceInfo.name);
+ tracker.makeActive();
}
return tracker;
}
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index fb4c1cf2f46e..231a40aef67f 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -688,19 +688,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
return retVal;
}
- public String[] getTetheredIfacePairs() {
- final ArrayList<String> list = Lists.newArrayList();
- synchronized (mPublicSync) {
- for (TetherInterfaceSM sm : mIfaces.values()) {
- if (sm.isTethered()) {
- list.add(sm.mMyUpstreamIfaceName);
- list.add(sm.mIfaceName);
- }
- }
- }
- return list.toArray(new String[list.size()]);
- }
-
public String[] getTetherableIfaces() {
ArrayList<String> list = new ArrayList<String>();
synchronized (mPublicSync) {
diff --git a/services/java/com/android/server/input/InputManagerService.java b/services/java/com/android/server/input/InputManagerService.java
index 7b4c0775e47e..d749e6c626a4 100644
--- a/services/java/com/android/server/input/InputManagerService.java
+++ b/services/java/com/android/server/input/InputManagerService.java
@@ -1292,8 +1292,9 @@ public class InputManagerService extends IInputManager.Stub
// Native callback.
private long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle) {
- return mWindowManagerCallbacks.notifyANR(inputApplicationHandle, inputWindowHandle);
+ InputWindowHandle inputWindowHandle, String reason) {
+ return mWindowManagerCallbacks.notifyANR(
+ inputApplicationHandle, inputWindowHandle, reason);
}
// Native callback.
@@ -1477,7 +1478,7 @@ public class InputManagerService extends IInputManager.Stub
public void notifyInputChannelBroken(InputWindowHandle inputWindowHandle);
public long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle);
+ InputWindowHandle inputWindowHandle, String reason);
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
diff --git a/services/java/com/android/server/location/FlpHardwareProvider.java b/services/java/com/android/server/location/FlpHardwareProvider.java
index ebeccfb6e6bf..60893b83943a 100644
--- a/services/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/java/com/android/server/location/FlpHardwareProvider.java
@@ -141,10 +141,16 @@ public class FlpHardwareProvider {
}
private void onGeofenceMonitorStatus(int status, int source, Location location) {
+ // allow the location to be optional in this event
+ Location updatedLocation = null;
+ if(location != null) {
+ updatedLocation = updateLocationInformation(location);
+ }
+
getGeofenceHardwareSink().reportGeofenceMonitorStatus(
GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
status,
- updateLocationInformation(location),
+ updatedLocation,
source);
}
diff --git a/services/java/com/android/server/net/NetworkStatsRecorder.java b/services/java/com/android/server/net/NetworkStatsRecorder.java
index 2b32b4150617..cea084b51849 100644
--- a/services/java/com/android/server/net/NetworkStatsRecorder.java
+++ b/services/java/com/android/server/net/NetworkStatsRecorder.java
@@ -135,6 +135,9 @@ public class NetworkStatsRecorder {
} catch (IOException e) {
Log.wtf(TAG, "problem completely reading network stats", e);
recoverFromWtf();
+ } catch (OutOfMemoryError e) {
+ Log.wtf(TAG, "problem completely reading network stats", e);
+ recoverFromWtf();
}
}
return complete;
@@ -226,6 +229,9 @@ public class NetworkStatsRecorder {
} catch (IOException e) {
Log.wtf(TAG, "problem persisting pending stats", e);
recoverFromWtf();
+ } catch (OutOfMemoryError e) {
+ Log.wtf(TAG, "problem persisting pending stats", e);
+ recoverFromWtf();
}
}
}
@@ -241,6 +247,9 @@ public class NetworkStatsRecorder {
} catch (IOException e) {
Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e);
recoverFromWtf();
+ } catch (OutOfMemoryError e) {
+ Log.wtf(TAG, "problem removing UIDs " + Arrays.toString(uids), e);
+ recoverFromWtf();
}
// Remove any pending stats
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index 05eeb36195ee..1e8a7b0176a9 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -412,6 +412,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
} catch (IOException e) {
Log.wtf(TAG, "problem during legacy upgrade", e);
+ } catch (OutOfMemoryError e) {
+ Log.wtf(TAG, "problem during legacy upgrade", e);
}
}
@@ -1186,8 +1188,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/
private NetworkStats getNetworkStatsTethering() throws RemoteException {
try {
- final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
- return mNetworkManager.getNetworkStatsTethering(tetheredIfacePairs);
+ return mNetworkManager.getNetworkStatsTethering();
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
return new NetworkStats(0L, 10);
diff --git a/services/java/com/android/server/pm/Settings.java b/services/java/com/android/server/pm/Settings.java
index 415cda19ecf2..92026b2bb6ba 100644
--- a/services/java/com/android/server/pm/Settings.java
+++ b/services/java/com/android/server/pm/Settings.java
@@ -1395,9 +1395,8 @@ final class Settings {
final boolean isDebug = (ai.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
final int[] gids = pkg.getGids();
- // Avoid any application that has a space in its path
- // or that is handled by the system.
- if (dataPath.indexOf(" ") >= 0 || ai.uid < Process.FIRST_APPLICATION_UID)
+ // Avoid any application that has a space in its path.
+ if (dataPath.indexOf(" ") >= 0)
continue;
// we store on each line the following information for now:
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 0d92f660b6ca..729bd1669e83 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -35,6 +35,7 @@ import android.util.FloatMath;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -94,7 +95,7 @@ final class ElectronBeam {
// Texture names. We only use one texture, which contains the screenshot.
private final int[] mTexNames = new int[1];
private boolean mTexNamesGenerated;
- private float mTexMatrix[] = new float[16];
+ private final float mTexMatrix[] = new float[16];
// Vertex and corresponding texture coordinates.
// We have 4 2D vertices, so 8 elements. The vertices form a quad.
@@ -515,7 +516,7 @@ final class ElectronBeam {
mSurfaceControl = new SurfaceControl(mSurfaceSession,
"ElectronBeam", mDisplayWidth, mDisplayHeight,
PixelFormat.OPAQUE, flags);
- } catch (SurfaceControl.OutOfResourcesException ex) {
+ } catch (OutOfResourcesException ex) {
Slog.e(TAG, "Unable to create surface.", ex);
return false;
}
@@ -525,7 +526,7 @@ final class ElectronBeam {
mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
mSurface = new Surface();
mSurface.copyFrom(mSurfaceControl);
-
+
mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl);
mSurfaceLayout.onDisplayTransaction();
} finally {
diff --git a/services/java/com/android/server/power/WirelessChargerDetector.java b/services/java/com/android/server/power/WirelessChargerDetector.java
index ac6dc3e6f299..35920f79a0c4 100644
--- a/services/java/com/android/server/power/WirelessChargerDetector.java
+++ b/services/java/com/android/server/power/WirelessChargerDetector.java
@@ -21,6 +21,7 @@ import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.BatteryManager;
+import android.os.SystemClock;
import android.util.Slog;
import java.io.PrintWriter;
@@ -130,6 +131,10 @@ final class WirelessChargerDetector {
private long mFirstSampleTime;
private float mFirstSampleX, mFirstSampleY, mFirstSampleZ;
+ // The time and value of the last sample that was collected (for debugging only).
+ private long mLastSampleTime;
+ private float mLastSampleX, mLastSampleY, mLastSampleZ;
+
public WirelessChargerDetector(SensorManager sensorManager,
SuspendBlocker suspendBlocker) {
mSensorManager = sensorManager;
@@ -153,6 +158,9 @@ final class WirelessChargerDetector {
pw.println(" mFirstSampleTime=" + mFirstSampleTime);
pw.println(" mFirstSampleX=" + mFirstSampleX
+ ", mFirstSampleY=" + mFirstSampleY + ", mFirstSampleZ=" + mFirstSampleZ);
+ pw.println(" mLastSampleTime=" + mLastSampleTime);
+ pw.println(" mLastSampleX=" + mLastSampleX
+ + ", mLastSampleY=" + mLastSampleY + ", mLastSampleZ=" + mLastSampleZ);
}
}
@@ -224,6 +232,11 @@ final class WirelessChargerDetector {
return;
}
+ mLastSampleTime = timeNanos;
+ mLastSampleX = x;
+ mLastSampleY = y;
+ mLastSampleZ = z;
+
mTotalSamples += 1;
if (mTotalSamples == 1) {
// Save information about the first sample collected.
@@ -310,7 +323,10 @@ final class WirelessChargerDetector {
private final SensorEventListener mListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
- processSample(event.timestamp, event.values[0], event.values[1], event.values[2]);
+ // We use SystemClock.elapsedRealtimeNanos() instead of event.timestamp because
+ // on some devices the sensor HAL may produce timestamps that are not monotonic.
+ processSample(SystemClock.elapsedRealtimeNanos(),
+ event.values[0], event.values[1], event.values[2]);
}
@Override
diff --git a/services/java/com/android/server/print/PrintManagerService.java b/services/java/com/android/server/print/PrintManagerService.java
index 2563b580f674..926f822d0eda 100644
--- a/services/java/com/android/server/print/PrintManagerService.java
+++ b/services/java/com/android/server/print/PrintManagerService.java
@@ -41,6 +41,8 @@ import android.util.SparseArray;
import com.android.internal.content.PackageMonitor;
import com.android.internal.os.BackgroundThread;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
@@ -298,6 +300,27 @@ public final class PrintManagerService extends IPrintManager.Stub {
}
}
+ @Override
+ public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump PrintManager from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
+ }
+
+ synchronized (mLock) {
+ pw.println("PRINT MANAGER STATE (dumpsys print)");
+ final int userStateCount = mUserStates.size();
+ for (int i = 0; i < userStateCount; i++) {
+ UserState userState = mUserStates.get(i);
+ userState.dump(fd, pw, "");
+ pw.println();
+ }
+ }
+ }
+
private void registerContentObservers() {
final Uri enabledPrintServicesUri = Settings.Secure.getUriFor(
Settings.Secure.ENABLED_PRINT_SERVICES);
diff --git a/services/java/com/android/server/print/RemotePrintService.java b/services/java/com/android/server/print/RemotePrintService.java
index 2ded2024d48b..ddff0ae55449 100644
--- a/services/java/com/android/server/print/RemotePrintService.java
+++ b/services/java/com/android/server/print/RemotePrintService.java
@@ -41,6 +41,7 @@ import android.util.Slog;
import com.android.internal.R;
+import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
@@ -137,6 +138,19 @@ final class RemotePrintService implements DeathRecipient {
}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
}
+ public void dump(PrintWriter pw, String prefix) {
+ String tab = " ";
+ pw.append(prefix).append("service:").println();
+ pw.append(prefix).append(tab).append("componentName=")
+ .append(mComponentName.flattenToString()).println();
+ pw.append(prefix).append(tab).append("destroyed=")
+ .append(String.valueOf(mDestroyed)).println();
+ pw.append(prefix).append(tab).append("bound=")
+ .append(String.valueOf(isBound())).println();
+ pw.append(prefix).append(tab).append("hasDicoverySession=")
+ .append(String.valueOf(mHasPrinterDiscoverySession));
+ }
+
private void failAllActivePrintJobs() {
List<PrintJobInfo> printJobs = mSpooler.getPrintJobInfos(mComponentName,
PrintJobInfo.STATE_ANY_ACTIVE, PrintManager.APP_ID_ANY);
diff --git a/services/java/com/android/server/print/RemotePrintSpooler.java b/services/java/com/android/server/print/RemotePrintSpooler.java
index db0eb3367aee..28a6186cbeb3 100644
--- a/services/java/com/android/server/print/RemotePrintSpooler.java
+++ b/services/java/com/android/server/print/RemotePrintSpooler.java
@@ -34,11 +34,14 @@ import android.print.IPrintSpoolerCallbacks;
import android.print.IPrintSpoolerClient;
import android.print.PrintAttributes;
import android.print.PrintJobInfo;
+import android.print.PrintManager;
import android.util.Slog;
import android.util.TimedRemoteCaller;
import libcore.io.IoUtils;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.concurrent.TimeoutException;
@@ -291,6 +294,28 @@ final class RemotePrintSpooler {
}
}
+ public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
+ synchronized (mLock) {
+ pw.append(prefix).append("destroyed=")
+ .append(String.valueOf(mDestroyed)).println();
+ pw.append(prefix).append("bound=")
+ .append((mRemoteInstance != null) ? "true" : "false").println();
+ pw.append(prefix).append("print jobs:").println();
+ if (mRemoteInstance != null) {
+ List<PrintJobInfo> printJobs = getPrintJobInfos(null,
+ PrintJobInfo.STATE_ANY, PrintManager.APP_ID_ANY);
+ if (printJobs != null) {
+ final int printJobCount = printJobs.size();
+ for (int i = 0; i < printJobCount; i++) {
+ PrintJobInfo printJob = printJobs.get(i);
+ pw.append(prefix).append(prefix).append(printJob.toString());
+ pw.println();
+ }
+ }
+ }
+ }
+ }
+
private void onAllPrintJobsHandled() {
synchronized (mLock) {
throwIfDestroyedLocked();
diff --git a/services/java/com/android/server/print/UserState.java b/services/java/com/android/server/print/UserState.java
index b37a0d91d4bd..5392975466ba 100644
--- a/services/java/com/android/server/print/UserState.java
+++ b/services/java/com/android/server/print/UserState.java
@@ -39,14 +39,16 @@ import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils.SimpleStringSplitter;
import android.util.ArrayMap;
+import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import com.android.internal.os.SomeArgs;
import com.android.server.print.RemotePrintSpooler.PrintSpoolerCallbacks;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -72,14 +74,14 @@ final class UserState implements PrintSpoolerCallbacks {
private final Intent mQueryIntent =
new Intent(android.printservice.PrintService.SERVICE_INTERFACE);
- private final Map<ComponentName, RemotePrintService> mActiveServices =
- new HashMap<ComponentName, RemotePrintService>();
+ private final ArrayMap<ComponentName, RemotePrintService> mActiveServices =
+ new ArrayMap<ComponentName, RemotePrintService>();
private final List<PrintServiceInfo> mInstalledServices =
new ArrayList<PrintServiceInfo>();
private final Set<ComponentName> mEnabledServices =
- new HashSet<ComponentName>();
+ new ArraySet<ComponentName>();
private final Object mLock;
@@ -318,6 +320,57 @@ final class UserState implements PrintSpoolerCallbacks {
mDestroyed = true;
}
+ public void dump(FileDescriptor fd, PrintWriter pw, String prefix) {
+ pw.append(prefix).append("user state ").append(String.valueOf(mUserId)).append(":");
+ pw.println();
+
+ String tab = " ";
+
+ pw.append(prefix).append(tab).append("installed services:").println();
+ final int installedServiceCount = mInstalledServices.size();
+ for (int i = 0; i < installedServiceCount; i++) {
+ PrintServiceInfo installedService = mInstalledServices.get(i);
+ String installedServicePrefix = prefix + tab + tab;
+ pw.append(installedServicePrefix).append("service:").println();
+ ResolveInfo resolveInfo = installedService.getResolveInfo();
+ ComponentName componentName = new ComponentName(
+ resolveInfo.serviceInfo.packageName,
+ resolveInfo.serviceInfo.name);
+ pw.append(installedServicePrefix).append(tab).append("componentName=")
+ .append(componentName.flattenToString()).println();
+ pw.append(installedServicePrefix).append(tab).append("settingsActivity=")
+ .append(installedService.getSettingsActivityName()).println();
+ pw.append(installedServicePrefix).append(tab).append("addPrintersActivity=")
+ .append(installedService.getAddPrintersActivityName()).println();
+ }
+
+ pw.append(prefix).append(tab).append("enabled services:").println();
+ for (ComponentName enabledService : mEnabledServices) {
+ String enabledServicePrefix = prefix + tab + tab;
+ pw.append(enabledServicePrefix).append("service:").println();
+ pw.append(enabledServicePrefix).append(tab).append("componentName=")
+ .append(enabledService.flattenToString());
+ pw.println();
+ }
+
+ pw.append(prefix).append(tab).append("active services:").println();
+ final int activeServiceCount = mActiveServices.size();
+ for (int i = 0; i < activeServiceCount; i++) {
+ RemotePrintService activeService = mActiveServices.valueAt(i);
+ activeService.dump(pw, prefix + tab + tab);
+ pw.println();
+ }
+
+ pw.append(prefix).append(tab).append("discovery mediator:").println();
+ if (mPrinterDiscoverySession != null) {
+ mPrinterDiscoverySession.dump(pw, prefix + tab + tab);
+ }
+
+ pw.append(prefix).append(tab).append("print spooler:").println();
+ mSpooler.dump(fd, pw, prefix + tab + tab);
+ pw.println();
+ }
+
private boolean readConfigurationLocked() {
boolean somethingChanged = false;
somethingChanged |= readInstalledPrintServicesLocked();
@@ -814,6 +867,47 @@ final class UserState implements PrintSpoolerCallbacks {
}
}
+ public void dump(PrintWriter pw, String prefix) {
+ pw.append(prefix).append("destroyed=")
+ .append(String.valueOf(mDestroyed)).println();
+
+ pw.append(prefix).append("printDiscoveryInProgress=")
+ .append(String.valueOf(!mStartedPrinterDiscoveryTokens.isEmpty())).println();
+
+ String tab = " ";
+
+ pw.append(prefix).append(tab).append("printer discovery observers:").println();
+ final int observerCount = mDiscoveryObservers.beginBroadcast();
+ for (int i = 0; i < observerCount; i++) {
+ IPrinterDiscoveryObserver observer = mDiscoveryObservers.getBroadcastItem(i);
+ pw.append(prefix).append(prefix).append(observer.toString());
+ pw.println();
+ }
+ mDiscoveryObservers.finishBroadcast();
+
+ pw.append(prefix).append(tab).append("start discovery requests:").println();
+ final int tokenCount = this.mStartedPrinterDiscoveryTokens.size();
+ for (int i = 0; i < tokenCount; i++) {
+ IBinder token = mStartedPrinterDiscoveryTokens.get(i);
+ pw.append(prefix).append(tab).append(tab).append(token.toString()).println();
+ }
+
+ pw.append(prefix).append(tab).append("tracked printer requests:").println();
+ final int trackedPrinters = mStateTrackedPrinters.size();
+ for (int i = 0; i < trackedPrinters; i++) {
+ PrinterId printer = mStateTrackedPrinters.get(i);
+ pw.append(prefix).append(tab).append(tab).append(printer.toString()).println();
+ }
+
+ pw.append(prefix).append(tab).append("printers:").println();
+ final int pritnerCount = mPrinters.size();
+ for (int i = 0; i < pritnerCount; i++) {
+ PrinterInfo printer = mPrinters.valueAt(i);
+ pw.append(prefix).append(tab).append(tab).append(
+ printer.toString()).println();
+ }
+ }
+
private void handleDispatchPrintersAdded(List<PrinterInfo> addedPrinters) {
final int observerCount = mDiscoveryObservers.beginBroadcast();
for (int i = 0; i < observerCount; i++) {
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 737d85425e31..5aa266d473bd 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -22,6 +22,7 @@ import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.Slog;
+import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -36,7 +37,7 @@ public class BlackFrame {
final SurfaceControl surface;
BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b, int layerStack)
- throws SurfaceControl.OutOfResourcesException {
+ throws OutOfResourcesException {
left = l;
top = t;
this.layer = layer;
@@ -112,7 +113,7 @@ public class BlackFrame {
}
public BlackFrame(SurfaceSession session, Rect outer, Rect inner, int layer, int layerStack,
- boolean forceDefaultOrientation) throws SurfaceControl.OutOfResourcesException {
+ boolean forceDefaultOrientation) throws OutOfResourcesException {
boolean success = false;
mForceDefaultOrientation = forceDefaultOrientation;
diff --git a/services/java/com/android/server/wm/DisplayMagnifier.java b/services/java/com/android/server/wm/DisplayMagnifier.java
index 0f51028b99f9..382d7b4a94af 100644
--- a/services/java/com/android/server/wm/DisplayMagnifier.java
+++ b/services/java/com/android/server/wm/DisplayMagnifier.java
@@ -496,7 +496,7 @@ final class DisplayMagnifier {
mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
surfaceControl = new SurfaceControl(mWindowManagerService.mFxSession, SURFACE_TITLE,
mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
- } catch (SurfaceControl.OutOfResourcesException oore) {
+ } catch (OutOfResourcesException oore) {
/* ignore */
}
mSurfaceControl = surfaceControl;
@@ -629,7 +629,7 @@ final class DisplayMagnifier {
}
} catch (IllegalArgumentException iae) {
/* ignore */
- } catch (OutOfResourcesException oore) {
+ } catch (Surface.OutOfResourcesException oore) {
/* ignore */
}
if (canvas == null) {
@@ -644,7 +644,7 @@ final class DisplayMagnifier {
canvas.drawPath(path, mPaint);
mSurface.unlockCanvasAndPost(canvas);
-
+
if (mAlpha > 0) {
mSurfaceControl.show();
} else {
diff --git a/services/java/com/android/server/wm/FocusedStackFrame.java b/services/java/com/android/server/wm/FocusedStackFrame.java
index 9c18331e068f..365b277c9525 100644
--- a/services/java/com/android/server/wm/FocusedStackFrame.java
+++ b/services/java/com/android/server/wm/FocusedStackFrame.java
@@ -26,6 +26,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.util.Slog;
import android.view.Display;
+import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -39,9 +40,9 @@ class FocusedStackFrame {
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
- private Rect mLastBounds = new Rect();
- private Rect mBounds = new Rect();
- private Rect mTmpDrawRect = new Rect();
+ private final Rect mLastBounds = new Rect();
+ private final Rect mBounds = new Rect();
+ private final Rect mTmpDrawRect = new Rect();
public FocusedStackFrame(Display display, SurfaceSession session) {
SurfaceControl ctrl = null;
@@ -56,7 +57,7 @@ class FocusedStackFrame {
ctrl.setLayerStack(display.getLayerStack());
ctrl.setAlpha(ALPHA);
mSurface.copyFrom(ctrl);
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
}
diff --git a/services/java/com/android/server/wm/InputMonitor.java b/services/java/com/android/server/wm/InputMonitor.java
index 9620612ec7bc..ea3af26349ed 100644
--- a/services/java/com/android/server/wm/InputMonitor.java
+++ b/services/java/com/android/server/wm/InputMonitor.java
@@ -88,7 +88,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
*/
@Override
public long notifyANR(InputApplicationHandle inputApplicationHandle,
- InputWindowHandle inputWindowHandle) {
+ InputWindowHandle inputWindowHandle, String reason) {
AppWindowToken appWindowToken = null;
WindowState windowState = null;
boolean aboveSystem = false;
@@ -105,7 +105,8 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
if (windowState != null) {
Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
- + "sending to " + windowState.mAttrs.getTitle());
+ + "sending to " + windowState.mAttrs.getTitle()
+ + ". Reason: " + reason);
// Figure out whether this window is layered above system windows.
// We need to do this here to help the activity manager know how to
// layer its ANR dialog.
@@ -114,19 +115,21 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
aboveSystem = windowState.mBaseLayer > systemAlertLayer;
} else if (appWindowToken != null) {
Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
- + "sending to application " + appWindowToken.stringName);
+ + "sending to application " + appWindowToken.stringName
+ + ". Reason: " + reason);
} else {
- Slog.i(WindowManagerService.TAG, "Input event dispatching timed out.");
+ Slog.i(WindowManagerService.TAG, "Input event dispatching timed out "
+ + ". Reason: " + reason);
}
- mService.saveANRStateLocked(appWindowToken, windowState);
+ mService.saveANRStateLocked(appWindowToken, windowState, reason);
}
if (appWindowToken != null && appWindowToken.appToken != null) {
try {
// Notify the activity manager about the timeout and let it decide whether
// to abort dispatching or keep waiting.
- boolean abort = appWindowToken.appToken.keyDispatchingTimedOut();
+ boolean abort = appWindowToken.appToken.keyDispatchingTimedOut(reason);
if (! abort) {
// The activity manager declined to abort dispatching.
// Wait a bit longer and timeout again later.
@@ -139,7 +142,7 @@ final class InputMonitor implements InputManagerService.WindowManagerCallbacks {
// Notify the activity manager about the timeout and let it decide whether
// to abort dispatching or keep waiting.
long timeout = ActivityManagerNative.getDefault().inputDispatchingTimedOut(
- windowState.mSession.mPid, aboveSystem);
+ windowState.mSession.mPid, aboveSystem, reason);
if (timeout >= 0) {
// The activity manager declined to abort dispatching.
// Wait a bit longer and timeout again later.
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 7d9085888ef2..e630737b40b7 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -27,6 +27,7 @@ import android.graphics.Rect;
import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -262,7 +263,7 @@ class ScreenRotationAnimation {
mSurfaceControl.setAlpha(0);
mSurfaceControl.show();
sur.destroy();
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate freeze surface", e);
}
@@ -547,7 +548,7 @@ class ScreenRotationAnimation {
mCustomBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 3,
layerStack, false);
mCustomBlackFrame.setMatrix(mFrameInitialMatrix);
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
} finally {
SurfaceControl.closeTransaction();
@@ -587,7 +588,7 @@ class ScreenRotationAnimation {
mExitingBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER + 2,
layerStack, mForceDefaultOrientation);
mExitingBlackFrame.setMatrix(mFrameInitialMatrix);
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
} finally {
SurfaceControl.closeTransaction();
@@ -609,7 +610,7 @@ class ScreenRotationAnimation {
Rect inner = new Rect(0, 0, finalWidth, finalHeight);
mEnteringBlackFrame = new BlackFrame(session, outer, inner, FREEZE_LAYER,
layerStack, false);
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
Slog.w(TAG, "Unable to allocate black surface", e);
} finally {
SurfaceControl.closeTransaction();
@@ -894,7 +895,7 @@ class ScreenRotationAnimation {
&& (mMoreStartEnter || mMoreStartExit || mMoreFinishEnter || mMoreFinishExit))
|| (USE_CUSTOM_BLACK_FRAME
&& (mMoreStartFrame || mMoreRotateFrame || mMoreFinishFrame))
- || mMoreRotateEnter || mMoreRotateExit
+ || mMoreRotateEnter || mMoreRotateExit
|| !mFinishAnimReady;
mSnapshotFinalMatrix.setConcat(mExitTransformation.getMatrix(), mSnapshotInitialMatrix);
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 31628e33866a..fb5876b65aed 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -23,6 +23,7 @@ import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.graphics.Region;
import android.view.Display;
+import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -47,7 +48,7 @@ class StrictModeFlash {
ctrl.setPosition(0, 0);
ctrl.show();
mSurface.copyFrom(ctrl);
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
mDrawNeeded = true;
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index fedd31416f03..e226e3d73e47 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -27,10 +27,10 @@ import android.util.DisplayMetrics;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
+import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
-import android.view.Surface.OutOfResourcesException;
/**
* Displays a watermark on top of the window manager's windows.
@@ -119,7 +119,7 @@ class Watermark {
ctrl.setPosition(0, 0);
ctrl.show();
mSurface.copyFrom(ctrl);
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
}
mSurfaceControl = ctrl;
}
@@ -144,11 +144,11 @@ class Watermark {
try {
c = mSurface.lockCanvas(dirty);
} catch (IllegalArgumentException e) {
- } catch (OutOfResourcesException e) {
+ } catch (Surface.OutOfResourcesException e) {
}
if (c != null) {
c.drawColor(0, PorterDuff.Mode.CLEAR);
-
+
int deltaX = mDeltaX;
int deltaY = mDeltaY;
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 34d89733feb1..f5e05315550e 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -116,6 +116,7 @@ import android.view.InputEventReceiver;
import android.view.KeyEvent;
import android.view.MagnificationSpec;
import android.view.MotionEvent;
+import android.view.Surface.OutOfResourcesException;
import android.view.Surface;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
@@ -461,7 +462,7 @@ public class WindowManagerService extends IWindowManager.Stub
// This is held as long as we have the screen frozen, to give us time to
// perform a rotation animation when turning off shows the lock screen which
// changes the orientation.
- private PowerManager.WakeLock mScreenFrozenLock;
+ private final PowerManager.WakeLock mScreenFrozenLock;
final AppTransition mAppTransition;
boolean mStartingIconInTransition = false;
@@ -664,7 +665,7 @@ public class WindowManagerService extends IWindowManager.Stub
boolean mInTouchMode = true;
private ViewServer mViewServer;
- private ArrayList<WindowChangeListener> mWindowChangeListeners =
+ private final ArrayList<WindowChangeListener> mWindowChangeListeners =
new ArrayList<WindowChangeListener>();
private boolean mWindowsChanged = false;
@@ -6812,7 +6813,7 @@ public class WindowManagerService extends IWindowManager.Stub
} else {
Slog.w(TAG, "Drag already in progress");
}
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
if (mDragState != null) {
mDragState.reset();
@@ -8580,12 +8581,8 @@ public class WindowManagerService extends IWindowManager.Stub
mAppTransition.getStartingPoint(p);
appAnimator.thumbnailX = p.x;
appAnimator.thumbnailY = p.y;
- } catch (SurfaceControl.OutOfResourcesException e) {
- Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
- + " h=" + dirty.height(), e);
- appAnimator.clearThumbnail();
- } catch (Surface.OutOfResourcesException e) {
- Slog.e(TAG, "Can't allocate Canvas surface w=" + dirty.width()
+ } catch (OutOfResourcesException e) {
+ Slog.e(TAG, "Can't allocate thumbnail/Canvas surface w=" + dirty.width()
+ " h=" + dirty.height(), e);
appAnimator.clearThumbnail();
}
@@ -10541,8 +10538,10 @@ public class WindowManagerService extends IWindowManager.Stub
*
* @param appWindowToken The application that ANR'd, may be null.
* @param windowState The window that ANR'd, may be null.
+ * @param reason The reason for the ANR, may be null.
*/
- public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState) {
+ public void saveANRStateLocked(AppWindowToken appWindowToken, WindowState windowState,
+ String reason) {
StringWriter sw = new StringWriter();
PrintWriter pw = new FastPrintWriter(sw, false, 1024);
pw.println(" ANR time: " + DateFormat.getInstance().format(new Date()));
@@ -10552,6 +10551,9 @@ public class WindowManagerService extends IWindowManager.Stub
if (windowState != null) {
pw.println(" Window at fault: " + windowState.mAttrs.getTitle());
}
+ if (reason != null) {
+ pw.println(" Reason: " + reason);
+ }
pw.println();
dumpWindowsNoHeaderLocked(pw, true, null);
pw.close();
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index 73325cbf5afc..9245542178ab 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -29,6 +29,7 @@ import android.util.Slog;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.MagnificationSpec;
+import android.view.Surface.OutOfResourcesException;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.view.WindowManager;
@@ -480,7 +481,7 @@ class WindowStateAnimator {
private final Rect mWindowCrop = new Rect();
private boolean mShown = false;
private int mLayerStack;
- private String mName;
+ private final String mName;
public SurfaceTrace(SurfaceSession s,
String name, int w, int h, int format, int flags)
@@ -694,7 +695,7 @@ class WindowStateAnimator {
+ attrs.format + " flags=0x"
+ Integer.toHexString(flags)
+ " / " + this);
- } catch (SurfaceControl.OutOfResourcesException e) {
+ } catch (OutOfResourcesException e) {
mWin.mHasSurface = false;
Slog.w(TAG, "OutOfResourcesException creating surface");
mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
diff --git a/services/jni/Android.mk b/services/jni/Android.mk
index 93d8e078181a..98e9b3085736 100644
--- a/services/jni/Android.mk
+++ b/services/jni/Android.mk
@@ -4,6 +4,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
com_android_server_AlarmManagerService.cpp \
com_android_server_AssetAtlasService.cpp \
+ com_android_server_ConsumerIrService.cpp \
com_android_server_input_InputApplicationHandle.cpp \
com_android_server_input_InputManagerService.cpp \
com_android_server_input_InputWindowHandle.cpp \
diff --git a/services/jni/com_android_server_ConsumerIrService.cpp b/services/jni/com_android_server_ConsumerIrService.cpp
new file mode 100644
index 000000000000..ed964fe28b18
--- /dev/null
+++ b/services/jni/com_android_server_ConsumerIrService.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "ConsumerIrService"
+
+#include "jni.h"
+#include "JNIHelp.h"
+#include "android_runtime/AndroidRuntime.h"
+
+#include <stdlib.h>
+#include <utils/misc.h>
+#include <utils/Log.h>
+#include <hardware/hardware.h>
+#include <hardware/consumerir.h>
+#include <ScopedPrimitiveArray.h>
+
+namespace android {
+
+static jint halOpen(JNIEnv *env, jobject obj) {
+ hw_module_t const* module;
+ consumerir_device_t *dev;
+ int err;
+
+ err = hw_get_module(CONSUMERIR_HARDWARE_MODULE_ID, &module);
+ if (err != 0) {
+ ALOGE("Can't open consumer IR HW Module, error: %d", err);
+ return 0;
+ }
+
+ err = module->methods->open(module, CONSUMERIR_TRANSMITTER,
+ (hw_device_t **) &dev);
+ if (err < 0) {
+ ALOGE("Can't open consumer IR transmitter, error: %d", err);
+ return 0;
+ }
+
+ return reinterpret_cast<jint>(dev);
+}
+
+static jint halTransmit(JNIEnv *env, jobject obj, jint halObject,
+ jint carrierFrequency, jintArray pattern) {
+ int ret;
+
+ consumerir_device_t *dev = reinterpret_cast<consumerir_device_t*>(halObject);
+ ScopedIntArrayRO cPattern(env, pattern);
+ if (cPattern.get() == NULL) {
+ return -EINVAL;
+ }
+ jsize patternLength = cPattern.size();
+
+ ret = dev->transmit(dev, carrierFrequency, cPattern.get(), patternLength);
+
+ return reinterpret_cast<jint>(ret);
+}
+
+static jintArray halGetCarrierFrequencies(JNIEnv *env, jobject obj,
+ jint halObject) {
+ consumerir_device_t *dev = (consumerir_device_t *) halObject;
+ consumerir_freq_range_t *ranges;
+ int len;
+
+ len = dev->get_num_carrier_freqs(dev);
+ if (len <= 0)
+ return NULL;
+
+ ranges = new consumerir_freq_range_t[len];
+
+ len = dev->get_carrier_freqs(dev, ranges);
+ if (len <= 0) {
+ delete[] ranges;
+ return NULL;
+ }
+
+ int i;
+ ScopedIntArrayRW freqsOut(env, env->NewIntArray(len*2));
+ jint *arr = freqsOut.get();
+ if (arr == NULL) {
+ delete[] ranges;
+ return NULL;
+ }
+ for (i = 0; i < len; i++) {
+ arr[i*2] = ranges[i].min;
+ arr[i*2+1] = ranges[i].max;
+ }
+
+ delete[] ranges;
+ return freqsOut.getJavaArray();
+}
+
+static JNINativeMethod method_table[] = {
+ { "halOpen", "()I", (void *)halOpen },
+ { "halTransmit", "(II[I)I", (void *)halTransmit },
+ { "halGetCarrierFrequencies", "(I)[I", (void *)halGetCarrierFrequencies},
+};
+
+int register_android_server_ConsumerIrService(JNIEnv *env) {
+ return jniRegisterNativeMethods(env, "com/android/server/ConsumerIrService",
+ method_table, NELEM(method_table));
+}
+
+};
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index b6c2eb460e84..4ab2086e10df 100644
--- a/services/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -192,7 +192,8 @@ public:
uint32_t policyFlags);
virtual void notifyConfigurationChanged(nsecs_t when);
virtual nsecs_t notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle);
+ const sp<InputWindowHandle>& inputWindowHandle,
+ const String8& reason);
virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
@@ -554,7 +555,7 @@ void NativeInputManager::notifyConfigurationChanged(nsecs_t when) {
}
nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApplicationHandle,
- const sp<InputWindowHandle>& inputWindowHandle) {
+ const sp<InputWindowHandle>& inputWindowHandle, const String8& reason) {
#if DEBUG_INPUT_DISPATCHER_POLICY
ALOGD("notifyANR");
#endif
@@ -565,15 +566,18 @@ nsecs_t NativeInputManager::notifyANR(const sp<InputApplicationHandle>& inputApp
getInputApplicationHandleObjLocalRef(env, inputApplicationHandle);
jobject inputWindowHandleObj =
getInputWindowHandleObjLocalRef(env, inputWindowHandle);
+ jstring reasonObj = env->NewStringUTF(reason.string());
jlong newTimeout = env->CallLongMethod(mServiceObj,
- gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj);
+ gServiceClassInfo.notifyANR, inputApplicationHandleObj, inputWindowHandleObj,
+ reasonObj);
if (checkAndClearExceptionFromCallback(env, "notifyANR")) {
newTimeout = 0; // abort dispatch
} else {
assert(newTimeout >= 0);
}
+ env->DeleteLocalRef(reasonObj);
env->DeleteLocalRef(inputWindowHandleObj);
env->DeleteLocalRef(inputApplicationHandleObj);
return newTimeout;
@@ -1380,7 +1384,7 @@ int register_android_server_InputManager(JNIEnv* env) {
GET_METHOD_ID(gServiceClassInfo.notifyANR, clazz,
"notifyANR",
- "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;)J");
+ "(Lcom/android/server/input/InputApplicationHandle;Lcom/android/server/input/InputWindowHandle;Ljava/lang/String;)J");
GET_METHOD_ID(gServiceClassInfo.filterInputEvent, clazz,
"filterInputEvent", "(Landroid/view/InputEvent;I)Z");
diff --git a/services/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/jni/com_android_server_location_FlpHardwareProvider.cpp
index f5d7f8be4c36..ac269eb468b8 100644
--- a/services/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -319,7 +319,7 @@ static void TranslateGeofenceFromGeofenceHardwareRequestParcelable(
jmethodID getNotificationResponsiveness = env->GetMethodID(
geofenceRequestClass,
"getNotificationResponsiveness",
- "()D");
+ "()I");
options->notification_responsivenes_ms = env->CallIntMethod(
geofenceRequestObject,
getNotificationResponsiveness);
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 5427277c905d..efc34a2aca41 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -21,6 +21,7 @@
namespace android {
int register_android_server_AlarmManagerService(JNIEnv* env);
+int register_android_server_ConsumerIrService(JNIEnv *env);
int register_android_server_InputApplicationHandle(JNIEnv* env);
int register_android_server_InputWindowHandle(JNIEnv* env);
int register_android_server_InputManager(JNIEnv* env);
@@ -65,6 +66,8 @@ extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
register_android_server_location_FlpHardwareProvider(env);
register_android_server_connectivity_Vpn(env);
register_android_server_AssetAtlasService(env);
+ register_android_server_ConsumerIrService(env);
+
return JNI_VERSION_1_4;
}
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index a9909b2ecf3f..a1af8cb79f43 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -40,7 +40,6 @@ import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_POLL;
import static org.easymock.EasyMock.anyLong;
-import static org.easymock.EasyMock.aryEq;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.eq;
@@ -74,13 +73,13 @@ import com.android.server.net.NetworkStatsService;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings;
import com.android.server.net.NetworkStatsService.NetworkStatsSettings.Config;
+import libcore.io.IoUtils;
+
import org.easymock.Capture;
import org.easymock.EasyMock;
import java.io.File;
-import libcore.io.IoUtils;
-
/**
* Tests for {@link NetworkStatsService}.
*/
@@ -919,8 +918,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
expect(mNetManager.getNetworkStatsUidDetail(eq(UID_ALL))).andReturn(detail).atLeastOnce();
// also include tethering details, since they are folded into UID
- expect(mConnManager.getTetheredIfacePairs()).andReturn(tetherIfacePairs).atLeastOnce();
- expect(mNetManager.getNetworkStatsTethering(aryEq(tetherIfacePairs)))
+ expect(mNetManager.getNetworkStatsTethering())
.andReturn(tetherStats).atLeastOnce();
}
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 40201ada54b8..7d8b64fe014c 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -309,7 +309,7 @@ public class TelephonyManager {
*/
public List<NeighboringCellInfo> getNeighboringCellInfo() {
try {
- return getITelephony().getNeighboringCellInfo(mContext.getBasePackageName());
+ return getITelephony().getNeighboringCellInfo(mContext.getOpPackageName());
} catch (RemoteException ex) {
return null;
} catch (NullPointerException ex) {
diff --git a/test-runner/src/android/test/mock/MockContext.java b/test-runner/src/android/test/mock/MockContext.java
index 252a14e87f67..0d9cd18999f2 100644
--- a/test-runner/src/android/test/mock/MockContext.java
+++ b/test-runner/src/android/test/mock/MockContext.java
@@ -112,6 +112,12 @@ public class MockContext extends Context {
throw new UnsupportedOperationException();
}
+ /** @hide */
+ @Override
+ public String getOpPackageName() {
+ throw new UnsupportedOperationException();
+ }
+
@Override
public ApplicationInfo getApplicationInfo() {
throw new UnsupportedOperationException();
diff --git a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
index 5256b583f8d3..04ce9d077b53 100644
--- a/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/BitmapFactory_Delegate.java
@@ -24,10 +24,13 @@ import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
import android.content.res.BridgeResources.NinePatchInputStream;
import android.graphics.BitmapFactory.Options;
+import android.graphics.Bitmap_Delegate.BitmapCreateFlags;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.InputStream;
+import java.util.EnumSet;
+import java.util.Set;
/**
* Delegate implementing the native methods of android.graphics.BitmapFactory
@@ -98,8 +101,12 @@ import java.io.InputStream;
//TODO support rescaling
Density density = Density.MEDIUM;
+ Set<BitmapCreateFlags> bitmapCreateFlags = EnumSet.of(BitmapCreateFlags.MUTABLE);
if (opts != null) {
density = Density.getEnum(opts.inDensity);
+ if (opts.inPremultiplied) {
+ bitmapCreateFlags.add(BitmapCreateFlags.PREMULTIPLIED);
+ }
}
try {
@@ -112,7 +119,7 @@ import java.io.InputStream;
npis, true /*is9Patch*/, false /*convert*/);
// get the bitmap and chunk objects.
- bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), true /*isMutable*/,
+ bm = Bitmap_Delegate.createBitmap(ninePatch.getImage(), bitmapCreateFlags,
density);
NinePatchChunk chunk = ninePatch.getChunk();
@@ -127,7 +134,7 @@ import java.io.InputStream;
padding.bottom = paddingarray[3];
} else {
// load the bitmap directly.
- bm = Bitmap_Delegate.createBitmap(is, true, density);
+ bm = Bitmap_Delegate.createBitmap(is, bitmapCreateFlags, density);
}
} catch (IOException e) {
Bridge.getLog().error(null,"Failed to load image" , e, null);
diff --git a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
index 4121f798ba9a..ec284ac3cfed 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Bitmap_Delegate.java
@@ -33,6 +33,8 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.nio.Buffer;
import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.Set;
import javax.imageio.ImageIO;
@@ -51,6 +53,10 @@ import javax.imageio.ImageIO;
*/
public final class Bitmap_Delegate {
+ public enum BitmapCreateFlags {
+ PREMULTIPLIED, MUTABLE
+ }
+
// ---- delegate manager ----
private static final DelegateManager<Bitmap_Delegate> sManager =
new DelegateManager<Bitmap_Delegate>(Bitmap_Delegate.class);
@@ -93,10 +99,25 @@ public final class Bitmap_Delegate {
*/
public static Bitmap createBitmap(File input, boolean isMutable, Density density)
throws IOException {
+ return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
+ }
+
+ /**
+ * Creates and returns a {@link Bitmap} initialized with the given file content.
+ *
+ * @param input the file from which to read the bitmap content
+ * @param density the density associated with the bitmap
+ *
+ * @see Bitmap#isPremultiplied()
+ * @see Bitmap#isMutable()
+ * @see Bitmap#getDensity()
+ */
+ public static Bitmap createBitmap(File input, Set<BitmapCreateFlags> createFlags,
+ Density density) throws IOException {
// create a delegate with the content of the file.
Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
- return createBitmap(delegate, isMutable, density.getDpiValue());
+ return createBitmap(delegate, createFlags, density.getDpiValue());
}
/**
@@ -111,10 +132,26 @@ public final class Bitmap_Delegate {
*/
public static Bitmap createBitmap(InputStream input, boolean isMutable, Density density)
throws IOException {
+ return createBitmap(input, getPremultipliedBitmapCreateFlags(isMutable), density);
+ }
+
+ /**
+ * Creates and returns a {@link Bitmap} initialized with the given stream content.
+ *
+ * @param input the stream from which to read the bitmap content
+ * @param createFlags
+ * @param density the density associated with the bitmap
+ *
+ * @see Bitmap#isPremultiplied()
+ * @see Bitmap#isMutable()
+ * @see Bitmap#getDensity()
+ */
+ public static Bitmap createBitmap(InputStream input, Set<BitmapCreateFlags> createFlags,
+ Density density) throws IOException {
// create a delegate with the content of the stream.
Bitmap_Delegate delegate = new Bitmap_Delegate(ImageIO.read(input), Config.ARGB_8888);
- return createBitmap(delegate, isMutable, density.getDpiValue());
+ return createBitmap(delegate, createFlags, density.getDpiValue());
}
/**
@@ -129,10 +166,26 @@ public final class Bitmap_Delegate {
*/
public static Bitmap createBitmap(BufferedImage image, boolean isMutable,
Density density) throws IOException {
+ return createBitmap(image, getPremultipliedBitmapCreateFlags(isMutable), density);
+ }
+
+ /**
+ * Creates and returns a {@link Bitmap} initialized with the given {@link BufferedImage}
+ *
+ * @param image the bitmap content
+ * @param createFlags
+ * @param density the density associated with the bitmap
+ *
+ * @see Bitmap#isPremultiplied()
+ * @see Bitmap#isMutable()
+ * @see Bitmap#getDensity()
+ */
+ public static Bitmap createBitmap(BufferedImage image, Set<BitmapCreateFlags> createFlags,
+ Density density) throws IOException {
// create a delegate with the given image.
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ARGB_8888);
- return createBitmap(delegate, isMutable, density.getDpiValue());
+ return createBitmap(delegate, createFlags, density.getDpiValue());
}
/**
@@ -203,7 +256,7 @@ public final class Bitmap_Delegate {
@LayoutlibDelegate
/*package*/ static Bitmap nativeCreate(int[] colors, int offset, int stride, int width,
- int height, int nativeConfig, boolean mutable) {
+ int height, int nativeConfig, boolean isMutable) {
int imageType = getBufferedImageType(nativeConfig);
// create the image
@@ -216,7 +269,8 @@ public final class Bitmap_Delegate {
// create a delegate with the content of the stream.
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
- return createBitmap(delegate, mutable, Bitmap.getDefaultDensity());
+ return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
+ Bitmap.getDefaultDensity());
}
@LayoutlibDelegate
@@ -244,7 +298,8 @@ public final class Bitmap_Delegate {
// create a delegate with the content of the stream.
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.nativeToConfig(nativeConfig));
- return createBitmap(delegate, isMutable, Bitmap.getDefaultDensity());
+ return createBitmap(delegate, getPremultipliedBitmapCreateFlags(isMutable),
+ Bitmap.getDefaultDensity());
}
@LayoutlibDelegate
@@ -464,7 +519,7 @@ public final class Bitmap_Delegate {
Bitmap_Delegate delegate = new Bitmap_Delegate(image, Config.ALPHA_8);
// the density doesn't matter, it's set by the Java method.
- return createBitmap(delegate, false /*isMutable*/,
+ return createBitmap(delegate, EnumSet.of(BitmapCreateFlags.MUTABLE),
Density.DEFAULT_DENSITY /*density*/);
}
@@ -546,15 +601,27 @@ public final class Bitmap_Delegate {
mConfig = config;
}
- private static Bitmap createBitmap(Bitmap_Delegate delegate, boolean isMutable, int density) {
+ private static Bitmap createBitmap(Bitmap_Delegate delegate,
+ Set<BitmapCreateFlags> createFlags, int density) {
// get its native_int
int nativeInt = sManager.addNewDelegate(delegate);
+ int width = delegate.mImage.getWidth();
+ int height = delegate.mImage.getHeight();
+ boolean isMutable = createFlags.contains(BitmapCreateFlags.MUTABLE);
+ boolean isPremultiplied = createFlags.contains(BitmapCreateFlags.PREMULTIPLIED);
+
// and create/return a new Bitmap with it
- // TODO: pass correct width, height, isPremultiplied
- return new Bitmap(nativeInt, null /* buffer */, -1 /* width */, -1 /* height */, density,
- isMutable, true /* isPremultiplied */,
- null /*ninePatchChunk*/, null /* layoutBounds */);
+ return new Bitmap(nativeInt, null /* buffer */, width, height, density, isMutable,
+ isPremultiplied, null /*ninePatchChunk*/, null /* layoutBounds */);
+ }
+
+ private static Set<BitmapCreateFlags> getPremultipliedBitmapCreateFlags(boolean isMutable) {
+ Set<BitmapCreateFlags> createFlags = EnumSet.of(BitmapCreateFlags.PREMULTIPLIED);
+ if (isMutable) {
+ createFlags.add(BitmapCreateFlags.MUTABLE);
+ }
+ return createFlags;
}
/**
diff --git a/tools/layoutlib/bridge/src/android/webkit/WebView.java b/tools/layoutlib/bridge/src/android/webkit/WebView.java
index 3b6618831113..202f2046a3fd 100644
--- a/tools/layoutlib/bridge/src/android/webkit/WebView.java
+++ b/tools/layoutlib/bridge/src/android/webkit/WebView.java
@@ -99,14 +99,6 @@ public class WebView extends MockView {
public static void disablePlatformNotifications() {
}
- public WebBackForwardList saveState(Bundle outState) {
- return null;
- }
-
- public WebBackForwardList restoreState(Bundle inState) {
- return null;
- }
-
public void loadUrl(String url) {
}
@@ -213,10 +205,6 @@ public class WebView extends MockView {
public void clearSslPreferences() {
}
- public WebBackForwardList copyBackForwardList() {
- return null;
- }
-
public static String findAddress(String addr) {
return null;
}
@@ -236,10 +224,6 @@ public class WebView extends MockView {
public void addJavascriptInterface(Object obj, String interfaceName) {
}
- public WebSettings getSettings() {
- return null;
- }
-
public View getZoomControls() {
return null;
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index a1f269715d52..b9294ab3c0f9 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -1090,6 +1090,12 @@ public final class BridgeContext extends Context {
}
@Override
+ public String getOpPackageName() {
+ // pass
+ return null;
+ }
+
+ @Override
public ApplicationInfo getApplicationInfo() {
return mApplicationInfo;
}
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 5f5d54fc5525..2a5b4da02678 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -833,7 +833,7 @@ public class WifiManager {
*/
public List<BatchedScanResult> getBatchedScanResults() {
try {
- return mService.getBatchedScanResults(mContext.getBasePackageName());
+ return mService.getBatchedScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
@@ -883,7 +883,7 @@ public class WifiManager {
*/
public List<ScanResult> getScanResults() {
try {
- return mService.getScanResults(mContext.getBasePackageName());
+ return mService.getScanResults(mContext.getOpPackageName());
} catch (RemoteException e) {
return null;
}
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 83789e265518..56261925c355 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -25,6 +25,7 @@ import android.util.Log;
import java.util.ArrayList;
import java.util.List;
+import java.util.Locale;
/**
* Native calls for bring up/shut down of the supplicant daemon and for
@@ -457,7 +458,7 @@ public class WifiNative {
}
public boolean setCountryCode(String countryCode) {
- return doBooleanCommand("DRIVER COUNTRY " + countryCode);
+ return doBooleanCommand("DRIVER COUNTRY " + countryCode.toUpperCase(Locale.ROOT));
}
public void enableBackgroundScan(boolean enable) {
diff --git a/wifi/java/android/net/wifi/WifiStateMachine.java b/wifi/java/android/net/wifi/WifiStateMachine.java
index 3ccdbea0182b..2bc22f26d859 100644
--- a/wifi/java/android/net/wifi/WifiStateMachine.java
+++ b/wifi/java/android/net/wifi/WifiStateMachine.java
@@ -88,7 +88,6 @@ import java.net.InetAddress;
import java.net.Inet6Address;
import java.util.ArrayList;
import java.util.List;
-import java.util.Locale;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.Iterator;
@@ -1431,6 +1430,7 @@ public class WifiStateMachine extends StateMachine {
countryCode);
}
sendMessage(CMD_SET_COUNTRY_CODE, countryCode);
+ mWifiP2pChannel.sendMessage(WifiP2pService.SET_COUNTRY_CODE, countryCode);
}
/**
@@ -2952,7 +2952,7 @@ public class WifiStateMachine extends StateMachine {
case CMD_SET_COUNTRY_CODE:
String country = (String) message.obj;
if (DBG) log("set country code " + country);
- if (!mWifiNative.setCountryCode(country.toUpperCase(Locale.ROOT))) {
+ if (!mWifiNative.setCountryCode(country)) {
loge("Failed to set country code " + country);
}
break;
@@ -4256,7 +4256,7 @@ public class WifiStateMachine extends StateMachine {
/**
* arg2 on the source message has a unique id that needs to be retained in replies
* to match the request
- *
+
* see WifiManager for details
*/
private Message obtainMessageWithArg2(Message srcMsg) {
diff --git a/wifi/java/android/net/wifi/p2p/WifiP2pService.java b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
index 05196b8a1683..625ffb8733d4 100644
--- a/wifi/java/android/net/wifi/p2p/WifiP2pService.java
+++ b/wifi/java/android/net/wifi/p2p/WifiP2pService.java
@@ -174,6 +174,9 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
// msg.obj = StateMachine to send to when blocked
public static final int BLOCK_DISCOVERY = BASE + 15;
+ // set country code
+ public static final int SET_COUNTRY_CODE = BASE + 16;
+
public static final int ENABLED = 1;
public static final int DISABLED = 0;
@@ -632,6 +635,7 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
case WifiP2pManager.START_LISTEN:
case WifiP2pManager.STOP_LISTEN:
case WifiP2pManager.SET_CHANNEL:
+ case SET_COUNTRY_CODE:
break;
case WifiStateMachine.CMD_ENABLE_P2P:
// Enable is lazy and has no response
@@ -1064,6 +1068,10 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
replyToMessage(message, WifiP2pManager.SET_CHANNEL_FAILED);
}
break;
+ case SET_COUNTRY_CODE:
+ String countryCode = (String) message.obj;
+ mWifiNative.setCountryCode(countryCode);
+ break;
default:
return NOT_HANDLED;
}
@@ -2537,6 +2545,12 @@ public class WifiP2pService extends IWifiP2pManager.Stub {
mServiceTransactionId = 0;
mServiceDiscReqId = null;
+ String countryCode = Settings.Global.getString(mContext.getContentResolver(),
+ Settings.Global.WIFI_COUNTRY_CODE);
+ if (countryCode != null && !countryCode.isEmpty()) {
+ mP2pStateMachine.sendMessage(SET_COUNTRY_CODE, countryCode);
+ }
+
updatePersistentNetworks(RELOAD);
}