summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Android.mk16
-rw-r--r--CleanSpec.mk1
-rw-r--r--\19
-rw-r--r--api/current.txt1318
-rw-r--r--cmds/pm/src/com/android/commands/pm/Pm.java30
-rw-r--r--core/java/android/app/ActivityTransitionCoordinator.java9
-rw-r--r--core/java/android/app/ContextImpl.java4
-rw-r--r--core/java/android/app/EnterTransitionCoordinator.java20
-rw-r--r--core/java/android/app/ExitTransitionCoordinator.java2
-rw-r--r--core/java/android/app/VoiceInteractor.java6
-rw-r--r--core/java/android/app/admin/DevicePolicyManager.java57
-rw-r--r--core/java/android/app/admin/IDevicePolicyManager.aidl3
-rw-r--r--core/java/android/app/backup/BackupTransport.java175
-rw-r--r--core/java/android/content/ContentResolver.java92
-rw-r--r--core/java/android/content/Context.java6
-rw-r--r--core/java/android/content/IContentService.aidl13
-rw-r--r--core/java/android/content/PeriodicSync.java73
-rw-r--r--core/java/android/content/SyncInfo.java20
-rw-r--r--core/java/android/content/SyncRequest.java137
-rw-r--r--core/java/android/content/SyncService.java211
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl7
-rw-r--r--core/java/android/content/pm/PackageManager.java10
-rw-r--r--core/java/android/content/res/Resources.java28
-rw-r--r--core/java/android/hardware/camera2/CameraCaptureSession.java87
-rw-r--r--core/java/android/hardware/camera2/CameraCharacteristics.java3
-rw-r--r--core/java/android/hardware/camera2/CameraDevice.java50
-rw-r--r--core/java/android/hardware/camera2/CameraManager.java4
-rw-r--r--core/java/android/hardware/camera2/DngCreator.java42
-rw-r--r--core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java85
-rw-r--r--core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java64
-rw-r--r--core/java/android/hardware/camera2/dispatch/Dispatchable.java35
-rw-r--r--core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java55
-rw-r--r--core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java85
-rw-r--r--core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java55
-rw-r--r--core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java93
-rw-r--r--core/java/android/hardware/camera2/dispatch/NullDispatcher.java38
-rw-r--r--core/java/android/hardware/camera2/dispatch/package.html3
-rw-r--r--core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java579
-rw-r--r--core/java/android/hardware/camera2/impl/CameraDeviceImpl.java (renamed from core/java/android/hardware/camera2/impl/CameraDevice.java)162
-rw-r--r--core/java/android/hardware/camera2/impl/ListenerProxies.java168
-rw-r--r--core/java/android/hardware/camera2/utils/TaskDrainer.java201
-rw-r--r--core/java/android/hardware/camera2/utils/TaskSingleDrainer.java104
-rw-r--r--core/java/android/hardware/camera2/utils/UncheckedThrow.java14
-rw-r--r--core/java/android/hardware/hdmi/HdmiCec.java4
-rw-r--r--core/java/android/net/ConnectivityManager.java259
-rw-r--r--core/java/android/net/ConnectivityServiceProtocol.java70
-rw-r--r--core/java/android/net/IConnectivityManager.aidl4
-rw-r--r--core/java/android/net/NetworkAgent.java337
-rw-r--r--core/java/android/net/NetworkFactory.java275
-rw-r--r--core/java/android/net/NetworkInfo.java14
-rw-r--r--core/java/android/net/NetworkRequest.java22
-rw-r--r--core/java/android/os/BatteryStats.java9
-rw-r--r--core/java/android/os/Process.java6
-rw-r--r--core/java/android/os/UserHandle.java8
-rw-r--r--core/java/android/service/notification/ZenModeConfig.java51
-rw-r--r--core/java/android/service/trust/TrustAgentService.java2
-rw-r--r--core/java/android/speech/tts/TextToSpeechClient.java89
-rw-r--r--core/java/android/view/GLES20Canvas.java114
-rw-r--r--core/java/android/view/GLES20RecordingCanvas.java2
-rw-r--r--core/java/android/view/GLRenderer.java1521
-rw-r--r--core/java/android/view/HardwareCanvas.java42
-rw-r--r--core/java/android/view/HardwareLayer.java37
-rw-r--r--core/java/android/view/HardwareRenderer.java15
-rw-r--r--core/java/android/view/IWindowManager.aidl6
-rw-r--r--core/java/android/view/KeyEvent.java1
-rw-r--r--core/java/android/view/ThreadedRenderer.java10
-rw-r--r--core/java/android/view/View.java20
-rw-r--r--core/java/android/view/ViewRootImpl.java11
-rw-r--r--core/java/android/view/WindowManagerInternal.java9
-rw-r--r--core/java/android/webkit/CookieManager.java3
-rw-r--r--core/java/android/webkit/WebSettings.java32
-rw-r--r--core/java/android/widget/AbsListView.java12
-rw-r--r--core/java/android/widget/EdgeEffect.java5
-rw-r--r--core/java/android/widget/ImageView.java2
-rw-r--r--core/java/android/widget/ProgressBar.java5
-rw-r--r--core/java/android/widget/RadialTimePickerView.java205
-rw-r--r--core/java/android/widget/ShareActionProvider.java2
-rw-r--r--core/java/android/widget/SuggestionsAdapter.java2
-rw-r--r--core/java/android/widget/TimePickerDelegate.java9
-rw-r--r--core/java/android/widget/Toolbar.java3
-rw-r--r--core/java/com/android/internal/app/ChooserActivity.java2
-rw-r--r--core/java/com/android/internal/app/IMediaContainerService.aidl10
-rw-r--r--core/java/com/android/internal/app/NavItemSelectedListener.java46
-rw-r--r--core/java/com/android/internal/app/ToolbarActionBar.java41
-rw-r--r--core/java/com/android/internal/app/WindowDecorActionBar.java23
-rw-r--r--core/java/com/android/internal/backup/BackupConstants.java28
-rw-r--r--core/java/com/android/internal/backup/LocalTransport.java20
-rw-r--r--core/java/com/android/internal/content/NativeLibraryHelper.java15
-rw-r--r--core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java91
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java25
-rw-r--r--core/java/com/android/internal/util/Protocol.java4
-rw-r--r--core/java/com/android/internal/widget/ActionBarView.java6
-rw-r--r--core/java/com/android/internal/widget/DecorToolbar.java2
-rw-r--r--core/java/com/android/internal/widget/ToolbarWidgetWrapper.java70
-rw-r--r--core/jni/Android.mk1
-rw-r--r--core/jni/AndroidRuntime.cpp8
-rw-r--r--core/jni/android/graphics/BitmapFactory.cpp139
-rw-r--r--core/jni/android/graphics/Canvas.cpp333
-rw-r--r--core/jni/android/graphics/FontFamily.cpp52
-rw-r--r--core/jni/android/graphics/MinikinSkia.h1
-rw-r--r--core/jni/android/graphics/MinikinUtils.cpp19
-rw-r--r--core/jni/android/graphics/MinikinUtils.h23
-rw-r--r--core/jni/android/graphics/Paint.cpp103
-rw-r--r--core/jni/android/graphics/TextLayoutCache.cpp6
-rw-r--r--core/jni/android/graphics/TypefaceImpl.cpp23
-rw-r--r--core/jni/android_hardware_camera2_DngCreator.cpp178
-rw-r--r--core/jni/android_media_AudioSystem.cpp8
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp167
-rw-r--r--core/jni/android_view_GLRenderer.cpp203
-rw-r--r--core/jni/android_view_HardwareLayer.cpp17
-rw-r--r--core/jni/android_view_ThreadedRenderer.cpp18
-rw-r--r--core/jni/com_android_internal_content_NativeLibraryHelper.cpp41
-rw-r--r--core/res/AndroidManifest.xml17
-rw-r--r--core/res/res/anim/voice_activity_open_enter.xml1
-rw-r--r--core/res/res/anim/voice_layer_enter.xml1
-rw-r--r--core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.pngbin170 -> 0 bytes
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-hdpi/perm_group_accessibility_features.pngbin1223 -> 685 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_accounts.pngbin1745 -> 890 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_affects_battery.pngbin1241 -> 634 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_app_info.pngbin1714 -> 1491 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_audio_settings.pngbin2008 -> 1446 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_bluetooth.pngbin1579 -> 893 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_bookmarks.pngbin2085 -> 720 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_calendar.pngbin1419 -> 756 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_camera.pngbin1781 -> 2217 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_device_alarms.pngbin2021 -> 2422 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_display.pngbin1218 -> 735 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_location.pngbin1574 -> 825 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_messages.pngbin1634 -> 717 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_microphone.pngbin1600 -> 1330 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_network.pngbin1826 -> 597 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_personal_info.pngbin1603 -> 1079 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_phone_calls.pngbin1691 -> 1316 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_screenlock.pngbin1383 -> 1272 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_shortrange_network.pngbin1319 -> 597 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_social_info.pngbin2075 -> 1044 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_status_bar.pngbin1272 -> 443 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_storage.pngbin1644 -> 1117 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_sync_settings.pngbin1938 -> 1584 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_system_clock.pngbin1794 -> 2529 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_system_tools.pngbin1535 -> 1711 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_user_dictionary.pngbin1386 -> 765 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_user_dictionary_write.pngbin1853 -> 766 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_voicemail.pngbin1655 -> 1275 bytes
-rw-r--r--core/res/res/drawable-hdpi/perm_group_wallpaper.pngbin1431 -> 1002 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_20_inner_holo.pngbin879 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/spinner_20_outer_holo.pngbin759 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/tab_indicator_normal_qntm_alpha.9.pngbin88 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/tab_indicator_qntm_alpha.9.pngbin0 -> 102 bytes
-rw-r--r--core/res/res/drawable-hdpi/tab_indicator_selected_qntm_alpha.9.pngbin87 -> 0 bytes
-rw-r--r--core/res/res/drawable-hdpi/work_icon.pngbin1153 -> 4442 bytes
-rw-r--r--core/res/res/drawable-ldpi/tab_indicator_normal_qntm_alpha.9.pngbin81 -> 0 bytes
-rw-r--r--core/res/res/drawable-ldpi/tab_indicator_selected_qntm_alpha.9.pngbin85 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.pngbin147 -> 0 bytes
-rw-r--r--[-rwxr-xr-x]core/res/res/drawable-mdpi/perm_group_accessibility_features.pngbin845 -> 603 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_accounts.pngbin1471 -> 676 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_affects_battery.pngbin1116 -> 562 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_app_info.pngbin1426 -> 1071 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_audio_settings.pngbin1582 -> 1015 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_bluetooth.pngbin1355 -> 670 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_bookmarks.pngbin1609 -> 600 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_calendar.pngbin1404 -> 657 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_camera.pngbin1465 -> 1571 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_device_alarms.pngbin1546 -> 1669 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_display.pngbin1203 -> 621 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_location.pngbin1360 -> 673 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_messages.pngbin1418 -> 605 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_microphone.pngbin1319 -> 957 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_network.pngbin1434 -> 554 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_personal_info.pngbin1359 -> 803 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_phone_calls.pngbin1429 -> 985 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_screenlock.pngbin1272 -> 979 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_shortrange_network.pngbin1171 -> 554 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_social_info.pngbin1590 -> 1012 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_status_bar.pngbin1160 -> 384 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_storage.pngbin1338 -> 917 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_sync_settings.pngbin1522 -> 1125 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_system_clock.pngbin1408 -> 1765 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_system_tools.pngbin1339 -> 1229 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_user_dictionary.pngbin1253 -> 627 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_user_dictionary_write.pngbin1530 -> 595 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_voicemail.pngbin1326 -> 1230 bytes
-rw-r--r--core/res/res/drawable-mdpi/perm_group_wallpaper.pngbin1240 -> 760 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_20_inner_holo.pngbin627 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/spinner_20_outer_holo.pngbin548 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/tab_indicator_normal_qntm_alpha.9.pngbin91 -> 0 bytes
-rw-r--r--core/res/res/drawable-mdpi/tab_indicator_qntm_alpha.9.pngbin0 -> 94 bytes
-rw-r--r--core/res/res/drawable-mdpi/tab_indicator_selected_qntm_alpha.9.pngbin85 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.pngbin194 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_accessibility_features.pngbin1631 -> 1014 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_accounts.pngbin2030 -> 1296 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_affects_battery.pngbin1304 -> 794 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_app_info.pngbin1839 -> 2312 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_audio_settings.pngbin2489 -> 2272 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_bluetooth.pngbin1948 -> 1380 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_bookmarks.pngbin2657 -> 1083 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_calendar.pngbin1680 -> 1084 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_camera.pngbin2050 -> 3674 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_device_alarms.pngbin2626 -> 3925 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_display.pngbin1425 -> 1035 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_location.pngbin1911 -> 1246 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_messages.pngbin1927 -> 1082 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_microphone.pngbin1866 -> 1954 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_network.pngbin2190 -> 991 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_personal_info.pngbin1910 -> 1664 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_phone_calls.pngbin2021 -> 2100 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_screenlock.pngbin1561 -> 1994 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_shortrange_network.pngbin1498 -> 991 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_social_info.pngbin2541 -> 2017 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_status_bar.pngbin1407 -> 494 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_storage.pngbin1924 -> 1744 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_sync_settings.pngbin2338 -> 2622 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_system_clock.pngbin2284 -> 3964 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_system_tools.pngbin1641 -> 2773 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_user_dictionary.pngbin1452 -> 1228 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.pngbin2166 -> 1129 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_voicemail.pngbin1971 -> 2579 bytes
-rw-r--r--core/res/res/drawable-xhdpi/perm_group_wallpaper.pngbin1544 -> 1513 bytes
-rw-r--r--core/res/res/drawable-xhdpi/spinner_20_inner_holo.pngbin1160 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/spinner_20_outer_holo.pngbin1007 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/tab_indicator_normal_qntm_alpha.9.pngbin95 -> 0 bytes
-rw-r--r--core/res/res/drawable-xhdpi/tab_indicator_qntm_alpha.9.pngbin0 -> 112 bytes
-rw-r--r--core/res/res/drawable-xhdpi/tab_indicator_selected_qntm_alpha.9.pngbin88 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.pngbin327 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_accessibility_features.pngbin0 -> 753 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_accounts.pngbin0 -> 995 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_affects_battery.pngbin0 -> 15116 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_app_info.pngbin0 -> 1993 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_audio_settings.pngbin0 -> 1991 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_bluetooth.pngbin0 -> 1084 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_bookmarks.pngbin0 -> 806 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_calendar.pngbin0 -> 873 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_camera.pngbin0 -> 3293 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_device_alarms.pngbin0 -> 3532 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_display.pngbin0 -> 833 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_location.pngbin0 -> 878 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_messages.pngbin0 -> 847 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_microphone.pngbin0 -> 1775 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_network.pngbin0 -> 541 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_personal_info.pngbin0 -> 1299 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_phone_calls.pngbin0 -> 1770 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_screenlock.pngbin0 -> 1654 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_shortrange_network.pngbin0 -> 541 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_social_info.pngbin0 -> 1346 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_status_bar.pngbin0 -> 15333 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_storage.pngbin0 -> 1442 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_sync_settings.pngbin0 -> 2174 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_system_clock.pngbin0 -> 3099 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_system_tools.pngbin0 -> 2442 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_user_dictionary.pngbin0 -> 913 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_user_dictionary_write.pngbin0 -> 826 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_voicemail.pngbin0 -> 1817 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/perm_group_wallpaper.pngbin0 -> 1229 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/spinner_20_inner_holo.pngbin2746 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/spinner_20_outer_holo.pngbin2097 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/tab_indicator_normal_qntm_alpha.9.pngbin149 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/tab_indicator_qntm_alpha.9.pngbin0 -> 142 bytes
-rw-r--r--core/res/res/drawable-xxhdpi/tab_indicator_selected_qntm_alpha.9.pngbin142 -> 0 bytes
-rw-r--r--core/res/res/drawable-xxxhdpi/tab_indicator_qntm_alpha.9.pngbin0 -> 171 bytes
-rw-r--r--core/res/res/drawable/edit_text_quantum.xml17
-rw-r--r--core/res/res/drawable/ic_lock_bugreport.xml37
-rw-r--r--core/res/res/drawable/progress_large_quantum.xml22
-rw-r--r--core/res/res/drawable/progress_medium_quantum.xml22
-rw-r--r--core/res/res/drawable/progress_small_quantum.xml22
-rw-r--r--core/res/res/drawable/tab_indicator_quantum.xml24
-rw-r--r--core/res/res/transition/fade.xml16
-rw-r--r--core/res/res/transition/move.xml30
-rw-r--r--core/res/res/values-km-rKH/strings.xml100
-rw-r--r--core/res/res/values-lo-rLA/strings.xml2
-rw-r--r--core/res/res/values/arrays.xml195
-rw-r--r--core/res/res/values/attrs.xml37
-rw-r--r--core/res/res/values/colors_quantum.xml61
-rw-r--r--core/res/res/values/config.xml8
-rw-r--r--core/res/res/values/dimens_quantum.xml6
-rw-r--r--core/res/res/values/public.xml5
-rw-r--r--core/res/res/values/strings.xml17
-rw-r--r--core/res/res/values/styles.xml1
-rw-r--r--core/res/res/values/styles_quantum.xml169
-rw-r--r--core/res/res/values/symbols.xml14
-rw-r--r--core/res/res/values/themes.xml4
-rw-r--r--core/res/res/values/themes_quantum.xml53
-rw-r--r--core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java30
-rw-r--r--docs/html/about/dashboards/index.jd50
-rw-r--r--docs/html/distribute/engage/deep-linking.jd2
-rw-r--r--docs/html/distribute/essentials/quality/core.jd16
-rw-r--r--docs/html/distribute/essentials/quality/tablets.jd20
-rw-r--r--docs/html/distribute/googleplay/edu/about.jd2
-rw-r--r--docs/html/distribute/tools/launch-checklist.jd64
-rw-r--r--docs/html/distribute/tools/localization-checklist.jd24
-rw-r--r--docs/html/distribute/tools/promote/badge-files.jd6
-rw-r--r--docs/html/guide/components/fundamentals.jd4
-rw-r--r--docs/html/images/training/volley-request.pngbin0 -> 61812 bytes
-rw-r--r--docs/html/tools/sdk/tools-notes.jd33
-rw-r--r--docs/html/training/basics/network-ops/connecting.jd1
-rw-r--r--docs/html/training/basics/network-ops/index.jd9
-rw-r--r--docs/html/training/contacts-provider/retrieve-names.jd12
-rw-r--r--docs/html/training/training_toc.cs29
-rw-r--r--docs/html/training/volley/index.jd133
-rw-r--r--docs/html/training/volley/request-custom.jd163
-rw-r--r--docs/html/training/volley/request.jd281
-rw-r--r--docs/html/training/volley/requestqueue.jd204
-rw-r--r--docs/html/training/volley/simple.jd169
-rw-r--r--docs/image_sources/training/volley/volley-request.graffle2259
-rw-r--r--graphics/java/android/graphics/BitmapFactory.java20
-rw-r--r--graphics/java/android/graphics/Canvas.java132
-rw-r--r--graphics/java/android/graphics/FontFamily.java18
-rw-r--r--graphics/java/android/graphics/Paint.java21
-rw-r--r--graphics/java/android/graphics/Typeface.java22
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java4
-rw-r--r--graphics/java/android/graphics/drawable/AnimationDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ClipDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/Drawable.java44
-rw-r--r--graphics/java/android/graphics/drawable/InsetDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/LayerDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/LevelListDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/NinePatchDrawable.java7
-rw-r--r--graphics/java/android/graphics/drawable/QuantumProgressDrawable.java520
-rw-r--r--graphics/java/android/graphics/drawable/Ripple.java28
-rw-r--r--graphics/java/android/graphics/drawable/RippleDrawable.java38
-rw-r--r--graphics/java/android/graphics/drawable/RotateDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ScaleDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/ShapeDrawable.java47
-rw-r--r--graphics/java/android/graphics/drawable/StateListDrawable.java2
-rw-r--r--graphics/java/android/graphics/drawable/VectorDrawable.java326
-rw-r--r--libs/hwui/Android.mk11
-rw-r--r--libs/hwui/DisplayListOp.h14
-rw-r--r--media/java/android/media/AudioFormat.java152
-rw-r--r--media/java/android/media/AudioManager.java12
-rw-r--r--media/java/android/media/AudioPort.java2
-rw-r--r--media/java/android/media/AudioTrack.java2
-rw-r--r--media/java/android/media/tv/ITvInputClient.aidl (renamed from core/java/android/tv/ITvInputClient.aidl)8
-rw-r--r--media/java/android/media/tv/ITvInputHardware.aidl (renamed from core/java/android/tv/ITvInputHardware.aidl)4
-rw-r--r--media/java/android/media/tv/ITvInputHardwareCallback.aidl (renamed from core/java/android/tv/ITvInputHardwareCallback.aidl)4
-rw-r--r--media/java/android/media/tv/ITvInputManager.aidl (renamed from core/java/android/tv/ITvInputManager.aidl)12
-rw-r--r--media/java/android/media/tv/ITvInputService.aidl (renamed from core/java/android/tv/ITvInputService.aidl)6
-rw-r--r--media/java/android/media/tv/ITvInputServiceCallback.aidl (renamed from core/java/android/tv/ITvInputServiceCallback.aidl)2
-rw-r--r--media/java/android/media/tv/ITvInputSession.aidl (renamed from core/java/android/tv/ITvInputSession.aidl)2
-rw-r--r--media/java/android/media/tv/ITvInputSessionCallback.aidl (renamed from core/java/android/tv/ITvInputSessionCallback.aidl)8
-rw-r--r--media/java/android/media/tv/ITvInputSessionWrapper.java (renamed from core/java/android/tv/ITvInputSessionWrapper.java)8
-rw-r--r--media/java/android/media/tv/TvContract.java (renamed from core/java/android/provider/TvContract.java)168
-rw-r--r--media/java/android/media/tv/TvInputHardwareInfo.aidl (renamed from core/java/android/tv/TvInputHardwareInfo.aidl)2
-rw-r--r--media/java/android/media/tv/TvInputHardwareInfo.java (renamed from core/java/android/tv/TvInputHardwareInfo.java)2
-rw-r--r--media/java/android/media/tv/TvInputInfo.aidl (renamed from core/java/android/tv/TvInputInfo.aidl)2
-rw-r--r--media/java/android/media/tv/TvInputInfo.java (renamed from core/java/android/tv/TvInputInfo.java)121
-rw-r--r--media/java/android/media/tv/TvInputManager.java (renamed from core/java/android/tv/TvInputManager.java)87
-rw-r--r--media/java/android/media/tv/TvInputService.java (renamed from core/java/android/tv/TvInputService.java)67
-rw-r--r--media/java/android/media/tv/TvStreamConfig.aidl (renamed from core/java/android/tv/TvStreamConfig.aidl)2
-rw-r--r--media/java/android/media/tv/TvStreamConfig.java (renamed from core/java/android/tv/TvStreamConfig.java)2
-rw-r--r--media/java/android/media/tv/TvView.java (renamed from core/java/android/tv/TvView.java)33
-rw-r--r--packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java61
-rw-r--r--packages/DocumentsUI/res/values-fi/strings.xml2
-rw-r--r--packages/DocumentsUI/res/values-fr/strings.xml2
-rw-r--r--packages/DocumentsUI/res/values-km-rKH/strings.xml6
-rw-r--r--packages/Keyguard/Android.mk6
-rw-r--r--packages/Keyguard/res/layout/keyguard_status_view.xml13
-rw-r--r--packages/Keyguard/res/values-km-rKH/strings.xml4
-rw-r--r--packages/Keyguard/res/values-sw600dp/dimens.xml3
-rw-r--r--packages/Keyguard/res/values/dimens.xml3
-rw-r--r--packages/Keyguard/res/values/strings.xml4
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java28
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java3
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java26
-rw-r--r--packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java2
-rw-r--r--packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java278
-rw-r--r--packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java109
-rw-r--r--packages/Keyguard/src/com/android/keyguard/analytics/Session.java220
-rw-r--r--packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto102
-rw-r--r--packages/Keyguard/test/SampleTrustAgent/Android.mk5
-rw-r--r--packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml1
-rw-r--r--packages/PrintSpooler/res/values-km-rKH/strings.xml2
-rw-r--r--packages/Shell/res/values-de/strings.xml2
-rw-r--r--packages/Shell/res/values-fr/strings.xml2
-rw-r--r--packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.pngbin0 -> 1054 bytes
-rw-r--r--packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.pngbin0 -> 1050 bytes
-rw-r--r--packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.pngbin0 -> 985 bytes
-rw-r--r--packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.pngbin0 -> 1070 bytes
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_06.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_07.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_08.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_09.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_10.xml4
-rw-r--r--packages/SystemUI/res/drawable/ic_qs_location_11.xml4
-rw-r--r--packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml21
-rw-r--r--packages/SystemUI/res/layout/recents_nav_bar_scrim.xml23
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml20
-rw-r--r--packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml4
-rw-r--r--packages/SystemUI/res/layout/volume_panel_item.xml1
-rw-r--r--packages/SystemUI/res/values-af/strings.xml4
-rw-r--r--packages/SystemUI/res/values-am/strings.xml31
-rw-r--r--packages/SystemUI/res/values-ar/strings.xml4
-rw-r--r--packages/SystemUI/res/values-bg/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ca/strings.xml4
-rw-r--r--packages/SystemUI/res/values-cs/strings.xml4
-rw-r--r--packages/SystemUI/res/values-da/strings.xml4
-rw-r--r--packages/SystemUI/res/values-de/strings.xml4
-rw-r--r--packages/SystemUI/res/values-el/strings.xml4
-rw-r--r--packages/SystemUI/res/values-en-rGB/strings.xml4
-rw-r--r--packages/SystemUI/res/values-en-rIN/strings.xml4
-rw-r--r--packages/SystemUI/res/values-es-rUS/strings.xml5
-rw-r--r--packages/SystemUI/res/values-es/strings.xml4
-rw-r--r--packages/SystemUI/res/values-et-rEE/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fa/strings.xml4
-rw-r--r--packages/SystemUI/res/values-fi/strings.xml5
-rw-r--r--packages/SystemUI/res/values-fr-rCA/strings.xml30
-rw-r--r--packages/SystemUI/res/values-fr/strings.xml31
-rw-r--r--packages/SystemUI/res/values-hi/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hr/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hu/strings.xml4
-rw-r--r--packages/SystemUI/res/values-hy-rAM/strings.xml30
-rw-r--r--packages/SystemUI/res/values-in/strings.xml4
-rw-r--r--packages/SystemUI/res/values-it/strings.xml4
-rw-r--r--packages/SystemUI/res/values-iw/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ja/strings.xml31
-rw-r--r--packages/SystemUI/res/values-ka-rGE/strings.xml30
-rw-r--r--packages/SystemUI/res/values-km-rKH/strings.xml13
-rw-r--r--packages/SystemUI/res/values-ko/strings.xml4
-rw-r--r--packages/SystemUI/res/values-lo-rLA/strings.xml14
-rw-r--r--packages/SystemUI/res/values-lt/strings.xml4
-rw-r--r--packages/SystemUI/res/values-lv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-mn-rMN/strings.xml31
-rw-r--r--packages/SystemUI/res/values-ms-rMY/strings.xml30
-rw-r--r--packages/SystemUI/res/values-nb/strings.xml4
-rw-r--r--packages/SystemUI/res/values-nl/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pl/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pt-rPT/strings.xml4
-rw-r--r--packages/SystemUI/res/values-pt/strings.xml30
-rw-r--r--packages/SystemUI/res/values-rm/strings.xml4
-rw-r--r--packages/SystemUI/res/values-ro/strings.xml31
-rw-r--r--packages/SystemUI/res/values-ru/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sk/strings.xml31
-rw-r--r--packages/SystemUI/res/values-sl/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sr/strings.xml4
-rw-r--r--packages/SystemUI/res/values-sv/strings.xml5
-rw-r--r--packages/SystemUI/res/values-sw/strings.xml31
-rw-r--r--packages/SystemUI/res/values-th/strings.xml31
-rw-r--r--packages/SystemUI/res/values-tl/strings.xml31
-rw-r--r--packages/SystemUI/res/values-tr/strings.xml30
-rw-r--r--packages/SystemUI/res/values-uk/strings.xml4
-rw-r--r--packages/SystemUI/res/values-vi/strings.xml4
-rw-r--r--packages/SystemUI/res/values-zh-rCN/strings.xml31
-rw-r--r--packages/SystemUI/res/values-zh-rHK/strings.xml8
-rw-r--r--packages/SystemUI/res/values-zh-rTW/strings.xml4
-rw-r--r--packages/SystemUI/res/values-zu/strings.xml4
-rw-r--r--packages/SystemUI/res/values/colors.xml2
-rw-r--r--packages/SystemUI/res/values/config.xml15
-rw-r--r--packages/SystemUI/res/values/dimens.xml21
-rw-r--r--packages/SystemUI/res/values/strings.xml25
-rw-r--r--packages/SystemUI/res/values/styles.xml6
-rw-r--r--packages/SystemUI/src/com/android/systemui/DessertCaseView.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/ExpandHelper.java189
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java43
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java9
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSTileView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java6
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java56
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java11
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java12
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java7
-rw-r--r--packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedView.java50
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java3
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java8
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java19
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java190
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java28
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java25
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java4
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java107
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java266
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java76
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java81
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java1
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java5
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java49
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java327
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java13
-rw-r--r--packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java314
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java26
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java88
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java129
-rw-r--r--rs/java/android/renderscript/FieldPacker.java14
-rw-r--r--rs/java/android/renderscript/RenderScript.java7
-rw-r--r--rs/java/android/renderscript/ScriptC.java33
-rw-r--r--rs/jni/android_renderscript_RenderScript.cpp7
-rw-r--r--services/backup/java/com/android/server/backup/BackupManagerService.java78
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java386
-rw-r--r--services/core/java/com/android/server/InputMethodManagerService.java117
-rw-r--r--services/core/java/com/android/server/LocationManagerService.java5
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java15
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java22
-rw-r--r--services/core/java/com/android/server/connectivity/NetworkAgentInfo.java5
-rw-r--r--services/core/java/com/android/server/content/ContentService.java129
-rw-r--r--services/core/java/com/android/server/content/SyncStorageEngine.java22
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecController.java2
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java67
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiConstants.java47
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiControlService.java117
-rw-r--r--services/core/java/com/android/server/hdmi/HdmiUtils.java74
-rw-r--r--services/core/java/com/android/server/hdmi/RequestArcAction.java21
-rw-r--r--services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java13
-rw-r--r--services/core/java/com/android/server/hdmi/SystemAudioAction.java192
-rw-r--r--services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java69
-rw-r--r--services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java50
-rw-r--r--services/core/java/com/android/server/location/FlpHardwareProvider.java2
-rw-r--r--services/core/java/com/android/server/notification/ConditionProviders.java118
-rw-r--r--services/core/java/com/android/server/notification/CountdownConditionProvider.java146
-rw-r--r--services/core/java/com/android/server/notification/NotificationManagerService.java26
-rwxr-xr-xservices/core/java/com/android/server/pm/PackageManagerService.java190
-rw-r--r--services/core/java/com/android/server/trust/TrustManagerService.java11
-rw-r--r--services/core/java/com/android/server/tv/TvInputHal.java4
-rw-r--r--services/core/java/com/android/server/tv/TvInputHardwareManager.java8
-rw-r--r--services/core/java/com/android/server/tv/TvInputManagerService.java266
-rw-r--r--services/core/java/com/android/server/wm/CircularDisplayMask.java51
-rw-r--r--services/core/java/com/android/server/wm/TaskStack.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java136
-rw-r--r--services/core/jni/com_android_server_location_FlpHardwareProvider.cpp77
-rw-r--r--services/core/jni/com_android_server_tv_TvInputHal.cpp18
-rw-r--r--services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java105
-rw-r--r--services/java/com/android/server/SystemServer.java12
-rw-r--r--tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java1
-rw-r--r--tests/VectorDrawableTest/AndroidManifest.xml33
-rw-r--r--tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml36
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable06.xml4
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable12.xml1
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable14.xml1
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable17.xml1
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable18.xml1
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable19.xml1
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable22.xml72
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable23.xml86
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_drawable24.xml91
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_test01.xml3
-rw-r--r--tests/VectorDrawableTest/res/drawable/vector_test02.xml3
-rw-r--r--tests/VectorDrawableTest/res/values/strings.xml1
-rw-r--r--tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java2
-rw-r--r--tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java45
-rw-r--r--tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java7
-rw-r--r--tools/aapt/Main.cpp12
-rw-r--r--tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java5
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java28
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java45
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java17
-rw-r--r--wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java47
555 files changed, 14487 insertions, 8191 deletions
diff --git a/Android.mk b/Android.mk
index 2f3a990..642d8b9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -217,14 +217,6 @@ LOCAL_SRC_FILES += \
core/java/android/service/wallpaper/IWallpaperConnection.aidl \
core/java/android/service/wallpaper/IWallpaperEngine.aidl \
core/java/android/service/wallpaper/IWallpaperService.aidl \
- core/java/android/tv/ITvInputClient.aidl \
- core/java/android/tv/ITvInputHardware.aidl \
- core/java/android/tv/ITvInputHardwareCallback.aidl \
- core/java/android/tv/ITvInputManager.aidl \
- core/java/android/tv/ITvInputService.aidl \
- core/java/android/tv/ITvInputServiceCallback.aidl \
- core/java/android/tv/ITvInputSession.aidl \
- core/java/android/tv/ITvInputSessionCallback.aidl \
core/java/android/view/accessibility/IAccessibilityInteractionConnection.aidl\
core/java/android/view/accessibility/IAccessibilityInteractionConnectionCallback.aidl\
core/java/android/view/accessibility/IAccessibilityManager.aidl \
@@ -322,6 +314,14 @@ LOCAL_SRC_FILES += \
media/java/android/media/session/ISession.aidl \
media/java/android/media/session/ISessionCallback.aidl \
media/java/android/media/session/ISessionManager.aidl \
+ media/java/android/media/tv/ITvInputClient.aidl \
+ media/java/android/media/tv/ITvInputHardware.aidl \
+ media/java/android/media/tv/ITvInputHardwareCallback.aidl \
+ media/java/android/media/tv/ITvInputManager.aidl \
+ media/java/android/media/tv/ITvInputService.aidl \
+ media/java/android/media/tv/ITvInputServiceCallback.aidl \
+ media/java/android/media/tv/ITvInputSession.aidl \
+ media/java/android/media/tv/ITvInputSessionCallback.aidl \
telecomm/java/com/android/internal/telecomm/ICallService.aidl \
telecomm/java/com/android/internal/telecomm/ICallServiceAdapter.aidl \
telecomm/java/com/android/internal/telecomm/ICallServiceLookupResponse.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 48a20a4..f3bb9b6 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -192,6 +192,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/app)
$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app/wearable)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/ITv*)
# ************************************************
# NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/\ b/\
new file mode 100644
index 0000000..1d25d33
--- /dev/null
+++ b/\
@@ -0,0 +1,19 @@
+Doc update: new Volley class
+
+Change-Id: Ife3a9a64439e07aaaf92a22adc6d1678138caf7d
+
+# Please enter the commit message for your changes. Lines starting
+# with '#' will be ignored, and an empty message aborts the commit.
+# On branch volley
+# Changes to be committed:
+# new file: docs/html/images/training/volley-request.png
+# modified: docs/html/training/basics/network-ops/connecting.jd
+# modified: docs/html/training/basics/network-ops/index.jd
+# modified: docs/html/training/training_toc.cs
+# new file: docs/html/training/volley/index.jd
+# new file: docs/html/training/volley/request-custom.jd
+# new file: docs/html/training/volley/request.jd
+# new file: docs/html/training/volley/requestqueue.jd
+# new file: docs/html/training/volley/setup.jd
+# new file: docs/html/training/volley/simple.jd
+#
diff --git a/api/current.txt b/api/current.txt
index b059841..2b667c0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -132,7 +132,6 @@ package android {
field public static final java.lang.String SET_WALLPAPER = "android.permission.SET_WALLPAPER";
field public static final java.lang.String SET_WALLPAPER_HINTS = "android.permission.SET_WALLPAPER_HINTS";
field public static final java.lang.String SIGNAL_PERSISTENT_PROCESSES = "android.permission.SIGNAL_PERSISTENT_PROCESSES";
- field public static final java.lang.String SIM_COMMUNICATION = "android.permission.SIM_COMMUNICATION";
field public static final java.lang.String STATUS_BAR = "android.permission.STATUS_BAR";
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";
@@ -266,7 +265,7 @@ package android {
field public static final int actionModeSplitBackground = 16843677; // 0x101039d
field public static final int actionModeStyle = 16843668; // 0x1010394
field public static final int actionOverflowButtonStyle = 16843510; // 0x10102f6
- field public static final int actionOverflowMenuStyle = 16843848; // 0x1010448
+ field public static final int actionOverflowMenuStyle = 16843847; // 0x1010447
field public static final int actionProviderClass = 16843657; // 0x1010389
field public static final int actionViewClass = 16843516; // 0x10102fc
field public static final int activatedBackgroundIndicator = 16843517; // 0x10102fd
@@ -312,7 +311,7 @@ package android {
field public static final int autoCompleteTextViewStyle = 16842859; // 0x101006b
field public static final int autoLink = 16842928; // 0x10100b0
field public static final int autoMirrored = 16843754; // 0x10103ea
- field public static final int autoRemoveFromRecents = 16843850; // 0x101044a
+ field public static final int autoRemoveFromRecents = 16843849; // 0x1010449
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
@@ -385,7 +384,7 @@ package android {
field public static final int codes = 16843330; // 0x1010242
field public static final int collapseColumns = 16843083; // 0x101014b
field public static final int color = 16843173; // 0x10101a5
- field public static final int colorAccent = 16843833; // 0x1010439
+ field public static final int colorAccent = 16843832; // 0x1010438
field public static final int colorActivatedHighlight = 16843664; // 0x1010390
field public static final int colorBackground = 16842801; // 0x1010031
field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
@@ -399,9 +398,8 @@ package android {
field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
field public static final int colorPressedHighlight = 16843661; // 0x101038d
- field public static final int colorPrimary = 16843831; // 0x1010437
- field public static final int colorPrimaryDark = 16843832; // 0x1010438
- field public static final int colorPrimaryLight = 16843830; // 0x1010436
+ field public static final int colorPrimary = 16843830; // 0x1010436
+ field public static final int colorPrimaryDark = 16843831; // 0x1010437
field public static final int columnCount = 16843639; // 0x1010377
field public static final int columnDelay = 16843215; // 0x10101cf
field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -416,10 +414,10 @@ package android {
field public static final int content = 16843355; // 0x101025b
field public static final int contentAuthority = 16843408; // 0x1010290
field public static final int contentDescription = 16843379; // 0x1010273
- field public static final int contentInsetEnd = 16843863; // 0x1010457
- field public static final int contentInsetLeft = 16843864; // 0x1010458
- field public static final int contentInsetRight = 16843865; // 0x1010459
- field public static final int contentInsetStart = 16843862; // 0x1010456
+ field public static final int contentInsetEnd = 16843862; // 0x1010456
+ field public static final int contentInsetLeft = 16843863; // 0x1010457
+ field public static final int contentInsetRight = 16843864; // 0x1010458
+ field public static final int contentInsetStart = 16843861; // 0x1010455
field public static final int controlX1 = 16843798; // 0x1010416
field public static final int controlX2 = 16843800; // 0x1010418
field public static final int controlY1 = 16843799; // 0x1010417
@@ -464,7 +462,7 @@ package android {
field public static final int dividerHorizontal = 16843564; // 0x101032c
field public static final int dividerPadding = 16843562; // 0x101032a
field public static final int dividerVertical = 16843530; // 0x101030a
- field public static final int documentLaunchMode = 16843849; // 0x1010449
+ field public static final int documentLaunchMode = 16843848; // 0x1010448
field public static final int drawSelectorOnTop = 16843004; // 0x10100fc
field public static final int drawable = 16843161; // 0x1010199
field public static final int drawableBottom = 16843118; // 0x101016e
@@ -493,7 +491,7 @@ package android {
field public static final int editTextStyle = 16842862; // 0x101006e
field public static final deprecated int editable = 16843115; // 0x101016b
field public static final int editorExtras = 16843300; // 0x1010224
- field public static final int elevation = 16843844; // 0x1010444
+ field public static final int elevation = 16843843; // 0x1010443
field public static final int ellipsize = 16842923; // 0x10100ab
field public static final int ems = 16843096; // 0x1010158
field public static final int enabled = 16842766; // 0x101000e
@@ -503,10 +501,10 @@ package android {
field public static final int entries = 16842930; // 0x10100b2
field public static final int entryValues = 16843256; // 0x10101f8
field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d
- field public static final int excludeClass = 16843846; // 0x1010446
+ field public static final int excludeClass = 16843845; // 0x1010445
field public static final int excludeFromRecents = 16842775; // 0x1010017
- field public static final int excludeId = 16843845; // 0x1010445
- field public static final int excludeViewName = 16843857; // 0x1010451
+ field public static final int excludeId = 16843844; // 0x1010444
+ field public static final int excludeViewName = 16843856; // 0x1010450
field public static final int exitFadeDuration = 16843533; // 0x101030d
field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
@@ -568,7 +566,7 @@ package android {
field public static final int freezesText = 16843116; // 0x101016c
field public static final int fromAlpha = 16843210; // 0x10101ca
field public static final int fromDegrees = 16843187; // 0x10101b3
- field public static final int fromId = 16843853; // 0x101044d
+ field public static final int fromId = 16843852; // 0x101044c
field public static final int fromScene = 16843741; // 0x10103dd
field public static final int fromXDelta = 16843206; // 0x10101c6
field public static final int fromXScale = 16843202; // 0x10101c2
@@ -601,7 +599,7 @@ package android {
field public static final int headerBackground = 16843055; // 0x101012f
field public static final int headerDividersEnabled = 16843310; // 0x101022e
field public static final int height = 16843093; // 0x1010155
- field public static final int hideOnContentScroll = 16843847; // 0x1010447
+ field public static final int hideOnContentScroll = 16843846; // 0x1010446
field public static final int hint = 16843088; // 0x1010150
field public static final int homeAsUpIndicator = 16843531; // 0x101030b
field public static final int homeLayout = 16843549; // 0x101031d
@@ -708,7 +706,6 @@ package android {
field public static final int l_resource_pad24 = 16843769; // 0x10103f9
field public static final int l_resource_pad25 = 16843768; // 0x10103f8
field public static final int l_resource_pad26 = 16843767; // 0x10103f7
- field public static final int l_resource_pad27 = 16843766; // 0x10103f6
field public static final int l_resource_pad3 = 16843790; // 0x101040e
field public static final int l_resource_pad4 = 16843789; // 0x101040d
field public static final int l_resource_pad5 = 16843788; // 0x101040c
@@ -749,7 +746,6 @@ package android {
field public static final int layout_centerVertical = 16843153; // 0x1010191
field public static final int layout_column = 16843084; // 0x101014c
field public static final int layout_columnSpan = 16843645; // 0x101037d
- field public static final int layout_columnWeight = 16843868; // 0x101045c
field public static final int layout_gravity = 16842931; // 0x10100b3
field public static final int layout_height = 16842997; // 0x10100f5
field public static final int layout_margin = 16842998; // 0x10100f6
@@ -761,7 +757,6 @@ package android {
field public static final int layout_marginTop = 16843000; // 0x10100f8
field public static final int layout_row = 16843643; // 0x101037b
field public static final int layout_rowSpan = 16843644; // 0x101037c
- field public static final int layout_rowWeight = 16843867; // 0x101045b
field public static final int layout_scale = 16843155; // 0x1010193
field public static final int layout_span = 16843085; // 0x101014d
field public static final int layout_toEndOf = 16843704; // 0x10103b8
@@ -800,7 +795,7 @@ package android {
field public static final int manageSpaceActivity = 16842756; // 0x1010004
field public static final int mapViewStyle = 16842890; // 0x101008a
field public static final int marqueeRepeatLimit = 16843293; // 0x101021d
- field public static final int matchOrder = 16843858; // 0x1010452
+ field public static final int matchOrder = 16843857; // 0x1010451
field public static final int max = 16843062; // 0x1010136
field public static final int maxDate = 16843584; // 0x1010340
field public static final int maxEms = 16843095; // 0x1010157
@@ -833,10 +828,10 @@ package android {
field public static final int moreIcon = 16843061; // 0x1010135
field public static final int multiprocess = 16842771; // 0x1010013
field public static final int name = 16842755; // 0x1010003
- field public static final int navigationBarColor = 16843861; // 0x1010455
+ field public static final int navigationBarColor = 16843860; // 0x1010454
field public static final int navigationMode = 16843471; // 0x10102cf
field public static final int negativeButtonText = 16843254; // 0x10101f6
- field public static final int nestedScrollingEnabled = 16843834; // 0x101043a
+ field public static final int nestedScrollingEnabled = 16843833; // 0x1010439
field public static final int nextFocusDown = 16842980; // 0x10100e4
field public static final int nextFocusForward = 16843580; // 0x101033c
field public static final int nextFocusLeft = 16842977; // 0x10100e1
@@ -867,7 +862,7 @@ package android {
field public static final int paddingBottom = 16842969; // 0x10100d9
field public static final int paddingEnd = 16843700; // 0x10103b4
field public static final int paddingLeft = 16842966; // 0x10100d6
- field public static final int paddingMode = 16843866; // 0x101045a
+ field public static final int paddingMode = 16843865; // 0x1010459
field public static final int paddingRight = 16842968; // 0x10100d8
field public static final int paddingStart = 16843699; // 0x10103b3
field public static final int paddingTop = 16842967; // 0x10100d7
@@ -963,7 +958,7 @@ package android {
field public static final int restoreAnyVersion = 16843450; // 0x10102ba
field public static final deprecated int restoreNeedsApplication = 16843421; // 0x101029d
field public static final int restrictedAccountType = 16843733; // 0x10103d5
- field public static final int reversible = 16843854; // 0x101044e
+ field public static final int reversible = 16843853; // 0x101044d
field public static final int right = 16843183; // 0x10101af
field public static final int ringtonePreferenceStyle = 16842899; // 0x1010093
field public static final int ringtoneType = 16843257; // 0x10101f9
@@ -1017,11 +1012,12 @@ package android {
field public static final int selectAllOnFocus = 16843102; // 0x101015e
field public static final int selectable = 16843238; // 0x10101e6
field public static final int selectableItemBackground = 16843534; // 0x101030e
- field public static final int selectableItemBackgroundBorderless = 16843871; // 0x101045f
+ field public static final int selectableItemBackgroundBorderless = 16843866; // 0x101045a
field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
- field public static final int sessionService = 16843841; // 0x1010441
+ field public static final int sessionService = 16843840; // 0x1010440
field public static final int settingsActivity = 16843301; // 0x1010225
+ field public static final int setupActivity = 16843766; // 0x10103f6
field public static final int shadowColor = 16843105; // 0x1010161
field public static final int shadowDx = 16843106; // 0x1010162
field public static final int shadowDy = 16843107; // 0x1010163
@@ -1053,19 +1049,19 @@ package android {
field public static final int spinnerStyle = 16842881; // 0x1010081
field public static final int spinnersShown = 16843595; // 0x101034b
field public static final int splitMotionEvents = 16843503; // 0x10102ef
- field public static final int splitTrack = 16843855; // 0x101044f
+ field public static final int splitTrack = 16843854; // 0x101044e
field public static final int src = 16843033; // 0x1010119
field public static final int ssp = 16843747; // 0x10103e3
field public static final int sspPattern = 16843749; // 0x10103e5
field public static final int sspPrefix = 16843748; // 0x10103e4
field public static final int stackFromBottom = 16843005; // 0x10100fd
- field public static final int stackViewStyle = 16843842; // 0x1010442
+ field public static final int stackViewStyle = 16843841; // 0x1010441
field public static final int starStyle = 16842882; // 0x1010082
field public static final int startColor = 16843165; // 0x101019d
field public static final int startDelay = 16843746; // 0x10103e2
field public static final int startOffset = 16843198; // 0x10101be
field public static final deprecated int startYear = 16843132; // 0x101017c
- field public static final int stateListAnimator = 16843851; // 0x101044b
+ field public static final int stateListAnimator = 16843850; // 0x101044a
field public static final int stateNotNeeded = 16842774; // 0x1010016
field public static final int state_above_anchor = 16842922; // 0x10100aa
field public static final int state_accelerated = 16843547; // 0x101031b
@@ -1090,7 +1086,7 @@ package android {
field public static final int state_single = 16842915; // 0x10100a3
field public static final int state_window_focused = 16842909; // 0x101009d
field public static final int staticWallpaperPreview = 16843569; // 0x1010331
- field public static final int statusBarColor = 16843860; // 0x1010454
+ field public static final int statusBarColor = 16843859; // 0x1010453
field public static final int stepSize = 16843078; // 0x1010146
field public static final int stopWithTask = 16843626; // 0x101036a
field public static final int streamType = 16843273; // 0x1010209
@@ -1119,7 +1115,7 @@ package android {
field public static final int switchMinWidth = 16843632; // 0x1010370
field public static final int switchPadding = 16843633; // 0x1010371
field public static final int switchPreferenceStyle = 16843629; // 0x101036d
- field public static final int switchStyle = 16843843; // 0x1010443
+ field public static final int switchStyle = 16843842; // 0x1010442
field public static final int switchTextAppearance = 16843630; // 0x101036e
field public static final int switchTextOff = 16843628; // 0x101036c
field public static final int switchTextOn = 16843627; // 0x101036b
@@ -1135,7 +1131,7 @@ package android {
field public static final int targetId = 16843740; // 0x10103dc
field public static final int targetPackage = 16842785; // 0x1010021
field public static final int targetSdkVersion = 16843376; // 0x1010270
- field public static final int targetViewName = 16843856; // 0x1010450
+ field public static final int targetViewName = 16843855; // 0x101044f
field public static final int taskAffinity = 16842770; // 0x1010012
field public static final int taskCloseEnterAnimation = 16842942; // 0x10100be
field public static final int taskCloseExitAnimation = 16842943; // 0x10100bf
@@ -1225,7 +1221,7 @@ package android {
field public static final int titleTextStyle = 16843512; // 0x10102f8
field public static final int toAlpha = 16843211; // 0x10101cb
field public static final int toDegrees = 16843188; // 0x10101b4
- field public static final int toId = 16843852; // 0x101044c
+ field public static final int toId = 16843851; // 0x101044b
field public static final int toScene = 16843742; // 0x10103de
field public static final int toXDelta = 16843207; // 0x10101c7
field public static final int toXScale = 16843203; // 0x10101c3
@@ -1244,8 +1240,6 @@ package android {
field public static final int transition = 16843743; // 0x10103df
field public static final int transitionGroup = 16843803; // 0x101041b
field public static final int transitionOrdering = 16843744; // 0x10103e0
- field public static final int translateX = 16843869; // 0x101045d
- field public static final int translateY = 16843870; // 0x101045e
field public static final int translationX = 16843554; // 0x1010322
field public static final int translationY = 16843555; // 0x1010323
field public static final int translationZ = 16843796; // 0x1010414
@@ -1307,8 +1301,8 @@ package android {
field public static final int windowActionBar = 16843469; // 0x10102cd
field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
- field public static final int windowAllowEnterTransitionOverlap = 16843840; // 0x1010440
- field public static final int windowAllowExitTransitionOverlap = 16843839; // 0x101043f
+ field public static final int windowAllowEnterTransitionOverlap = 16843839; // 0x101043f
+ field public static final int windowAllowExitTransitionOverlap = 16843838; // 0x101043e
field public static final int windowAnimationStyle = 16842926; // 0x10100ae
field public static final int windowBackground = 16842836; // 0x1010054
field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
@@ -1316,12 +1310,12 @@ package android {
field public static final int windowContentTransitionManager = 16843795; // 0x1010413
field public static final int windowContentTransitions = 16843794; // 0x1010412
field public static final int windowDisablePreview = 16843298; // 0x1010222
- field public static final int windowDrawsSystemBarBackgrounds = 16843859; // 0x1010453
+ field public static final int windowDrawsSystemBarBackgrounds = 16843858; // 0x1010452
field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
field public static final int windowEnterAnimation = 16842932; // 0x10100b4
- field public static final int windowEnterTransition = 16843835; // 0x101043b
+ field public static final int windowEnterTransition = 16843834; // 0x101043a
field public static final int windowExitAnimation = 16842933; // 0x10100b5
- field public static final int windowExitTransition = 16843836; // 0x101043c
+ field public static final int windowExitTransition = 16843835; // 0x101043b
field public static final int windowFrame = 16842837; // 0x1010055
field public static final int windowFullscreen = 16843277; // 0x101020d
field public static final int windowHideAnimation = 16842935; // 0x10100b7
@@ -1332,8 +1326,8 @@ package android {
field public static final int windowNoDisplay = 16843294; // 0x101021e
field public static final int windowNoTitle = 16842838; // 0x1010056
field public static final int windowOverscan = 16843727; // 0x10103cf
- field public static final int windowSharedElementEnterTransition = 16843837; // 0x101043d
- field public static final int windowSharedElementExitTransition = 16843838; // 0x101043e
+ field public static final int windowSharedElementEnterTransition = 16843836; // 0x101043c
+ field public static final int windowSharedElementExitTransition = 16843837; // 0x101043d
field public static final int windowShowAnimation = 16842934; // 0x10100b6
field public static final int windowShowWallpaper = 16843410; // 0x1010292
field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -1868,28 +1862,28 @@ package android {
field public static final int TextAppearance_Medium = 16973892; // 0x1030044
field public static final int TextAppearance_Medium_Inverse = 16973893; // 0x1030045
field public static final int TextAppearance_Quantum = 16974348; // 0x103020c
- field public static final int TextAppearance_Quantum_Body1 = 16974545; // 0x10302d1
- field public static final int TextAppearance_Quantum_Body2 = 16974544; // 0x10302d0
- field public static final int TextAppearance_Quantum_Button = 16974548; // 0x10302d4
- field public static final int TextAppearance_Quantum_Caption = 16974546; // 0x10302d2
+ field public static final int TextAppearance_Quantum_Body1 = 16974546; // 0x10302d2
+ field public static final int TextAppearance_Quantum_Body2 = 16974545; // 0x10302d1
+ field public static final int TextAppearance_Quantum_Button = 16974549; // 0x10302d5
+ field public static final int TextAppearance_Quantum_Caption = 16974547; // 0x10302d3
field public static final int TextAppearance_Quantum_DialogWindowTitle = 16974349; // 0x103020d
- field public static final int TextAppearance_Quantum_Display1 = 16974540; // 0x10302cc
- field public static final int TextAppearance_Quantum_Display2 = 16974539; // 0x10302cb
- field public static final int TextAppearance_Quantum_Display3 = 16974538; // 0x10302ca
- field public static final int TextAppearance_Quantum_Display4 = 16974537; // 0x10302c9
- field public static final int TextAppearance_Quantum_Headline = 16974541; // 0x10302cd
+ field public static final int TextAppearance_Quantum_Display1 = 16974541; // 0x10302cd
+ field public static final int TextAppearance_Quantum_Display2 = 16974540; // 0x10302cc
+ field public static final int TextAppearance_Quantum_Display3 = 16974539; // 0x10302cb
+ field public static final int TextAppearance_Quantum_Display4 = 16974538; // 0x10302ca
+ field public static final int TextAppearance_Quantum_Headline = 16974542; // 0x10302ce
field public static final int TextAppearance_Quantum_Inverse = 16974350; // 0x103020e
field public static final int TextAppearance_Quantum_Large = 16974351; // 0x103020f
field public static final int TextAppearance_Quantum_Large_Inverse = 16974352; // 0x1030210
field public static final int TextAppearance_Quantum_Medium = 16974353; // 0x1030211
field public static final int TextAppearance_Quantum_Medium_Inverse = 16974354; // 0x1030212
- field public static final int TextAppearance_Quantum_Menu = 16974547; // 0x10302d3
+ field public static final int TextAppearance_Quantum_Menu = 16974548; // 0x10302d4
field public static final int TextAppearance_Quantum_SearchResult_Subtitle = 16974355; // 0x1030213
field public static final int TextAppearance_Quantum_SearchResult_Title = 16974356; // 0x1030214
field public static final int TextAppearance_Quantum_Small = 16974357; // 0x1030215
field public static final int TextAppearance_Quantum_Small_Inverse = 16974358; // 0x1030216
- field public static final int TextAppearance_Quantum_Subhead = 16974543; // 0x10302cf
- field public static final int TextAppearance_Quantum_Title = 16974542; // 0x10302ce
+ field public static final int TextAppearance_Quantum_Subhead = 16974544; // 0x10302d0
+ field public static final int TextAppearance_Quantum_Title = 16974543; // 0x10302cf
field public static final int TextAppearance_Quantum_Widget = 16974360; // 0x1030218
field public static final int TextAppearance_Quantum_Widget_ActionBar_Menu = 16974361; // 0x1030219
field public static final int TextAppearance_Quantum_Widget_ActionBar_Subtitle = 16974362; // 0x103021a
@@ -1938,9 +1932,10 @@ package android {
field public static final int Theme = 16973829; // 0x1030005
field public static final int ThemeOverlay = 16974412; // 0x103024c
field public static final int ThemeOverlay_Quantum = 16974413; // 0x103024d
- field public static final int ThemeOverlay_Quantum_ActionBarWidget = 16974416; // 0x1030250
- field public static final int ThemeOverlay_Quantum_Dark = 16974415; // 0x103024f
- field public static final int ThemeOverlay_Quantum_Light = 16974414; // 0x103024e
+ field public static final int ThemeOverlay_Quantum_ActionBar = 16974414; // 0x103024e
+ field public static final int ThemeOverlay_Quantum_Dark = 16974416; // 0x1030250
+ field public static final int ThemeOverlay_Quantum_Dark_ActionBar = 16974417; // 0x1030251
+ field public static final int ThemeOverlay_Quantum_Light = 16974415; // 0x103024f
field public static final int Theme_Black = 16973832; // 0x1030008
field public static final int Theme_Black_NoTitleBar = 16973833; // 0x1030009
field public static final int Theme_Black_NoTitleBar_Fullscreen = 16973834; // 0x103000a
@@ -2330,126 +2325,126 @@ package android {
field public static final int Widget_ProgressBar_Large_Inverse = 16973916; // 0x103005c
field public static final int Widget_ProgressBar_Small = 16973854; // 0x103001e
field public static final int Widget_ProgressBar_Small_Inverse = 16973917; // 0x103005d
- field public static final int Widget_Quantum = 16974417; // 0x1030251
- field public static final int Widget_Quantum_ActionBar = 16974418; // 0x1030252
- field public static final int Widget_Quantum_ActionBar_Solid = 16974419; // 0x1030253
- field public static final int Widget_Quantum_ActionBar_TabBar = 16974420; // 0x1030254
- field public static final int Widget_Quantum_ActionBar_TabText = 16974421; // 0x1030255
- field public static final int Widget_Quantum_ActionBar_TabView = 16974422; // 0x1030256
- field public static final int Widget_Quantum_ActionButton = 16974423; // 0x1030257
- field public static final int Widget_Quantum_ActionButton_CloseMode = 16974424; // 0x1030258
- field public static final int Widget_Quantum_ActionButton_Overflow = 16974425; // 0x1030259
- field public static final int Widget_Quantum_ActionMode = 16974426; // 0x103025a
- field public static final int Widget_Quantum_AutoCompleteTextView = 16974427; // 0x103025b
- field public static final int Widget_Quantum_Button = 16974428; // 0x103025c
- field public static final int Widget_Quantum_ButtonBar = 16974434; // 0x1030262
- field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974435; // 0x1030263
- field public static final int Widget_Quantum_Button_Borderless = 16974429; // 0x103025d
- field public static final int Widget_Quantum_Button_Borderless_Small = 16974430; // 0x103025e
- field public static final int Widget_Quantum_Button_Inset = 16974431; // 0x103025f
- field public static final int Widget_Quantum_Button_Small = 16974432; // 0x1030260
- field public static final int Widget_Quantum_Button_Toggle = 16974433; // 0x1030261
- field public static final int Widget_Quantum_CalendarView = 16974436; // 0x1030264
- field public static final int Widget_Quantum_CheckedTextView = 16974437; // 0x1030265
- field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974438; // 0x1030266
- field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974439; // 0x1030267
- field public static final int Widget_Quantum_CompoundButton_Star = 16974440; // 0x1030268
- field public static final int Widget_Quantum_DatePicker = 16974441; // 0x1030269
- field public static final int Widget_Quantum_DropDownItem = 16974442; // 0x103026a
- field public static final int Widget_Quantum_DropDownItem_Spinner = 16974443; // 0x103026b
- field public static final int Widget_Quantum_EditText = 16974444; // 0x103026c
- field public static final int Widget_Quantum_ExpandableListView = 16974445; // 0x103026d
- field public static final int Widget_Quantum_FastScroll = 16974446; // 0x103026e
- field public static final int Widget_Quantum_GridView = 16974447; // 0x103026f
- field public static final int Widget_Quantum_HorizontalScrollView = 16974448; // 0x1030270
- field public static final int Widget_Quantum_ImageButton = 16974449; // 0x1030271
- field public static final int Widget_Quantum_Light = 16974476; // 0x103028c
- field public static final int Widget_Quantum_Light_ActionBar = 16974477; // 0x103028d
- field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974478; // 0x103028e
- field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974479; // 0x103028f
- field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974480; // 0x1030290
- field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974481; // 0x1030291
- field public static final int Widget_Quantum_Light_ActionButton = 16974482; // 0x1030292
- field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974483; // 0x1030293
- field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974484; // 0x1030294
- field public static final int Widget_Quantum_Light_ActionMode = 16974485; // 0x1030295
- field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974486; // 0x1030296
- field public static final int Widget_Quantum_Light_Button = 16974487; // 0x1030297
- field public static final int Widget_Quantum_Light_ButtonBar = 16974493; // 0x103029d
- field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974494; // 0x103029e
- field public static final int Widget_Quantum_Light_Button_Borderless = 16974488; // 0x1030298
- field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974489; // 0x1030299
- field public static final int Widget_Quantum_Light_Button_Inset = 16974490; // 0x103029a
- field public static final int Widget_Quantum_Light_Button_Small = 16974491; // 0x103029b
- field public static final int Widget_Quantum_Light_Button_Toggle = 16974492; // 0x103029c
- field public static final int Widget_Quantum_Light_CalendarView = 16974495; // 0x103029f
- field public static final int Widget_Quantum_Light_CheckedTextView = 16974496; // 0x10302a0
- field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974497; // 0x10302a1
- field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974498; // 0x10302a2
- field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974499; // 0x10302a3
- field public static final int Widget_Quantum_Light_DropDownItem = 16974500; // 0x10302a4
- field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974501; // 0x10302a5
- field public static final int Widget_Quantum_Light_EditText = 16974502; // 0x10302a6
- field public static final int Widget_Quantum_Light_ExpandableListView = 16974503; // 0x10302a7
- field public static final int Widget_Quantum_Light_FastScroll = 16974504; // 0x10302a8
- field public static final int Widget_Quantum_Light_GridView = 16974505; // 0x10302a9
- field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974506; // 0x10302aa
- field public static final int Widget_Quantum_Light_ImageButton = 16974507; // 0x10302ab
- field public static final int Widget_Quantum_Light_ListPopupWindow = 16974508; // 0x10302ac
- field public static final int Widget_Quantum_Light_ListView = 16974509; // 0x10302ad
- field public static final int Widget_Quantum_Light_ListView_DropDown = 16974510; // 0x10302ae
- field public static final int Widget_Quantum_Light_MediaRouteButton = 16974511; // 0x10302af
- field public static final int Widget_Quantum_Light_PopupMenu = 16974512; // 0x10302b0
- field public static final int Widget_Quantum_Light_PopupMenu_Overflow = 16974513; // 0x10302b1
- field public static final int Widget_Quantum_Light_PopupWindow = 16974514; // 0x10302b2
- field public static final int Widget_Quantum_Light_ProgressBar = 16974515; // 0x10302b3
- field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974516; // 0x10302b4
- field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974517; // 0x10302b5
- field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974518; // 0x10302b6
- field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974519; // 0x10302b7
- field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974520; // 0x10302b8
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974521; // 0x10302b9
- field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974522; // 0x10302ba
- field public static final int Widget_Quantum_Light_RatingBar = 16974523; // 0x10302bb
- field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974524; // 0x10302bc
- field public static final int Widget_Quantum_Light_RatingBar_Small = 16974525; // 0x10302bd
- field public static final int Widget_Quantum_Light_ScrollView = 16974526; // 0x10302be
- field public static final int Widget_Quantum_Light_SeekBar = 16974527; // 0x10302bf
- field public static final int Widget_Quantum_Light_SegmentedButton = 16974528; // 0x10302c0
- field public static final int Widget_Quantum_Light_Spinner = 16974530; // 0x10302c2
- field public static final int Widget_Quantum_Light_StackView = 16974529; // 0x10302c1
- field public static final int Widget_Quantum_Light_Tab = 16974531; // 0x10302c3
- field public static final int Widget_Quantum_Light_TabWidget = 16974532; // 0x10302c4
- field public static final int Widget_Quantum_Light_TextView = 16974533; // 0x10302c5
- field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974534; // 0x10302c6
- field public static final int Widget_Quantum_Light_WebTextView = 16974535; // 0x10302c7
- field public static final int Widget_Quantum_Light_WebView = 16974536; // 0x10302c8
- field public static final int Widget_Quantum_ListPopupWindow = 16974450; // 0x1030272
- field public static final int Widget_Quantum_ListView = 16974451; // 0x1030273
- field public static final int Widget_Quantum_ListView_DropDown = 16974452; // 0x1030274
- field public static final int Widget_Quantum_MediaRouteButton = 16974453; // 0x1030275
- field public static final int Widget_Quantum_PopupMenu = 16974454; // 0x1030276
- field public static final int Widget_Quantum_PopupMenu_Overflow = 16974455; // 0x1030277
- field public static final int Widget_Quantum_PopupWindow = 16974456; // 0x1030278
- field public static final int Widget_Quantum_ProgressBar = 16974457; // 0x1030279
- field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974458; // 0x103027a
- field public static final int Widget_Quantum_ProgressBar_Large = 16974459; // 0x103027b
- field public static final int Widget_Quantum_ProgressBar_Small = 16974460; // 0x103027c
- field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974461; // 0x103027d
- field public static final int Widget_Quantum_RatingBar = 16974462; // 0x103027e
- field public static final int Widget_Quantum_RatingBar_Indicator = 16974463; // 0x103027f
- field public static final int Widget_Quantum_RatingBar_Small = 16974464; // 0x1030280
- field public static final int Widget_Quantum_ScrollView = 16974465; // 0x1030281
- field public static final int Widget_Quantum_SeekBar = 16974466; // 0x1030282
- field public static final int Widget_Quantum_SegmentedButton = 16974467; // 0x1030283
- field public static final int Widget_Quantum_Spinner = 16974469; // 0x1030285
- field public static final int Widget_Quantum_StackView = 16974468; // 0x1030284
- field public static final int Widget_Quantum_Tab = 16974470; // 0x1030286
- field public static final int Widget_Quantum_TabWidget = 16974471; // 0x1030287
- field public static final int Widget_Quantum_TextView = 16974472; // 0x1030288
- field public static final int Widget_Quantum_TextView_SpinnerItem = 16974473; // 0x1030289
- field public static final int Widget_Quantum_WebTextView = 16974474; // 0x103028a
- field public static final int Widget_Quantum_WebView = 16974475; // 0x103028b
+ field public static final int Widget_Quantum = 16974418; // 0x1030252
+ field public static final int Widget_Quantum_ActionBar = 16974419; // 0x1030253
+ field public static final int Widget_Quantum_ActionBar_Solid = 16974420; // 0x1030254
+ field public static final int Widget_Quantum_ActionBar_TabBar = 16974421; // 0x1030255
+ field public static final int Widget_Quantum_ActionBar_TabText = 16974422; // 0x1030256
+ field public static final int Widget_Quantum_ActionBar_TabView = 16974423; // 0x1030257
+ field public static final int Widget_Quantum_ActionButton = 16974424; // 0x1030258
+ field public static final int Widget_Quantum_ActionButton_CloseMode = 16974425; // 0x1030259
+ field public static final int Widget_Quantum_ActionButton_Overflow = 16974426; // 0x103025a
+ field public static final int Widget_Quantum_ActionMode = 16974427; // 0x103025b
+ field public static final int Widget_Quantum_AutoCompleteTextView = 16974428; // 0x103025c
+ field public static final int Widget_Quantum_Button = 16974429; // 0x103025d
+ field public static final int Widget_Quantum_ButtonBar = 16974435; // 0x1030263
+ field public static final int Widget_Quantum_ButtonBar_AlertDialog = 16974436; // 0x1030264
+ field public static final int Widget_Quantum_Button_Borderless = 16974430; // 0x103025e
+ field public static final int Widget_Quantum_Button_Borderless_Small = 16974431; // 0x103025f
+ field public static final int Widget_Quantum_Button_Inset = 16974432; // 0x1030260
+ field public static final int Widget_Quantum_Button_Small = 16974433; // 0x1030261
+ field public static final int Widget_Quantum_Button_Toggle = 16974434; // 0x1030262
+ field public static final int Widget_Quantum_CalendarView = 16974437; // 0x1030265
+ field public static final int Widget_Quantum_CheckedTextView = 16974438; // 0x1030266
+ field public static final int Widget_Quantum_CompoundButton_CheckBox = 16974439; // 0x1030267
+ field public static final int Widget_Quantum_CompoundButton_RadioButton = 16974440; // 0x1030268
+ field public static final int Widget_Quantum_CompoundButton_Star = 16974441; // 0x1030269
+ field public static final int Widget_Quantum_DatePicker = 16974442; // 0x103026a
+ field public static final int Widget_Quantum_DropDownItem = 16974443; // 0x103026b
+ field public static final int Widget_Quantum_DropDownItem_Spinner = 16974444; // 0x103026c
+ field public static final int Widget_Quantum_EditText = 16974445; // 0x103026d
+ field public static final int Widget_Quantum_ExpandableListView = 16974446; // 0x103026e
+ field public static final int Widget_Quantum_FastScroll = 16974447; // 0x103026f
+ field public static final int Widget_Quantum_GridView = 16974448; // 0x1030270
+ field public static final int Widget_Quantum_HorizontalScrollView = 16974449; // 0x1030271
+ field public static final int Widget_Quantum_ImageButton = 16974450; // 0x1030272
+ field public static final int Widget_Quantum_Light = 16974477; // 0x103028d
+ field public static final int Widget_Quantum_Light_ActionBar = 16974478; // 0x103028e
+ field public static final int Widget_Quantum_Light_ActionBar_Solid = 16974479; // 0x103028f
+ field public static final int Widget_Quantum_Light_ActionBar_TabBar = 16974480; // 0x1030290
+ field public static final int Widget_Quantum_Light_ActionBar_TabText = 16974481; // 0x1030291
+ field public static final int Widget_Quantum_Light_ActionBar_TabView = 16974482; // 0x1030292
+ field public static final int Widget_Quantum_Light_ActionButton = 16974483; // 0x1030293
+ field public static final int Widget_Quantum_Light_ActionButton_CloseMode = 16974484; // 0x1030294
+ field public static final int Widget_Quantum_Light_ActionButton_Overflow = 16974485; // 0x1030295
+ field public static final int Widget_Quantum_Light_ActionMode = 16974486; // 0x1030296
+ field public static final int Widget_Quantum_Light_AutoCompleteTextView = 16974487; // 0x1030297
+ field public static final int Widget_Quantum_Light_Button = 16974488; // 0x1030298
+ field public static final int Widget_Quantum_Light_ButtonBar = 16974494; // 0x103029e
+ field public static final int Widget_Quantum_Light_ButtonBar_AlertDialog = 16974495; // 0x103029f
+ field public static final int Widget_Quantum_Light_Button_Borderless = 16974489; // 0x1030299
+ field public static final int Widget_Quantum_Light_Button_Borderless_Small = 16974490; // 0x103029a
+ field public static final int Widget_Quantum_Light_Button_Inset = 16974491; // 0x103029b
+ field public static final int Widget_Quantum_Light_Button_Small = 16974492; // 0x103029c
+ field public static final int Widget_Quantum_Light_Button_Toggle = 16974493; // 0x103029d
+ field public static final int Widget_Quantum_Light_CalendarView = 16974496; // 0x10302a0
+ field public static final int Widget_Quantum_Light_CheckedTextView = 16974497; // 0x10302a1
+ field public static final int Widget_Quantum_Light_CompoundButton_CheckBox = 16974498; // 0x10302a2
+ field public static final int Widget_Quantum_Light_CompoundButton_RadioButton = 16974499; // 0x10302a3
+ field public static final int Widget_Quantum_Light_CompoundButton_Star = 16974500; // 0x10302a4
+ field public static final int Widget_Quantum_Light_DropDownItem = 16974501; // 0x10302a5
+ field public static final int Widget_Quantum_Light_DropDownItem_Spinner = 16974502; // 0x10302a6
+ field public static final int Widget_Quantum_Light_EditText = 16974503; // 0x10302a7
+ field public static final int Widget_Quantum_Light_ExpandableListView = 16974504; // 0x10302a8
+ field public static final int Widget_Quantum_Light_FastScroll = 16974505; // 0x10302a9
+ field public static final int Widget_Quantum_Light_GridView = 16974506; // 0x10302aa
+ field public static final int Widget_Quantum_Light_HorizontalScrollView = 16974507; // 0x10302ab
+ field public static final int Widget_Quantum_Light_ImageButton = 16974508; // 0x10302ac
+ field public static final int Widget_Quantum_Light_ListPopupWindow = 16974509; // 0x10302ad
+ field public static final int Widget_Quantum_Light_ListView = 16974510; // 0x10302ae
+ field public static final int Widget_Quantum_Light_ListView_DropDown = 16974511; // 0x10302af
+ field public static final int Widget_Quantum_Light_MediaRouteButton = 16974512; // 0x10302b0
+ field public static final int Widget_Quantum_Light_PopupMenu = 16974513; // 0x10302b1
+ field public static final int Widget_Quantum_Light_PopupMenu_Overflow = 16974514; // 0x10302b2
+ field public static final int Widget_Quantum_Light_PopupWindow = 16974515; // 0x10302b3
+ field public static final int Widget_Quantum_Light_ProgressBar = 16974516; // 0x10302b4
+ field public static final int Widget_Quantum_Light_ProgressBar_Horizontal = 16974517; // 0x10302b5
+ field public static final int Widget_Quantum_Light_ProgressBar_Inverse = 16974518; // 0x10302b6
+ field public static final int Widget_Quantum_Light_ProgressBar_Large = 16974519; // 0x10302b7
+ field public static final int Widget_Quantum_Light_ProgressBar_Large_Inverse = 16974520; // 0x10302b8
+ field public static final int Widget_Quantum_Light_ProgressBar_Small = 16974521; // 0x10302b9
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Inverse = 16974522; // 0x10302ba
+ field public static final int Widget_Quantum_Light_ProgressBar_Small_Title = 16974523; // 0x10302bb
+ field public static final int Widget_Quantum_Light_RatingBar = 16974524; // 0x10302bc
+ field public static final int Widget_Quantum_Light_RatingBar_Indicator = 16974525; // 0x10302bd
+ field public static final int Widget_Quantum_Light_RatingBar_Small = 16974526; // 0x10302be
+ field public static final int Widget_Quantum_Light_ScrollView = 16974527; // 0x10302bf
+ field public static final int Widget_Quantum_Light_SeekBar = 16974528; // 0x10302c0
+ field public static final int Widget_Quantum_Light_SegmentedButton = 16974529; // 0x10302c1
+ field public static final int Widget_Quantum_Light_Spinner = 16974531; // 0x10302c3
+ field public static final int Widget_Quantum_Light_StackView = 16974530; // 0x10302c2
+ field public static final int Widget_Quantum_Light_Tab = 16974532; // 0x10302c4
+ field public static final int Widget_Quantum_Light_TabWidget = 16974533; // 0x10302c5
+ field public static final int Widget_Quantum_Light_TextView = 16974534; // 0x10302c6
+ field public static final int Widget_Quantum_Light_TextView_SpinnerItem = 16974535; // 0x10302c7
+ field public static final int Widget_Quantum_Light_WebTextView = 16974536; // 0x10302c8
+ field public static final int Widget_Quantum_Light_WebView = 16974537; // 0x10302c9
+ field public static final int Widget_Quantum_ListPopupWindow = 16974451; // 0x1030273
+ field public static final int Widget_Quantum_ListView = 16974452; // 0x1030274
+ field public static final int Widget_Quantum_ListView_DropDown = 16974453; // 0x1030275
+ field public static final int Widget_Quantum_MediaRouteButton = 16974454; // 0x1030276
+ field public static final int Widget_Quantum_PopupMenu = 16974455; // 0x1030277
+ field public static final int Widget_Quantum_PopupMenu_Overflow = 16974456; // 0x1030278
+ field public static final int Widget_Quantum_PopupWindow = 16974457; // 0x1030279
+ field public static final int Widget_Quantum_ProgressBar = 16974458; // 0x103027a
+ field public static final int Widget_Quantum_ProgressBar_Horizontal = 16974459; // 0x103027b
+ field public static final int Widget_Quantum_ProgressBar_Large = 16974460; // 0x103027c
+ field public static final int Widget_Quantum_ProgressBar_Small = 16974461; // 0x103027d
+ field public static final int Widget_Quantum_ProgressBar_Small_Title = 16974462; // 0x103027e
+ field public static final int Widget_Quantum_RatingBar = 16974463; // 0x103027f
+ field public static final int Widget_Quantum_RatingBar_Indicator = 16974464; // 0x1030280
+ field public static final int Widget_Quantum_RatingBar_Small = 16974465; // 0x1030281
+ field public static final int Widget_Quantum_ScrollView = 16974466; // 0x1030282
+ field public static final int Widget_Quantum_SeekBar = 16974467; // 0x1030283
+ field public static final int Widget_Quantum_SegmentedButton = 16974468; // 0x1030284
+ field public static final int Widget_Quantum_Spinner = 16974470; // 0x1030286
+ field public static final int Widget_Quantum_StackView = 16974469; // 0x1030285
+ field public static final int Widget_Quantum_Tab = 16974471; // 0x1030287
+ field public static final int Widget_Quantum_TabWidget = 16974472; // 0x1030288
+ field public static final int Widget_Quantum_TextView = 16974473; // 0x1030289
+ field public static final int Widget_Quantum_TextView_SpinnerItem = 16974474; // 0x103028a
+ field public static final int Widget_Quantum_WebTextView = 16974475; // 0x103028b
+ field public static final int Widget_Quantum_WebView = 16974476; // 0x103028c
field public static final int Widget_RatingBar = 16973857; // 0x1030021
field public static final int Widget_ScrollView = 16973869; // 0x103002d
field public static final int Widget_SeekBar = 16973856; // 0x1030020
@@ -5167,10 +5162,10 @@ package android.app.admin {
}
public class DevicePolicyManager {
- method public void addCrossProfileIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
+ method public void addForwardingIntentFilter(android.content.ComponentName, android.content.IntentFilter, int);
method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
method public void addUserRestriction(android.content.ComponentName, java.lang.String);
- method public void clearCrossProfileIntentFilters(android.content.ComponentName);
+ method public void clearForwardingIntentFilters(android.content.ComponentName);
method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
method public android.os.UserHandle createUser(android.content.ComponentName, java.lang.String);
@@ -5230,7 +5225,6 @@ package android.app.admin {
method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
method public void setPasswordQuality(android.content.ComponentName, int);
method public void setProfileEnabled(android.content.ComponentName);
- method public void setRestrictionsProvider(android.content.ComponentName, android.content.ComponentName);
method public void setSecureSetting(android.content.ComponentName, java.lang.String, java.lang.String);
method public int setStorageEncryption(android.content.ComponentName, boolean);
method public void wipeData(int);
@@ -5246,8 +5240,8 @@ package android.app.admin {
field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "defaultManagedProfileName";
field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "deviceAdminPackageName";
- field public static int FLAG_MANAGED_CAN_ACCESS_PARENT;
- field public static int FLAG_PARENT_CAN_ACCESS_MANAGED;
+ field public static int FLAG_TO_MANAGED_PROFILE;
+ field public static int FLAG_TO_PRIMARY_USER;
field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2
@@ -6758,7 +6752,6 @@ package android.content {
method public final android.os.Bundle call(android.net.Uri, java.lang.String, java.lang.String, android.os.Bundle);
method public deprecated void cancelSync(android.net.Uri);
method public static void cancelSync(android.accounts.Account, java.lang.String);
- method public static void cancelSync(android.content.ComponentName);
method public static void cancelSync(android.content.SyncRequest);
method public final android.net.Uri canonicalize(android.net.Uri);
method public final int delete(android.net.Uri, java.lang.String, java.lang.String[]);
@@ -6768,18 +6761,14 @@ package android.content {
method public static boolean getMasterSyncAutomatically();
method public java.util.List<android.content.UriPermission> getOutgoingPersistedUriPermissions();
method public static java.util.List<android.content.PeriodicSync> getPeriodicSyncs(android.accounts.Account, java.lang.String);
- method public static java.util.List<android.content.PeriodicSync> getPeriodicSyncs(android.content.ComponentName);
method public java.util.List<android.content.UriPermission> getPersistedUriPermissions();
method public java.lang.String[] getStreamTypes(android.net.Uri, java.lang.String);
method public static android.content.SyncAdapterType[] getSyncAdapterTypes();
method public static boolean getSyncAutomatically(android.accounts.Account, java.lang.String);
method public final java.lang.String getType(android.net.Uri);
method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
- method public static boolean isServiceActive(android.content.ComponentName);
method public static boolean isSyncActive(android.accounts.Account, java.lang.String);
- method public static boolean isSyncActive(android.content.ComponentName);
method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
- method public static boolean isSyncPending(android.content.ComponentName);
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -6801,7 +6790,6 @@ package android.content {
method public static void requestSync(android.content.SyncRequest);
method public static void setIsSyncable(android.accounts.Account, java.lang.String, int);
method public static void setMasterSyncAutomatically(boolean);
- method public static void setServiceActive(android.content.ComponentName, boolean);
method public static void setSyncAutomatically(android.accounts.Account, java.lang.String, boolean);
method public deprecated void startSync(android.net.Uri, android.os.Bundle);
method public void takePersistableUriPermission(android.net.Uri, int);
@@ -7026,7 +7014,6 @@ package android.content {
field public static final java.lang.String NSD_SERVICE = "servicediscovery";
field public static final java.lang.String POWER_SERVICE = "power";
field public static final java.lang.String PRINT_SERVICE = "print";
- field public static final java.lang.String RESTRICTIONS_SERVICE = "restrictions";
field public static final java.lang.String SEARCH_SERVICE = "search";
field public static final java.lang.String SENSOR_SERVICE = "sensor";
field public static final java.lang.String STORAGE_SERVICE = "storage";
@@ -7770,9 +7757,7 @@ package android.content {
field public final android.accounts.Account account;
field public final java.lang.String authority;
field public final android.os.Bundle extras;
- field public final boolean isService;
field public final long period;
- field public final android.content.ComponentName service;
}
public class ReceiverCallNotAllowedException extends android.util.AndroidRuntimeException {
@@ -7783,14 +7768,12 @@ package android.content {
ctor public RestrictionEntry(java.lang.String, java.lang.String);
ctor public RestrictionEntry(java.lang.String, boolean);
ctor public RestrictionEntry(java.lang.String, java.lang.String[]);
- ctor public RestrictionEntry(java.lang.String, int);
ctor public RestrictionEntry(android.os.Parcel);
method public int describeContents();
method public java.lang.String[] getAllSelectedStrings();
method public java.lang.String[] getChoiceEntries();
method public java.lang.String[] getChoiceValues();
method public java.lang.String getDescription();
- method public int getIntValue();
method public java.lang.String getKey();
method public boolean getSelectedState();
method public java.lang.String getSelectedString();
@@ -7802,7 +7785,6 @@ package android.content {
method public void setChoiceValues(java.lang.String[]);
method public void setChoiceValues(android.content.Context, int);
method public void setDescription(java.lang.String);
- method public void setIntValue(int);
method public void setSelectedState(boolean);
method public void setSelectedString(java.lang.String);
method public void setTitle(java.lang.String);
@@ -7811,36 +7793,10 @@ package android.content {
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int TYPE_BOOLEAN = 1; // 0x1
field public static final int TYPE_CHOICE = 2; // 0x2
- field public static final int TYPE_INTEGER = 5; // 0x5
field public static final int TYPE_MULTI_SELECT = 4; // 0x4
field public static final int TYPE_NULL = 0; // 0x0
}
- public class RestrictionsManager {
- method public android.os.Bundle getApplicationRestrictions();
- method public java.util.List<android.content.RestrictionEntry> getManifestRestrictions(java.lang.String);
- method public boolean hasRestrictionsProvider();
- method public void notifyPermissionResponse(java.lang.String, android.os.Bundle);
- method public void requestPermission(java.lang.String, android.os.Bundle);
- field public static final java.lang.String ACTION_PERMISSION_RESPONSE_RECEIVED = "android.intent.action.PERMISSION_RESPONSE_RECEIVED";
- field public static final java.lang.String ACTION_REQUEST_PERMISSION = "android.intent.action.REQUEST_PERMISSION";
- field public static final java.lang.String EXTRA_PACKAGE_NAME = "package_name";
- field public static final java.lang.String EXTRA_REQUEST_BUNDLE = "request_bundle";
- field public static final java.lang.String EXTRA_RESPONSE_BUNDLE = "response_bundle";
- field public static final java.lang.String EXTRA_TEMPLATE_ID = "template_id";
- field public static final java.lang.String REQUEST_KEY_APPROVE_LABEL = "android.req_template.accept";
- field public static final java.lang.String REQUEST_KEY_DATA = "android.req_template.data";
- field public static final java.lang.String REQUEST_KEY_DENY_LABEL = "android.req_template.reject";
- field public static final java.lang.String REQUEST_KEY_DEVICE_NAME = "android.req_template.device";
- field public static final java.lang.String REQUEST_KEY_ICON = "android.req_template.icon";
- field public static final java.lang.String REQUEST_KEY_ID = "android.req_template.req_id";
- field public static final java.lang.String REQUEST_KEY_MESSAGE = "android.req_template.mesg";
- field public static final java.lang.String REQUEST_KEY_REQUESTOR_NAME = "android.req_template.requestor";
- field public static final java.lang.String REQUEST_KEY_TITLE = "android.req_template.title";
- field public static final java.lang.String REQUEST_TEMPLATE_QUESTION = "android.req_template.type.simple";
- field public static final java.lang.String RESPONSE_KEY_BOOLEAN = "android.req_template.response";
- }
-
public class SearchRecentSuggestionsProvider extends android.content.ContentProvider {
ctor public SearchRecentSuggestionsProvider();
method public int delete(android.net.Uri, java.lang.String, java.lang.String[]);
@@ -7917,7 +7873,6 @@ package android.content {
method public void writeToParcel(android.os.Parcel, int);
field public final android.accounts.Account account;
field public final java.lang.String authority;
- field public final android.content.ComponentName service;
field public final long startTime;
}
@@ -7940,8 +7895,6 @@ package android.content {
method public android.content.SyncRequest.Builder setNoRetry(boolean);
method public android.content.SyncRequest.Builder setPriority(int);
method public android.content.SyncRequest.Builder setSyncAdapter(android.accounts.Account, java.lang.String);
- method public android.content.SyncRequest.Builder setSyncAdapter(android.content.ComponentName);
- method public android.content.SyncRequest.Builder setTransferSize(long, long);
method public android.content.SyncRequest.Builder syncOnce();
method public android.content.SyncRequest.Builder syncPeriodic(long, long);
}
@@ -7969,13 +7922,6 @@ package android.content {
field public boolean tooManyRetries;
}
- public abstract class SyncService extends android.app.Service {
- ctor public SyncService();
- method public android.os.IBinder onBind(android.content.Intent);
- method public abstract void onPerformSync(android.os.Bundle, android.content.SyncResult);
- method protected boolean parallelSyncsEnabled();
- }
-
public class SyncStats implements android.os.Parcelable {
ctor public SyncStats();
ctor public SyncStats(android.os.Parcel);
@@ -10205,8 +10151,8 @@ package android.graphics {
method public boolean clipRect(float, float, float, float, android.graphics.Region.Op);
method public boolean clipRect(float, float, float, float);
method public boolean clipRect(int, int, int, int);
- method public deprecated boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
- method public deprecated boolean clipRegion(android.graphics.Region);
+ method public boolean clipRegion(android.graphics.Region, android.graphics.Region.Op);
+ method public boolean clipRegion(android.graphics.Region);
method public void concat(android.graphics.Matrix);
method public void drawARGB(int, int, int, int);
method public void drawArc(android.graphics.RectF, float, float, boolean, android.graphics.Paint);
@@ -11271,14 +11217,11 @@ package android.graphics.drawable {
method public static android.graphics.drawable.Drawable createFromPath(java.lang.String);
method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String);
method public static android.graphics.drawable.Drawable createFromResourceStream(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options);
- method public static android.graphics.drawable.Drawable createFromResourceStreamThemed(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.content.res.Resources.Theme);
- method public static android.graphics.drawable.Drawable createFromResourceStreamThemed(android.content.res.Resources, android.util.TypedValue, java.io.InputStream, java.lang.String, android.graphics.BitmapFactory.Options, android.content.res.Resources.Theme);
method public static android.graphics.drawable.Drawable createFromStream(java.io.InputStream, java.lang.String);
- method public static android.graphics.drawable.Drawable createFromStreamThemed(java.io.InputStream, java.lang.String, android.content.res.Resources.Theme);
method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static android.graphics.drawable.Drawable createFromXml(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static android.graphics.drawable.Drawable createFromXmlInnerThemed(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
- method public static android.graphics.drawable.Drawable createFromXmlThemed(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
+ method public static android.graphics.drawable.Drawable createFromXmlInner(android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet, android.content.res.Resources.Theme) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
method public abstract void draw(android.graphics.Canvas);
method public int getAlpha();
method public final android.graphics.Rect getBounds();
@@ -11554,7 +11497,6 @@ package android.graphics.drawable {
method public android.graphics.Paint getPaint();
method public android.graphics.drawable.ShapeDrawable.ShaderFactory getShaderFactory();
method public android.graphics.drawable.shapes.Shape getShape();
- method public android.content.res.ColorStateList getTint();
method protected boolean inflateTag(java.lang.String, android.content.res.Resources, org.xmlpull.v1.XmlPullParser, android.util.AttributeSet);
method protected void onDraw(android.graphics.drawable.shapes.Shape, android.graphics.Canvas, android.graphics.Paint);
method public void setAlpha(int);
@@ -11565,7 +11507,6 @@ package android.graphics.drawable {
method public void setPadding(android.graphics.Rect);
method public void setShaderFactory(android.graphics.drawable.ShapeDrawable.ShaderFactory);
method public void setShape(android.graphics.drawable.shapes.Shape);
- method public void setTint(android.content.res.ColorStateList);
}
public static abstract class ShapeDrawable.ShaderFactory {
@@ -11587,16 +11528,6 @@ package android.graphics.drawable {
method public void startTransition(int);
}
- public class VectorDrawable extends android.graphics.drawable.Drawable {
- ctor public VectorDrawable();
- method public void draw(android.graphics.Canvas);
- method public int getOpacity();
- method public void setAlpha(int);
- method public void setColorFilter(android.graphics.ColorFilter);
- method public void setPadding(android.graphics.Rect);
- method public void setPadding(int, int, int, int);
- }
-
}
package android.graphics.drawable.shapes {
@@ -11967,19 +11898,16 @@ package android.hardware {
public final class Sensor {
method public int getFifoMaxEventCount();
method public int getFifoReservedEventCount();
- method public int getMaxDelay();
method public float getMaximumRange();
method public int getMinDelay();
method public java.lang.String getName();
method public float getPower();
+ method public java.lang.String getRequiredPermission();
method public float getResolution();
method public java.lang.String getStringType();
method public int getType();
method public java.lang.String getVendor();
method public int getVersion();
- method public boolean isWakeUpSensor();
- field public static final java.lang.String SENSOR_STRING_TYPE_NON_WAKE_UP_PROXIMITY_SENSOR = "android.sensor.non_wake_up_proximity_sensor";
- field public static final java.lang.String SENSOR_STRING_TYPE_WAKE_UP_TILT_DETECTOR = "android.sensor.wake_up_tilt_detector";
field public static final java.lang.String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer";
field public static final java.lang.String STRING_TYPE_AMBIENT_TEMPERATURE = "android.sensor.ambient_temperature";
field public static final java.lang.String STRING_TYPE_GAME_ROTATION_VECTOR = "android.sensor.game_rotation_vector";
@@ -12001,24 +11929,6 @@ package android.hardware {
field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_ACCELEROMETER = "android.sensor.wake_up_accelerometer";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_AMBIENT_TEMPERATURE = "android.sensor.wake_up_ambient_temperature";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_GAME_ROTATION_VECTOR = "android.sensor.wake_up_game_rotation_vector";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR = "android.sensor.wake_up_geomagnetic_rotation_vector";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_GRAVITY = "android.sensor.wake_up_gravity";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_GYROSCOPE = "android.sensor.wake_up_gyroscope";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED = "android.sensor.wake_up_gyroscope_uncalibrated";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_HEART_RATE = "android.sensor.wake_up_heart_rate";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_LIGHT = "android.sensor.wake_up_light";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_LINEAR_ACCELERATION = "android.sensor.wake_up_linear_acceleration";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_MAGNETIC_FIELD = "android.sensor.wake_up_magnetic_field";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.wake_up_magnetic_field_uncalibrated";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_ORIENTATION = "android.sensor.wake_up_orientation";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_PRESSURE = "android.sensor.wake_up_pressure";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_RELATIVE_HUMIDITY = "android.sensor.wake_up_relative_humidity";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_ROTATION_VECTOR = "android.sensor.wake_up_rotation_vector";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_STEP_COUNTER = "android.sensor.wake_up_step_counter";
- field public static final java.lang.String STRING_TYPE_WAKE_UP_STEP_DETECTOR = "android.sensor.wake_up_step_detector";
field public static final int TYPE_ACCELEROMETER = 1; // 0x1
field public static final int TYPE_ALL = -1; // 0xffffffff
field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
@@ -12032,7 +11942,6 @@ package android.hardware {
field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
field public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14; // 0xe
- field public static final int TYPE_NON_WAKE_UP_PROXIMITY_SENSOR = 22; // 0x16
field public static final deprecated int TYPE_ORIENTATION = 3; // 0x3
field public static final int TYPE_PRESSURE = 6; // 0x6
field public static final int TYPE_PROXIMITY = 8; // 0x8
@@ -12042,25 +11951,6 @@ package android.hardware {
field public static final int TYPE_STEP_COUNTER = 19; // 0x13
field public static final int TYPE_STEP_DETECTOR = 18; // 0x12
field public static final deprecated int TYPE_TEMPERATURE = 7; // 0x7
- field public static final int TYPE_WAKE_UP_ACCELEROMETER = 23; // 0x17
- field public static final int TYPE_WAKE_UP_AMBIENT_TEMPERATURE = 33; // 0x21
- field public static final int TYPE_WAKE_UP_GAME_ROTATION_VECTOR = 35; // 0x23
- field public static final int TYPE_WAKE_UP_GEOMAGNETIC_ROTATION_VECTOR = 39; // 0x27
- field public static final int TYPE_WAKE_UP_GRAVITY = 29; // 0x1d
- field public static final int TYPE_WAKE_UP_GYROSCOPE = 26; // 0x1a
- field public static final int TYPE_WAKE_UP_GYROSCOPE_UNCALIBRATED = 36; // 0x24
- field public static final int TYPE_WAKE_UP_HEART_RATE = 40; // 0x28
- field public static final int TYPE_WAKE_UP_LIGHT = 27; // 0x1b
- field public static final int TYPE_WAKE_UP_LINEAR_ACCELERATION = 30; // 0x1e
- field public static final int TYPE_WAKE_UP_MAGNETIC_FIELD = 24; // 0x18
- field public static final int TYPE_WAKE_UP_MAGNETIC_FIELD_UNCALIBRATED = 34; // 0x22
- field public static final int TYPE_WAKE_UP_ORIENTATION = 25; // 0x19
- field public static final int TYPE_WAKE_UP_PRESSURE = 28; // 0x1c
- field public static final int TYPE_WAKE_UP_RELATIVE_HUMIDITY = 32; // 0x20
- field public static final int TYPE_WAKE_UP_ROTATION_VECTOR = 31; // 0x1f
- field public static final int TYPE_WAKE_UP_STEP_COUNTER = 38; // 0x26
- field public static final int TYPE_WAKE_UP_STEP_DETECTOR = 37; // 0x25
- field public static final int TYPE_WAKE_UP_TILT_DETECTOR = 41; // 0x29
}
public class SensorEvent {
@@ -12162,7 +12052,6 @@ package android.hardware {
field public static final int SENSOR_STATUS_ACCURACY_HIGH = 3; // 0x3
field public static final int SENSOR_STATUS_ACCURACY_LOW = 1; // 0x1
field public static final int SENSOR_STATUS_ACCURACY_MEDIUM = 2; // 0x2
- field public static final int SENSOR_STATUS_NO_CONTACT = -1; // 0xffffffff
field public static final int SENSOR_STATUS_UNRELIABLE = 0; // 0x0
field public static final deprecated int SENSOR_TEMPERATURE = 4; // 0x4
field public static final deprecated int SENSOR_TRICORDER = 64; // 0x40
@@ -12209,12 +12098,12 @@ package android.hardware.camera2 {
public static abstract class CameraCaptureSession.CaptureListener {
ctor public CameraCaptureSession.CaptureListener();
- method public void onCaptureCompleted(android.hardware.camera2.CameraDevice, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
- method public void onCaptureFailed(android.hardware.camera2.CameraDevice, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
- method public void onCaptureProgressed(android.hardware.camera2.CameraDevice, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
- method public void onCaptureSequenceAborted(android.hardware.camera2.CameraDevice, int);
- method public void onCaptureSequenceCompleted(android.hardware.camera2.CameraDevice, int, long);
- method public void onCaptureStarted(android.hardware.camera2.CameraDevice, android.hardware.camera2.CaptureRequest, long);
+ method public void onCaptureCompleted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.TotalCaptureResult);
+ method public void onCaptureFailed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureFailure);
+ method public void onCaptureProgressed(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, android.hardware.camera2.CaptureResult);
+ method public void onCaptureSequenceAborted(android.hardware.camera2.CameraCaptureSession, int);
+ method public void onCaptureSequenceCompleted(android.hardware.camera2.CameraCaptureSession, int, long);
+ method public void onCaptureStarted(android.hardware.camera2.CameraCaptureSession, android.hardware.camera2.CaptureRequest, long);
}
public static abstract class CameraCaptureSession.StateListener {
@@ -12301,7 +12190,7 @@ package android.hardware.camera2 {
method public final int hashCode();
}
- public abstract interface CameraDevice implements java.lang.AutoCloseable {
+ public abstract class CameraDevice implements java.lang.AutoCloseable {
method public abstract deprecated int capture(android.hardware.camera2.CaptureRequest, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract deprecated int captureBurst(java.util.List<android.hardware.camera2.CaptureRequest>, android.hardware.camera2.CameraDevice.CaptureListener, android.os.Handler) throws android.hardware.camera2.CameraAccessException;
method public abstract void close();
@@ -12694,14 +12583,7 @@ package android.hardware.camera2 {
public final class DngCreator implements java.lang.AutoCloseable {
ctor public DngCreator(android.hardware.camera2.CameraCharacteristics, android.hardware.camera2.CaptureResult);
method public void close();
- method public android.hardware.camera2.DngCreator setDescription(java.lang.String);
- method public android.hardware.camera2.DngCreator setLocation(android.location.Location);
- method public android.hardware.camera2.DngCreator setOrientation(int);
- method public android.hardware.camera2.DngCreator setThumbnail(android.graphics.Bitmap);
- method public android.hardware.camera2.DngCreator setThumbnail(android.media.Image);
- method public void writeByteBuffer(java.io.OutputStream, android.util.Size, java.nio.ByteBuffer, long) throws java.io.IOException;
method public void writeImage(java.io.OutputStream, android.media.Image) throws java.io.IOException;
- method public void writeInputStream(java.io.OutputStream, android.util.Size, java.io.InputStream, long) throws java.io.IOException;
}
public final class TotalCaptureResult extends android.hardware.camera2.CaptureResult {
@@ -13807,46 +13689,8 @@ package android.media {
method public void stop();
}
- public final class AudioAttributes {
- method public int getContentType();
- method public int getFlags();
- method public java.util.Set<java.lang.String> getTags();
- method public int getUsage();
- field public static final int CONTENT_TYPE_MOVIE = 3; // 0x3
- field public static final int CONTENT_TYPE_MUSIC = 2; // 0x2
- field public static final int CONTENT_TYPE_SONIFICATION = 4; // 0x4
- field public static final int CONTENT_TYPE_SPEECH = 1; // 0x1
- field public static final int CONTENT_TYPE_UNKNOWN = 0; // 0x0
- field public static final int FLAG_AUDIBILITY_ENFORCED = 1; // 0x1
- field public static final int USAGE_ALARM = 4; // 0x4
- field public static final int USAGE_ASSISTANCE_ACCESSIBILITY = 11; // 0xb
- field public static final int USAGE_ASSISTANCE_NAVIGATION_GUIDANCE = 12; // 0xc
- field public static final int USAGE_ASSISTANCE_SONIFICATION = 13; // 0xd
- field public static final int USAGE_GAME = 14; // 0xe
- field public static final int USAGE_MEDIA = 1; // 0x1
- field public static final int USAGE_NOTIFICATION = 5; // 0x5
- field public static final int USAGE_NOTIFICATION_COMMUNICATION_DELAYED = 9; // 0x9
- field public static final int USAGE_NOTIFICATION_COMMUNICATION_INSTANT = 8; // 0x8
- field public static final int USAGE_NOTIFICATION_COMMUNICATION_REQUEST = 7; // 0x7
- field public static final int USAGE_NOTIFICATION_EVENT = 10; // 0xa
- field public static final int USAGE_NOTIFICATION_TELEPHONY_RINGTONE = 6; // 0x6
- field public static final int USAGE_UNKNOWN = 0; // 0x0
- field public static final int USAGE_VOICE_COMMUNICATION = 2; // 0x2
- field public static final int USAGE_VOICE_COMMUNICATION_SIGNALLING = 3; // 0x3
- }
-
- public static class AudioAttributes.Builder {
- ctor public AudioAttributes.Builder();
- ctor public AudioAttributes.Builder(android.media.AudioAttributes);
- method public android.media.AudioAttributes.Builder addTag(java.lang.String);
- method public android.media.AudioAttributes build();
- method public android.media.AudioAttributes.Builder setContentType(int);
- method public android.media.AudioAttributes.Builder setFlags(int);
- method public android.media.AudioAttributes.Builder setLegacyStreamType(int);
- method public android.media.AudioAttributes.Builder setUsage(int);
- }
-
public class AudioFormat {
+ ctor public AudioFormat();
field public static final deprecated int CHANNEL_CONFIGURATION_DEFAULT = 1; // 0x1
field public static final deprecated int CHANNEL_CONFIGURATION_INVALID = 0; // 0x0
field public static final deprecated int CHANNEL_CONFIGURATION_MONO = 2; // 0x2
@@ -15978,6 +15822,180 @@ package android.media.session {
}
+package android.media.tv {
+
+ public final class TvContract {
+ method public static final android.net.Uri buildChannelUri(long);
+ method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName);
+ method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName, boolean);
+ method public static final android.net.Uri buildProgramUri(long);
+ method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri);
+ method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
+ field public static final java.lang.String AUTHORITY = "android.media.tv";
+ }
+
+ public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
+ field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
+ }
+
+ public static final class TvContract.Channels implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
+ field public static final java.lang.String COLUMN_DESCRIPTION = "description";
+ field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
+ field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
+ field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
+ field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
+ field public static final java.lang.String COLUMN_SERVICE_NAME = "service_name";
+ field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
+ field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
+ field public static final java.lang.String COLUMN_TYPE = "type";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
+ field public static final android.net.Uri CONTENT_URI;
+ field public static final int SERVICE_TYPE_AUDIO = 2; // 0x2
+ field public static final int SERVICE_TYPE_AUDIO_VIDEO = 1; // 0x1
+ field public static final int SERVICE_TYPE_OTHER = 0; // 0x0
+ field public static final int TYPE_1SEG = 263168; // 0x40400
+ field public static final int TYPE_ATSC_C = 197120; // 0x30200
+ field public static final int TYPE_ATSC_M_H = 197120; // 0x30200
+ field public static final int TYPE_ATSC_T = 196608; // 0x30000
+ field public static final int TYPE_CMMB = 327936; // 0x50100
+ field public static final int TYPE_DTMB = 327680; // 0x50000
+ field public static final int TYPE_DVB_C = 131584; // 0x20200
+ field public static final int TYPE_DVB_C2 = 131585; // 0x20201
+ field public static final int TYPE_DVB_H = 131840; // 0x20300
+ field public static final int TYPE_DVB_S = 131328; // 0x20100
+ field public static final int TYPE_DVB_S2 = 131329; // 0x20101
+ field public static final int TYPE_DVB_SH = 132096; // 0x20400
+ field public static final int TYPE_DVB_T = 131072; // 0x20000
+ field public static final int TYPE_DVB_T2 = 131073; // 0x20001
+ field public static final int TYPE_ISDB_C = 262912; // 0x40300
+ field public static final int TYPE_ISDB_S = 262656; // 0x40200
+ field public static final int TYPE_ISDB_T = 262144; // 0x40000
+ field public static final int TYPE_ISDB_TB = 262400; // 0x40100
+ field public static final int TYPE_OTHER = 0; // 0x0
+ field public static final int TYPE_PASSTHROUGH = 65536; // 0x10000
+ field public static final int TYPE_S_DMB = 393472; // 0x60100
+ field public static final int TYPE_T_DMB = 393216; // 0x60000
+ }
+
+ public static final class TvContract.Programs implements android.media.tv.TvContract.BaseTvColumns {
+ field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
+ field public static final java.lang.String COLUMN_BROADCAST_GENRE = "broadcast_genre";
+ field public static final java.lang.String COLUMN_CANONICAL_GENRE = "canonical_genre";
+ field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
+ field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
+ field public static final java.lang.String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
+ field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
+ field public static final java.lang.String COLUMN_SHORT_DESCRIPTION = "short_description";
+ field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
+ field public static final java.lang.String COLUMN_TITLE = "title";
+ field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
+ field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
+ field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/program";
+ field public static final android.net.Uri CONTENT_URI;
+ }
+
+ public static final class TvContract.Programs.Genres {
+ method public static java.lang.String[] decode(java.lang.String);
+ method public static java.lang.String encode(java.lang.String...);
+ field public static final java.lang.String ANIMAL_WILDLIFE = "Animal/Wildlife";
+ field public static final java.lang.String COMEDY = "Comedy";
+ field public static final java.lang.String DRAMA = "Drama";
+ field public static final java.lang.String EDUCATION = "Education";
+ field public static final java.lang.String FAMILY_KIDS = "Family/Kids";
+ field public static final java.lang.String GAMING = "Gaming";
+ field public static final java.lang.String MOVIES = "Movies";
+ field public static final java.lang.String NEWS = "News";
+ field public static final java.lang.String SHOPPING = "Shopping";
+ field public static final java.lang.String SPORTS = "Sports";
+ field public static final java.lang.String TRAVEL = "Travel";
+ }
+
+ public final class TvInputInfo implements android.os.Parcelable {
+ method public int describeContents();
+ method public android.content.ComponentName getComponent();
+ method public java.lang.String getId();
+ method public android.content.Intent getIntentForSettingsActivity();
+ method public android.content.Intent getIntentForSetupActivity();
+ method public java.lang.String getPackageName();
+ method public java.lang.String getServiceName();
+ method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
+ method public void writeToParcel(android.os.Parcel, int);
+ field public static final java.lang.String EXTRA_SERVICE_NAME = "serviceName";
+ }
+
+ public final class TvInputManager {
+ method public void createSession(java.lang.String, android.media.tv.TvInputManager.SessionCallback, android.os.Handler);
+ method public boolean getAvailability(java.lang.String);
+ method public java.util.List<android.media.tv.TvInputInfo> getTvInputList();
+ method public void registerListener(java.lang.String, android.media.tv.TvInputManager.TvInputListener, android.os.Handler);
+ method public void unregisterListener(java.lang.String, android.media.tv.TvInputManager.TvInputListener);
+ }
+
+ public static final class TvInputManager.Session {
+ method public void release();
+ method public void setVolume(float);
+ method public void tune(android.net.Uri);
+ }
+
+ public static abstract class TvInputManager.SessionCallback {
+ ctor public TvInputManager.SessionCallback();
+ method public void onSessionCreated(android.media.tv.TvInputManager.Session);
+ method public void onSessionReleased(android.media.tv.TvInputManager.Session);
+ }
+
+ public static abstract class TvInputManager.TvInputListener {
+ ctor public TvInputManager.TvInputListener();
+ method public void onAvailabilityChanged(java.lang.String, boolean);
+ }
+
+ public abstract class TvInputService extends android.app.Service {
+ ctor public TvInputService();
+ method public final android.os.IBinder onBind(android.content.Intent);
+ method public abstract android.media.tv.TvInputService.TvInputSessionImpl onCreateSession();
+ method public final void setAvailable(boolean);
+ field public static final java.lang.String SERVICE_INTERFACE = "android.media.tv.TvInputService";
+ field public static final java.lang.String SERVICE_META_DATA = "android.media.tv.input";
+ }
+
+ public abstract class TvInputService.TvInputSessionImpl implements android.view.KeyEvent.Callback {
+ ctor public TvInputService.TvInputSessionImpl();
+ method public android.view.View onCreateOverlayView();
+ method public boolean onGenericMotionEvent(android.view.MotionEvent);
+ method public boolean onKeyDown(int, android.view.KeyEvent);
+ method public boolean onKeyLongPress(int, android.view.KeyEvent);
+ method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+ method public boolean onKeyUp(int, android.view.KeyEvent);
+ method public abstract void onRelease();
+ method public abstract boolean onSetSurface(android.view.Surface);
+ method public abstract void onSetVolume(float);
+ method public boolean onTouchEvent(android.view.MotionEvent);
+ method public boolean onTrackballEvent(android.view.MotionEvent);
+ method public abstract boolean onTune(android.net.Uri);
+ method public void setOverlayViewEnabled(boolean);
+ }
+
+ public class TvView extends android.view.SurfaceView {
+ ctor public TvView(android.content.Context);
+ ctor public TvView(android.content.Context, android.util.AttributeSet);
+ ctor public TvView(android.content.Context, android.util.AttributeSet, int);
+ method public void bindTvInput(java.lang.String, android.media.tv.TvInputManager.SessionCallback);
+ method public boolean dispatchUnhandledInputEvent(android.view.InputEvent);
+ method public boolean onUnhandledInputEvent(android.view.InputEvent);
+ method public void setOnUnhandledInputEventListener(android.media.tv.TvView.OnUnhandledInputEventListener);
+ method public void unbindTvInput();
+ }
+
+ public static abstract interface TvView.OnUnhandledInputEventListener {
+ method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
+ }
+
+}
+
package android.mtp {
public final class MtpConstants {
@@ -17173,9 +17191,11 @@ package android.net.wifi {
}
public static final class WifiEnterpriseConfig.Eap {
+ field public static final int AKA = 5; // 0x5
field public static final int NONE = -1; // 0xffffffff
field public static final int PEAP = 0; // 0x0
field public static final int PWD = 3; // 0x3
+ field public static final int SIM = 4; // 0x4
field public static final int TLS = 1; // 0x1
field public static final int TTLS = 2; // 0x2
}
@@ -17209,7 +17229,6 @@ package android.net.wifi {
public class WifiManager {
method public int addNetwork(android.net.wifi.WifiConfiguration);
method public static int calculateSignalLevel(int, int);
- method public void cancelWps(android.net.wifi.WifiManager.ActionListener);
method public static int compareSignalLevel(int, int);
method public android.net.wifi.WifiManager.MulticastLock createMulticastLock(java.lang.String);
method public android.net.wifi.WifiManager.WifiLock createWifiLock(int, java.lang.String);
@@ -17233,12 +17252,9 @@ package android.net.wifi {
method public void setTdlsEnabledWithMacAddress(java.lang.String, boolean);
method public boolean setWifiEnabled(boolean);
method public boolean startScan();
- method public void startWps(android.net.wifi.WpsInfo, android.net.wifi.WifiManager.WpsListener);
method public int updateNetwork(android.net.wifi.WifiConfiguration);
field public static final java.lang.String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
field public static final java.lang.String ACTION_REQUEST_SCAN_ALWAYS_AVAILABLE = "android.net.wifi.action.REQUEST_SCAN_ALWAYS_AVAILABLE";
- field public static final int BUSY = 2; // 0x2
- field public static final int ERROR = 0; // 0x0
field public static final int ERROR_AUTHENTICATING = 1; // 0x1
field public static final java.lang.String EXTRA_BSSID = "bssid";
field public static final java.lang.String EXTRA_NETWORK_INFO = "networkInfo";
@@ -17249,8 +17265,6 @@ package android.net.wifi {
field public static final java.lang.String EXTRA_SUPPLICANT_ERROR = "supplicantError";
field public static final java.lang.String EXTRA_WIFI_INFO = "wifiInfo";
field public static final java.lang.String EXTRA_WIFI_STATE = "wifi_state";
- field public static final int INVALID_ARGS = 8; // 0x8
- field public static final int IN_PROGRESS = 1; // 0x1
field public static final java.lang.String NETWORK_IDS_CHANGED_ACTION = "android.net.wifi.NETWORK_IDS_CHANGED";
field public static final java.lang.String NETWORK_STATE_CHANGED_ACTION = "android.net.wifi.STATE_CHANGE";
field public static final java.lang.String RSSI_CHANGED_ACTION = "android.net.wifi.RSSI_CHANGED";
@@ -17266,16 +17280,6 @@ package android.net.wifi {
field public static final int WIFI_STATE_ENABLED = 3; // 0x3
field public static final int WIFI_STATE_ENABLING = 2; // 0x2
field public static final int WIFI_STATE_UNKNOWN = 4; // 0x4
- field public static final int WPS_AUTH_FAILURE = 6; // 0x6
- field public static final int WPS_OVERLAP_ERROR = 3; // 0x3
- field public static final int WPS_TIMED_OUT = 7; // 0x7
- field public static final int WPS_TKIP_ONLY_PROHIBITED = 5; // 0x5
- field public static final int WPS_WEP_PROHIBITED = 4; // 0x4
- }
-
- public static abstract interface WifiManager.ActionListener {
- method public abstract void onFailure(int);
- method public abstract void onSuccess();
}
public class WifiManager.MulticastLock {
@@ -17293,18 +17297,11 @@ package android.net.wifi {
method public void setWorkSource(android.os.WorkSource);
}
- public static abstract interface WifiManager.WpsListener {
- method public abstract void onCompletion();
- method public abstract void onFailure(int);
- method public abstract void onStartSuccess(java.lang.String);
- }
-
public class WpsInfo implements android.os.Parcelable {
ctor public WpsInfo();
ctor public WpsInfo(android.net.wifi.WpsInfo);
method public int describeContents();
method public void writeToParcel(android.os.Parcel, int);
- field public java.lang.String BSSID;
field public static final android.os.Parcelable.Creator CREATOR;
field public static final int DISPLAY = 1; // 0x1
field public static final int INVALID = 4; // 0x4
@@ -21585,9 +21582,7 @@ package android.os {
method public abstract void cancel();
method public abstract boolean hasVibrator();
method public void vibrate(long);
- method public void vibrate(long, int);
method public void vibrate(long[], int);
- method public void vibrate(long[], int, int);
}
public class WorkSource implements android.os.Parcelable {
@@ -23371,13 +23366,6 @@ package android.provider {
field public static final java.lang.String URL = "data1";
}
- public static final class ContactsContract.ContactCounts {
- ctor public ContactsContract.ContactCounts();
- field public static final java.lang.String ADDRESS_BOOK_INDEX_EXTRAS = "address_book_index_extras";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_COUNTS = "address_book_index_counts";
- field public static final java.lang.String EXTRA_ADDRESS_BOOK_INDEX_TITLES = "address_book_index_titles";
- }
-
protected static abstract interface ContactsContract.ContactNameColumns {
field public static final java.lang.String DISPLAY_NAME_ALTERNATIVE = "display_name_alt";
field public static final java.lang.String DISPLAY_NAME_PRIMARY = "display_name";
@@ -24945,81 +24933,6 @@ package android.provider {
field public static final java.lang.String TYPE = "type";
}
- public final class TvContract {
- method public static final android.net.Uri buildChannelUri(long);
- method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName);
- method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName, boolean);
- method public static final android.net.Uri buildProgramUri(long);
- method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri);
- method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
- field public static final java.lang.String AUTHORITY = "com.android.tv";
- }
-
- public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
- field public static final java.lang.String COLUMN_PACKAGE_NAME = "package_name";
- }
-
- public static final class TvContract.Channels implements android.provider.TvContract.BaseTvColumns {
- field public static final java.lang.String COLUMN_BROWSABLE = "browsable";
- field public static final java.lang.String COLUMN_DATA = "data";
- field public static final java.lang.String COLUMN_DESCRIPTION = "description";
- field public static final java.lang.String COLUMN_DISPLAY_NAME = "display_name";
- field public static final java.lang.String COLUMN_DISPLAY_NUMBER = "display_number";
- field public static final java.lang.String COLUMN_LOCKED = "locked";
- field public static final java.lang.String COLUMN_ORIGINAL_NETWORK_ID = "original_network_id";
- field public static final java.lang.String COLUMN_SEARCHABLE = "searchable";
- field public static final java.lang.String COLUMN_SERVICE_ID = "service_id";
- field public static final java.lang.String COLUMN_SERVICE_NAME = "service_name";
- field public static final java.lang.String COLUMN_SERVICE_TYPE = "service_type";
- field public static final java.lang.String COLUMN_TRANSPORT_STREAM_ID = "transport_stream_id";
- field public static final java.lang.String COLUMN_TYPE = "type";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.channels";
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.channels";
- field public static final android.net.Uri CONTENT_URI;
- field public static final int SERVICE_TYPE_OTHER = 0; // 0x0
- field public static final int SERVICE_TYPE_RADIO = 2; // 0x2
- field public static final int SERVICE_TYPE_TV = 1; // 0x1
- field public static final int TYPE_1SEG = 263168; // 0x40400
- field public static final int TYPE_ATSC_C = 197120; // 0x30200
- field public static final int TYPE_ATSC_M_H = 197120; // 0x30200
- field public static final int TYPE_ATSC_T = 196608; // 0x30000
- field public static final int TYPE_CMMB = 327936; // 0x50100
- field public static final int TYPE_DTMB = 327680; // 0x50000
- field public static final int TYPE_DVB_C = 131584; // 0x20200
- field public static final int TYPE_DVB_C2 = 131585; // 0x20201
- field public static final int TYPE_DVB_H = 131840; // 0x20300
- field public static final int TYPE_DVB_S = 131328; // 0x20100
- field public static final int TYPE_DVB_S2 = 131329; // 0x20101
- field public static final int TYPE_DVB_SH = 132096; // 0x20400
- field public static final int TYPE_DVB_T = 131072; // 0x20000
- field public static final int TYPE_DVB_T2 = 131073; // 0x20001
- field public static final int TYPE_ISDB_C = 262912; // 0x40300
- field public static final int TYPE_ISDB_S = 262656; // 0x40200
- field public static final int TYPE_ISDB_T = 262144; // 0x40000
- field public static final int TYPE_ISDB_TB = 262400; // 0x40100
- field public static final int TYPE_OTHER = 0; // 0x0
- field public static final int TYPE_PASSTHROUGH = 65536; // 0x10000
- field public static final int TYPE_S_DMB = 393472; // 0x60100
- field public static final int TYPE_T_DMB = 393216; // 0x60000
- }
-
- public static final class TvContract.Programs implements android.provider.TvContract.BaseTvColumns {
- field public static final java.lang.String COLUMN_AUDIO_LANGUAGE = "audio_language";
- field public static final java.lang.String COLUMN_CHANNEL_ID = "channel_id";
- field public static final java.lang.String COLUMN_DATA = "data";
- field public static final java.lang.String COLUMN_DESCRIPTION = "description";
- field public static final java.lang.String COLUMN_END_TIME_UTC_MILLIS = "end_time_utc_millis";
- field public static final java.lang.String COLUMN_GENRE = "genre";
- field public static final java.lang.String COLUMN_LONG_DESCRIPTION = "long_description";
- field public static final java.lang.String COLUMN_START_TIME_UTC_MILLIS = "start_time_utc_millis";
- field public static final java.lang.String COLUMN_TITLE = "title";
- field public static final java.lang.String COLUMN_VERSION_NUMBER = "version_number";
- field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.programs";
- field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.programs";
- field public static final android.net.Uri CONTENT_URI;
- }
-
public class UserDictionary {
ctor public UserDictionary();
field public static final java.lang.String AUTHORITY = "user_dictionary";
@@ -26469,28 +26382,6 @@ package android.speech {
package android.speech.tts {
- public final class Markup implements android.os.Parcelable {
- ctor public Markup();
- ctor public Markup(java.lang.String);
- ctor public Markup(android.speech.tts.Markup);
- method public android.speech.tts.Markup addNestedMarkup(android.speech.tts.Markup);
- method public int describeContents();
- method public android.speech.tts.Markup getNestedMarkup(int);
- method public java.util.List<android.speech.tts.Markup> getNestedMarkups();
- method public java.lang.String getParameter(java.lang.String);
- method public java.lang.String getPlainText();
- method public java.lang.String getType();
- method public static android.speech.tts.Markup markupFromString(java.lang.String) throws java.lang.IllegalArgumentException;
- method public int nestedMarkupSize();
- method public int parametersSize();
- method public boolean removeNestedMarkup(android.speech.tts.Markup);
- method public void removeParameter(java.lang.String);
- method public android.speech.tts.Markup setParameter(java.lang.String, java.lang.String);
- method public void setPlainText(java.lang.String);
- method public void setType(java.lang.String);
- method public void writeToParcel(android.os.Parcel, int);
- }
-
public final class RequestConfig {
method public android.os.Bundle getAudioParams();
method public android.speech.tts.VoiceInfo getVoice();
@@ -26553,10 +26444,9 @@ package android.speech.tts {
}
public final class SynthesisRequestV2 implements android.os.Parcelable {
- ctor public SynthesisRequestV2(android.speech.tts.Markup, java.lang.String, java.lang.String, android.os.Bundle, android.os.Bundle);
+ ctor public SynthesisRequestV2(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle, android.os.Bundle);
method public int describeContents();
method public android.os.Bundle getAudioParams();
- method public android.speech.tts.Markup getMarkup();
method public java.lang.String getText();
method public java.lang.String getUtteranceId();
method public java.lang.String getVoiceName();
@@ -26659,9 +26549,7 @@ package android.speech.tts {
method public void queueAudio(android.net.Uri, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
method public void queueSilence(long, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.TextToSpeechClient.RequestCallbacks);
method public void queueSpeak(java.lang.String, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
- method public void queueSpeak(android.speech.tts.Markup, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
method public void queueSynthesizeToFile(java.lang.String, android.speech.tts.TextToSpeechClient.UtteranceId, java.io.File, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
- method public void queueSynthesizeToFile(android.speech.tts.Markup, android.speech.tts.TextToSpeechClient.UtteranceId, java.io.File, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
method public void stop();
}
@@ -26735,85 +26623,6 @@ package android.speech.tts {
method protected void onVoicesInfoChange();
}
- public class Utterance {
- ctor public Utterance();
- method public android.speech.tts.Utterance append(android.speech.tts.Utterance.AbstractTts<? extends android.speech.tts.Utterance.AbstractTts<?>>);
- method public android.speech.tts.Utterance append(java.lang.String);
- method public android.speech.tts.Utterance append(int);
- method public android.speech.tts.Markup createMarkup();
- method public android.speech.tts.Utterance.AbstractTts<? extends android.speech.tts.Utterance.AbstractTts<?>> get(int);
- method public android.speech.tts.Utterance setNoWarningOnFallback(boolean);
- method public int size();
- method public static android.speech.tts.Utterance utteranceFromString(java.lang.String) throws java.lang.IllegalArgumentException;
- field public static final int ANIMACY_ANIMATE = 1; // 0x1
- field public static final int ANIMACY_INANIMATE = 2; // 0x2
- field public static final int ANIMACY_UNKNOWN = 0; // 0x0
- field public static final int CASE_ABLATIVE = 4; // 0x4
- field public static final int CASE_ACCUSATIVE = 2; // 0x2
- field public static final int CASE_DATIVE = 3; // 0x3
- field public static final int CASE_GENITIVE = 5; // 0x5
- field public static final int CASE_INSTRUMENTAL = 8; // 0x8
- field public static final int CASE_LOCATIVE = 7; // 0x7
- field public static final int CASE_NOMINATIVE = 1; // 0x1
- field public static final int CASE_UNKNOWN = 0; // 0x0
- field public static final int CASE_VOCATIVE = 6; // 0x6
- field public static final int GENDER_FEMALE = 3; // 0x3
- field public static final int GENDER_MALE = 2; // 0x2
- field public static final int GENDER_NEUTRAL = 1; // 0x1
- field public static final int GENDER_UNKNOWN = 0; // 0x0
- field public static final java.lang.String KEY_NO_WARNING_ON_FALLBACK = "no_warning_on_fallback";
- field public static final int MULTIPLICITY_DUAL = 2; // 0x2
- field public static final int MULTIPLICITY_PLURAL = 3; // 0x3
- field public static final int MULTIPLICITY_SINGLE = 1; // 0x1
- field public static final int MULTIPLICITY_UNKNOWN = 0; // 0x0
- field public static final java.lang.String TYPE_UTTERANCE = "utterance";
- }
-
- public static abstract class Utterance.AbstractTts {
- ctor protected Utterance.AbstractTts();
- ctor protected Utterance.AbstractTts(android.speech.tts.Markup);
- method public java.lang.String generatePlainText();
- method public android.speech.tts.Markup getMarkup();
- method protected java.lang.String getParameter(java.lang.String);
- method public java.lang.String getPlainText();
- method public java.lang.String getType();
- method protected C removeParameter(java.lang.String);
- method protected C setParameter(java.lang.String, java.lang.String);
- method public C setPlainText(java.lang.String);
- field protected android.speech.tts.Markup mMarkup;
- }
-
- public static abstract class Utterance.AbstractTtsSemioticClass extends android.speech.tts.Utterance.AbstractTts {
- ctor protected Utterance.AbstractTtsSemioticClass();
- ctor protected Utterance.AbstractTtsSemioticClass(android.speech.tts.Markup);
- method public int getAnimacy();
- method public int getCase();
- method public int getGender();
- method public int getMultiplicity();
- method public C setAnimacy(int);
- method public C setCase(int);
- method public C setGender(int);
- method public C setMultiplicity(int);
- }
-
- public static class Utterance.TtsCardinal extends android.speech.tts.Utterance.AbstractTtsSemioticClass {
- ctor public Utterance.TtsCardinal();
- ctor public Utterance.TtsCardinal(int);
- ctor public Utterance.TtsCardinal(java.lang.String);
- method public java.lang.String getInteger();
- method public android.speech.tts.Utterance.TtsCardinal setInteger(int);
- method public android.speech.tts.Utterance.TtsCardinal setInteger(java.lang.String);
- field protected static final java.lang.String TYPE_CARDINAL = "cardinal";
- }
-
- public static class Utterance.TtsText extends android.speech.tts.Utterance.AbstractTtsSemioticClass {
- ctor public Utterance.TtsText();
- ctor public Utterance.TtsText(java.lang.String);
- method public java.lang.String getText();
- method public android.speech.tts.Utterance.TtsText setText(java.lang.String);
- field protected static final java.lang.String TYPE_TEXT = "text";
- }
-
public abstract class UtteranceProgressListener {
ctor public UtteranceProgressListener();
method public abstract void onDone(java.lang.String);
@@ -27492,313 +27301,6 @@ package android.system {
}
-package android.telecomm {
-
- public final class CallAudioState implements android.os.Parcelable {
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- field public static int ROUTE_ALL;
- field public static int ROUTE_BLUETOOTH;
- field public static int ROUTE_EARPIECE;
- field public static int ROUTE_SPEAKER;
- field public static int ROUTE_WIRED_HEADSET;
- field public static int ROUTE_WIRED_OR_EARPIECE;
- field public final boolean isMuted;
- field public final int route;
- field public final int supportedRouteMask;
- }
-
- public class CallCapabilities {
- ctor public CallCapabilities();
- field public static final int ADD_CALL = 16; // 0x10
- field public static final int ALL = 511; // 0x1ff
- field public static final int CONNECTION_HANDOFF = 256; // 0x100
- field public static final int GENERIC_CONFERENCE = 128; // 0x80
- field public static final int HOLD = 1; // 0x1
- field public static final int MERGE_CALLS = 4; // 0x4
- field public static final int MUTE = 64; // 0x40
- field public static final int RESPOND_VIA_TEXT = 32; // 0x20
- field public static final int SUPPORT_HOLD = 2; // 0x2
- field public static final int SWAP_CALLS = 8; // 0x8
- }
-
- public final class CallInfo implements android.os.Parcelable {
- ctor public CallInfo(java.lang.String, android.telecomm.CallState, android.net.Uri);
- method public int describeContents();
- method public android.telecomm.CallServiceDescriptor getCurrentCallServiceDescriptor();
- method public android.os.Bundle getExtras();
- method public android.telecomm.GatewayInfo getGatewayInfo();
- method public android.net.Uri getHandle();
- method public java.lang.String getId();
- method public android.net.Uri getOriginalHandle();
- method public android.telecomm.CallState getState();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public final class CallNumberPresentation extends java.lang.Enum {
- method public static android.telecomm.CallNumberPresentation valueOf(java.lang.String);
- method public static final android.telecomm.CallNumberPresentation[] values();
- enum_constant public static final android.telecomm.CallNumberPresentation ALLOWED;
- enum_constant public static final android.telecomm.CallNumberPresentation PAYPHONE;
- enum_constant public static final android.telecomm.CallNumberPresentation RESTRICTED;
- enum_constant public static final android.telecomm.CallNumberPresentation UNKNOWN;
- }
-
- public abstract class CallService extends android.app.Service {
- ctor public CallService();
- method public abstract void abort(java.lang.String);
- method public abstract void answer(java.lang.String);
- method public abstract void call(android.telecomm.CallInfo);
- method public abstract void disconnect(java.lang.String);
- method protected final android.telecomm.CallServiceAdapter getAdapter();
- method public final android.os.IBinder getBinder();
- method public abstract void hold(java.lang.String);
- method public abstract void isCompatibleWith(android.telecomm.CallInfo);
- method protected void onAdapterAttached(android.telecomm.CallServiceAdapter);
- method public abstract void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
- method public final android.os.IBinder onBind(android.content.Intent);
- method public abstract void playDtmfTone(java.lang.String, char);
- method public abstract void reject(java.lang.String);
- method public abstract void setIncomingCallId(java.lang.String, android.os.Bundle);
- method public abstract void stopDtmfTone(java.lang.String);
- method public abstract void unhold(java.lang.String);
- }
-
- public final class CallServiceAdapter {
- method public void handleFailedOutgoingCall(java.lang.String, java.lang.String);
- method public void handleSuccessfulOutgoingCall(java.lang.String);
- method public void notifyIncomingCall(android.telecomm.CallInfo);
- method public void setActive(java.lang.String);
- method public void setDialing(java.lang.String);
- method public void setDisconnected(java.lang.String, int, java.lang.String);
- method public void setIsCompatibleWith(java.lang.String, boolean);
- method public void setOnHold(java.lang.String);
- method public void setRequestingRingback(java.lang.String, boolean);
- method public void setRinging(java.lang.String);
- }
-
- public final class CallServiceDescriptor implements android.os.Parcelable {
- method public int describeContents();
- method public java.lang.String getCallServiceId();
- method public int getNetworkType();
- method public android.content.ComponentName getServiceComponent();
- method public static android.telecomm.CallServiceDescriptor.Builder newBuilder(android.content.Context);
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- field public static final int FLAG_MOBILE = 4; // 0x4
- field public static final int FLAG_PSTN = 2; // 0x2
- field public static final int FLAG_WIFI = 1; // 0x1
- }
-
- public static class CallServiceDescriptor.Builder {
- method public android.telecomm.CallServiceDescriptor build();
- method public android.telecomm.CallServiceDescriptor.Builder setCallService(java.lang.Class<? extends android.telecomm.CallService>);
- method public android.telecomm.CallServiceDescriptor.Builder setNetworkType(int);
- }
-
- public final class CallServiceLookupResponse {
- method public void setCallServiceDescriptors(java.util.List<android.telecomm.CallServiceDescriptor>);
- }
-
- public abstract class CallServiceProvider extends android.app.Service {
- ctor protected CallServiceProvider();
- method public abstract void lookupCallServices(android.telecomm.CallServiceLookupResponse);
- method public android.os.IBinder onBind(android.content.Intent);
- }
-
- public abstract class CallServiceSelector extends android.app.Service {
- ctor protected CallServiceSelector();
- method protected final void cancelOutgoingCall(android.telecomm.CallInfo);
- method protected final android.telecomm.CallServiceSelectorAdapter getAdapter();
- method protected final java.util.Collection<android.telecomm.CallInfo> getCalls();
- method protected void onAdapterAttached(android.telecomm.CallServiceSelectorAdapter);
- method public final android.os.IBinder onBind(android.content.Intent);
- method protected abstract void select(android.telecomm.CallInfo, java.util.List<android.telecomm.CallServiceDescriptor>);
- }
-
- public final class CallServiceSelectorAdapter {
- method public void cancelOutgoingCall(java.lang.String);
- method public void setHandoffInfo(java.lang.String, android.net.Uri, android.os.Bundle);
- method public void setSelectedCallServices(java.lang.String, java.util.List<android.telecomm.CallServiceDescriptor>);
- }
-
- public final class CallState extends java.lang.Enum {
- method public static android.telecomm.CallState valueOf(java.lang.String);
- method public static final android.telecomm.CallState[] values();
- enum_constant public static final android.telecomm.CallState ACTIVE;
- enum_constant public static final android.telecomm.CallState DIALING;
- enum_constant public static final android.telecomm.CallState DISCONNECTED;
- enum_constant public static final android.telecomm.CallState NEW;
- enum_constant public static final android.telecomm.CallState ON_HOLD;
- enum_constant public static final android.telecomm.CallState POST_DIAL;
- enum_constant public static final android.telecomm.CallState POST_DIAL_WAIT;
- enum_constant public static final android.telecomm.CallState RINGING;
- }
-
- public abstract class Connection {
- ctor protected Connection();
- method public final android.telecomm.CallAudioState getCallAudioState();
- method public final android.net.Uri getHandle();
- method public boolean isRequestingRingback();
- method protected void onAbort();
- method protected void onAnswer();
- method protected void onDisconnect();
- method protected void onHold();
- method protected void onPlayDtmfTone(char);
- method protected void onReject();
- method protected void onSetAudioState(android.telecomm.CallAudioState);
- method protected void onSetSignal(android.os.Bundle);
- method protected void onSetState(int);
- method protected void onStopDtmfTone();
- method protected void onUnhold();
- method protected void setActive();
- method public void setAudioState(android.telecomm.CallAudioState);
- method protected void setDialing();
- method protected void setDisconnected(int, java.lang.String);
- method protected void setHandle(android.net.Uri);
- method protected void setOnHold();
- method protected void setRequestingRingback(boolean);
- method protected void setRinging();
- method public static java.lang.String stateToString(int);
- }
-
- public static abstract interface Connection.Listener {
- method public abstract void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
- method public abstract void onDestroyed(android.telecomm.Connection);
- method public abstract void onDisconnected(android.telecomm.Connection, int, java.lang.String);
- method public abstract void onHandleChanged(android.telecomm.Connection, android.net.Uri);
- method public abstract void onRequestingRingback(android.telecomm.Connection, boolean);
- method public abstract void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
- method public abstract void onStateChanged(android.telecomm.Connection, int);
- }
-
- public static class Connection.ListenerBase implements android.telecomm.Connection.Listener {
- ctor public Connection.ListenerBase();
- method public void onAudioStateChanged(android.telecomm.Connection, android.telecomm.CallAudioState);
- method public void onDestroyed(android.telecomm.Connection);
- method public void onDisconnected(android.telecomm.Connection, int, java.lang.String);
- method public void onHandleChanged(android.telecomm.Connection, android.net.Uri);
- method public void onRequestingRingback(android.telecomm.Connection, boolean);
- method public void onSignalChanged(android.telecomm.Connection, android.os.Bundle);
- method public void onStateChanged(android.telecomm.Connection, int);
- }
-
- public final class Connection.State {
- field public static final int ACTIVE = 3; // 0x3
- field public static final int DIALING = 2; // 0x2
- field public static final int DISCONNECTED = 5; // 0x5
- field public static final int HOLDING = 4; // 0x4
- field public static final int NEW = 0; // 0x0
- field public static final int RINGING = 1; // 0x1
- }
-
- public final class ConnectionRequest {
- ctor public ConnectionRequest(android.net.Uri, android.os.Bundle);
- method public android.os.Bundle getExtras();
- method public android.net.Uri getHandle();
- }
-
- public abstract class ConnectionService extends android.telecomm.CallService {
- ctor public ConnectionService();
- method public final void abort(java.lang.String);
- method public final void answer(java.lang.String);
- method public final void call(android.telecomm.CallInfo);
- method public final void disconnect(java.lang.String);
- method public final void hold(java.lang.String);
- method public final void isCompatibleWith(android.telecomm.CallInfo);
- method public final void onAudioStateChanged(java.lang.String, android.telecomm.CallAudioState);
- method public void onCreateConnections(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
- method public void onCreateIncomingConnection(android.telecomm.ConnectionRequest, android.telecomm.Response<android.telecomm.ConnectionRequest, android.telecomm.Connection>);
- method public void onFindSubscriptions(android.net.Uri, android.telecomm.Response<android.net.Uri, android.telecomm.Subscription>);
- method public final void playDtmfTone(java.lang.String, char);
- method public final void reject(java.lang.String);
- method public final void setIncomingCallId(java.lang.String, android.os.Bundle);
- method public final void stopDtmfTone(java.lang.String);
- method public final void unhold(java.lang.String);
- }
-
- public class GatewayInfo implements android.os.Parcelable {
- method public int describeContents();
- method public android.net.Uri getGatewayHandle();
- method public java.lang.String getGatewayProviderPackageName();
- method public android.net.Uri getOriginalHandle();
- method public boolean isEmpty();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public final class InCallAdapter {
- method public void answerCall(java.lang.String);
- method public void disconnectCall(java.lang.String);
- method public void handoffCall(java.lang.String);
- method public void holdCall(java.lang.String);
- method public void mute(boolean);
- method public void playDtmfTone(java.lang.String, char);
- method public void postDialContinue(java.lang.String);
- method public void rejectCall(java.lang.String);
- method public void setAudioRoute(int);
- method public void stopDtmfTone(java.lang.String);
- method public void unholdCall(java.lang.String);
- }
-
- public final class InCallCall implements android.os.Parcelable {
- method public int describeContents();
- method public int getCapabilities();
- method public long getConnectTimeMillis();
- method public android.telecomm.CallServiceDescriptor getCurrentCallServiceDescriptor();
- method public int getDisconnectCause();
- method public android.telecomm.GatewayInfo getGatewayInfo();
- method public android.net.Uri getHandle();
- method public android.telecomm.CallServiceDescriptor getHandoffCallServiceDescriptor();
- method public java.lang.String getId();
- method public android.telecomm.CallState getState();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public abstract class InCallService extends android.app.Service {
- ctor protected InCallService();
- method protected abstract void addCall(android.telecomm.InCallCall);
- method protected abstract void bringToForeground(boolean);
- method protected final android.telecomm.InCallAdapter getAdapter();
- method protected void onAdapterAttached(android.telecomm.InCallAdapter);
- method protected abstract void onAudioStateChanged(android.telecomm.CallAudioState);
- method public final android.os.IBinder onBind(android.content.Intent);
- method protected abstract void setPostDial(java.lang.String, java.lang.String);
- method protected abstract void setPostDialWait(java.lang.String, java.lang.String);
- method protected abstract void updateCall(android.telecomm.InCallCall);
- }
-
- public abstract interface Response {
- method public abstract void onError(IN, java.lang.String);
- method public abstract void onResult(IN, OUT...);
- }
-
- public class Subscription implements android.os.Parcelable {
- ctor public Subscription();
- method public int describeContents();
- method public void writeToParcel(android.os.Parcel, int);
- field public static final android.os.Parcelable.Creator CREATOR;
- }
-
- public final class TelecommConstants {
- ctor public TelecommConstants();
- field public static final java.lang.String ACTION_CALL_SERVICE;
- field public static final java.lang.String ACTION_CALL_SERVICE_PROVIDER;
- field public static final java.lang.String ACTION_CALL_SERVICE_SELECTOR;
- field public static final java.lang.String ACTION_INCOMING_CALL = "android.intent.action.INCOMING_CALL";
- field public static final char DTMF_CHARACTER_PAUSE = 44; // 0x002c ','
- field public static final char DTMF_CHARACTER_WAIT = 59; // 0x003b ';'
- field public static final java.lang.String EXTRA_CALL_DISCONNECT_CAUSE = "android.telecomm.extra.CALL_DISCONNECT_CAUSE";
- field public static final java.lang.String EXTRA_CALL_DISCONNECT_MESSAGE = "android.telecomm.extra.CALL_DISCONNECT_MESSAGE";
- field public static final java.lang.String EXTRA_CALL_SERVICE_DESCRIPTOR = "android.intent.extra.CALL_SERVICE_DESCRIPTOR";
- field public static final java.lang.String EXTRA_INCOMING_CALL_EXTRAS = "android.intent.extra.INCOMING_CALL_EXTRAS";
- }
-
-}
-
package android.telephony {
public final class CellIdentityCdma implements android.os.Parcelable {
@@ -30593,85 +30095,6 @@ package android.transition {
}
-package android.tv {
-
- public final class TvInputInfo implements android.os.Parcelable {
- method public int describeContents();
- method public android.content.ComponentName getComponent();
- method public java.lang.String getId();
- method public java.lang.String getPackageName();
- method public java.lang.String getServiceName();
- method public java.lang.CharSequence loadLabel(android.content.pm.PackageManager);
- method public void writeToParcel(android.os.Parcel, int);
- }
-
- public final class TvInputManager {
- method public void createSession(java.lang.String, android.tv.TvInputManager.SessionCallback, android.os.Handler);
- method public boolean getAvailability(java.lang.String);
- method public java.util.List<android.tv.TvInputInfo> getTvInputList();
- method public void registerListener(java.lang.String, android.tv.TvInputManager.TvInputListener, android.os.Handler);
- method public void unregisterListener(java.lang.String, android.tv.TvInputManager.TvInputListener);
- }
-
- public static final class TvInputManager.Session {
- method public void release();
- method public void setVolume(float);
- method public void tune(android.net.Uri);
- }
-
- public static abstract class TvInputManager.SessionCallback {
- ctor public TvInputManager.SessionCallback();
- method public void onSessionCreated(android.tv.TvInputManager.Session);
- method public void onSessionReleased(android.tv.TvInputManager.Session);
- }
-
- public static abstract class TvInputManager.TvInputListener {
- ctor public TvInputManager.TvInputListener();
- method public void onAvailabilityChanged(java.lang.String, boolean);
- }
-
- public abstract class TvInputService extends android.app.Service {
- ctor public TvInputService();
- method public final android.os.IBinder onBind(android.content.Intent);
- method public abstract android.tv.TvInputService.TvInputSessionImpl onCreateSession();
- method public final void setAvailable(boolean);
- field public static final java.lang.String SERVICE_INTERFACE = "android.tv.TvInputService";
- }
-
- public abstract class TvInputService.TvInputSessionImpl implements android.view.KeyEvent.Callback {
- ctor public TvInputService.TvInputSessionImpl();
- method public android.view.View onCreateOverlayView();
- method public boolean onGenericMotionEvent(android.view.MotionEvent);
- method public boolean onKeyDown(int, android.view.KeyEvent);
- method public boolean onKeyLongPress(int, android.view.KeyEvent);
- method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
- method public boolean onKeyUp(int, android.view.KeyEvent);
- method public abstract void onRelease();
- method public abstract boolean onSetSurface(android.view.Surface);
- method public abstract void onSetVolume(float);
- method public boolean onTouchEvent(android.view.MotionEvent);
- method public boolean onTrackballEvent(android.view.MotionEvent);
- method public abstract boolean onTune(android.net.Uri);
- method public void setOverlayViewEnabled(boolean);
- }
-
- public class TvView extends android.view.SurfaceView {
- ctor public TvView(android.content.Context);
- ctor public TvView(android.content.Context, android.util.AttributeSet);
- ctor public TvView(android.content.Context, android.util.AttributeSet, int);
- method public void bindTvInput(java.lang.String, android.tv.TvInputManager.SessionCallback);
- method public boolean dispatchUnhandledInputEvent(android.view.InputEvent);
- method public boolean onUnhandledInputEvent(android.view.InputEvent);
- method public void setOnUnhandledInputEventListener(android.tv.TvView.OnUnhandledInputEventListener);
- method public void unbindTvInput();
- }
-
- public static abstract interface TvView.OnUnhandledInputEventListener {
- method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
- }
-
-}
-
package android.util {
public class AndroidException extends java.lang.Exception {
@@ -32922,7 +32345,6 @@ package android.view {
method public void requestLayout();
method public boolean requestRectangleOnScreen(android.graphics.Rect);
method public boolean requestRectangleOnScreen(android.graphics.Rect, boolean);
- method public final void requestUnbufferedDispatch(android.view.MotionEvent);
method public static int resolveSize(int, int);
method public static int resolveSizeAndState(int, int, int);
method public void restoreHierarchyState(android.util.SparseArray<android.os.Parcelable>);
@@ -36620,10 +36042,6 @@ package android.widget {
method public void setRowCount(int);
method public void setRowOrderPreserved(boolean);
method public void setUseDefaultMargins(boolean);
- method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment, float);
- method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment, float);
- method public static android.widget.GridLayout.Spec spec(int, int, float);
- method public static android.widget.GridLayout.Spec spec(int, float);
method public static android.widget.GridLayout.Spec spec(int, int, android.widget.GridLayout.Alignment);
method public static android.widget.GridLayout.Spec spec(int, android.widget.GridLayout.Alignment);
method public static android.widget.GridLayout.Spec spec(int, int);
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index b7c2c22..47047b8 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -39,6 +39,7 @@ import android.content.pm.VerificationParams;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.net.Uri;
+import android.os.Build;
import android.os.Bundle;
import android.os.IUserManager;
import android.os.Process;
@@ -57,7 +58,6 @@ import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.WeakHashMap;
-
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
@@ -823,6 +823,7 @@ public final class Pm {
byte[] tag = null;
String originatingUriString = null;
String referrer = null;
+ String abi = null;
while ((opt=nextOption()) != null) {
if (opt.equals("-l")) {
@@ -893,12 +894,34 @@ public final class Pm {
System.err.println("Error: must supply argument for --referrer");
return;
}
+ } else if (opt.equals("--abi")) {
+ abi = nextOptionData();
+ if (abi == null) {
+ System.err.println("Error: must supply argument for --abi");
+ return;
+ }
} else {
System.err.println("Error: Unknown option: " + opt);
return;
}
}
+ if (abi != null) {
+ final String[] supportedAbis = Build.SUPPORTED_ABIS;
+ boolean matched = false;
+ for (String supportedAbi : supportedAbis) {
+ if (supportedAbi.equals(abi)) {
+ matched = true;
+ break;
+ }
+ }
+
+ if (!matched) {
+ System.err.println("Error: abi " + abi + " not supported on this device.");
+ return;
+ }
+ }
+
final ContainerEncryptionParams encryptionParams;
if (algo != null || iv != null || key != null || macAlgo != null || macKey != null
|| tag != null) {
@@ -976,8 +999,9 @@ public final class Pm {
VerificationParams verificationParams = new VerificationParams(verificationURI,
originatingURI, referrerURI, VerificationParams.NO_UID, null);
- mPm.installPackageWithVerificationAndEncryptionEtc(apkURI, null, obs, installFlags,
- installerPackageName, verificationParams, encryptionParams);
+ mPm.installPackageWithVerificationEncryptionAndAbiOverrideEtc(apkURI, null,
+ obs, installFlags, installerPackageName, verificationParams,
+ encryptionParams, abi);
synchronized (obs) {
while (!obs.finished) {
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
index 5e4ddd0..b739387 100644
--- a/core/java/android/app/ActivityTransitionCoordinator.java
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -129,8 +129,8 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
protected static final String KEY_SCALE_TYPE = "shared_element:scaleType";
protected static final String KEY_IMAGE_MATRIX = "shared_element:imageMatrix";
- // The background fade in/out duration. 150ms is pretty quick, but not abrupt.
- public static final int FADE_BACKGROUND_DURATION_MS = 150;
+ // The background fade in/out duration. TODO: Enable tuning this.
+ public static final int FADE_BACKGROUND_DURATION_MS = 300;
protected static final ImageView.ScaleType[] SCALE_TYPE_VALUES = ImageView.ScaleType.values();
@@ -195,6 +195,11 @@ abstract class ActivityTransitionCoordinator extends ResultReceiver {
*/
public static final int MSG_SHARED_ELEMENT_DESTINATION = 107;
+ /**
+ * Send the shared element positions.
+ */
+ public static final int MSG_SEND_SHARED_ELEMENT_DESTINATION = 108;
+
final private Window mWindow;
final protected ArrayList<String> mAllSharedElementNames;
final protected ArrayList<View> mSharedElements = new ArrayList<View>();
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 4f335bb..e03224c 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -75,6 +75,8 @@ import android.location.LocationManager;
import android.media.AudioManager;
import android.media.MediaRouter;
import android.media.session.MediaSessionManager;
+import android.media.tv.ITvInputManager;
+import android.media.tv.TvInputManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.EthernetManager;
@@ -119,8 +121,6 @@ import android.service.fingerprint.FingerprintManager;
import android.service.fingerprint.FingerprintManagerReceiver;
import android.service.fingerprint.FingerprintService;
import android.telephony.TelephonyManager;
-import android.tv.ITvInputManager;
-import android.tv.TvInputManager;
import android.content.ClipboardManager;
import android.util.AndroidRuntimeException;
import android.util.ArrayMap;
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
index a8617b8..4b052e7 100644
--- a/core/java/android/app/EnterTransitionCoordinator.java
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -29,6 +29,7 @@ import android.transition.TransitionManager;
import android.util.ArrayMap;
import android.util.Pair;
import android.view.View;
+import android.view.ViewGroup;
import android.view.ViewGroupOverlay;
import android.view.ViewTreeObserver;
import android.widget.ImageView;
@@ -72,8 +73,24 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
}
};
mHandler.sendEmptyMessageDelayed(MSG_CANCEL, MAX_WAIT_MS);
+ send(MSG_SEND_SHARED_ELEMENT_DESTINATION, null);
+ }
+ }
+
+ private void sendSharedElementDestination() {
+ ViewGroup decor = getDecor();
+ if (!decor.isLayoutRequested()) {
Bundle state = captureSharedElementState();
mResultReceiver.send(MSG_SHARED_ELEMENT_DESTINATION, state);
+ } else {
+ getDecor().getViewTreeObserver()
+ .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
+ @Override
+ public boolean onPreDraw() {
+ getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+ return true;
+ }
+ });
}
}
@@ -105,6 +122,9 @@ class EnterTransitionCoordinator extends ActivityTransitionCoordinator {
case MSG_CANCEL:
cancel();
break;
+ case MSG_SEND_SHARED_ELEMENT_DESTINATION:
+ sendSharedElementDestination();
+ break;
}
}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
index a71d649..ba1638f 100644
--- a/core/java/android/app/ExitTransitionCoordinator.java
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -294,7 +294,7 @@ class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
}
private void finishIfNecessary() {
- if (mIsReturning && mExitNotified && (mSharedElements.isEmpty()
+ if (mIsReturning && mExitNotified && mActivity != null && (mSharedElements.isEmpty()
|| mSharedElements.get(0).getVisibility() == View.INVISIBLE)) {
mActivity.finish();
mActivity.overridePendingTransition(0, 0);
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
index f332c9d..85e970c 100644
--- a/core/java/android/app/VoiceInteractor.java
+++ b/core/java/android/app/VoiceInteractor.java
@@ -43,7 +43,7 @@ import java.util.ArrayList;
* {@link Request} subclass describing the type of operation to perform -- currently the
* possible requests are {@link ConfirmationRequest} and {@link CommandRequest}.
*
- * <p>Once a request is submitted, the voice system will process it and evetually deliver
+ * <p>Once a request is submitted, the voice system will process it and eventually deliver
* the result to the request object. The application can cancel a pending request at any
* time.
*
@@ -51,7 +51,7 @@ import java.util.ArrayList;
* if an activity is being restarted with retained state, it will retain the current
* VoiceInteractor and any outstanding requests. Because of this, you should always use
* {@link Request#getActivity() Request.getActivity} to get back to the activity of a
- * request, rather than holding on to the actvitity instance yourself, either explicitly
+ * request, rather than holding on to the activity instance yourself, either explicitly
* or implicitly through a non-static inner class.
*/
public class VoiceInteractor {
@@ -236,7 +236,7 @@ public class VoiceInteractor {
* Reports that the current interaction can not be complete with voice, so the
* application will need to switch to a traditional input UI. Applications should
* only use this when they need to completely bail out of the voice interaction
- * and switch to a traditional UI. When the resonsponse comes back, the voice
+ * and switch to a traditional UI. When the response comes back, the voice
* system has handled the request and is ready to switch; at that point the application
* can start a new non-voice activity. Be sure when starting the new activity
* to use {@link android.content.Intent#FLAG_ACTIVITY_NEW_TASK
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index b3b1d47..24a354f 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -104,6 +104,17 @@ public class DevicePolicyManager {
= "android.app.action.ACTION_PROVISION_MANAGED_PROFILE";
/**
+ * A broadcast intent with this action can be sent to ManagedProvisionning to specify that the
+ * user has already consented to the creation of the managed profile.
+ * The intent must contain the extras
+ * {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME} and
+ * {@link #EXTRA_PROVISIONING_TOKEN}
+ * @hide
+ */
+ public static final String ACTION_PROVISIONING_USER_HAS_CONSENTED
+ = "android.app.action.USER_HAS_CONSENTED";
+
+ /**
* A String extra holding the name of the package of the mobile device management application
* that starts the managed provisioning flow. This package will be set as the profile owner.
* <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}.
@@ -112,6 +123,13 @@ public class DevicePolicyManager {
= "deviceAdminPackageName";
/**
+ * An int extra used to identify the consent of the user to create the managed profile.
+ * <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
+ */
+ public static final String EXTRA_PROVISIONING_TOKEN
+ = "android.app.extra.token";
+
+ /**
* A String extra holding the default name of the profile that is created during managed profile
* provisioning.
* <p>Use with {@link #ACTION_PROVISION_MANAGED_PROFILE}
@@ -2152,45 +2170,6 @@ public class DevicePolicyManager {
}
/**
- * Called by profile or device owner to re-enable a system app that was disabled by default
- * when the managed profile was created. This should only be called from a profile or device
- * owner running within a managed profile.
- *
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param packageName The package to be re-enabled in the current profile.
- */
- public void enableSystemApp(ComponentName admin, String packageName) {
- if (mService != null) {
- try {
- mService.enableSystemApp(admin, packageName);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to install package: " + packageName);
- }
- }
- }
-
- /**
- * Called by profile or device owner to re-enable system apps by intent that were disabled
- * by default when the managed profile was created. This should only be called from a profile
- * or device owner running within a managed profile.
- *
- * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
- * @param intent An intent matching the app(s) to be installed. All apps that resolve for this
- * intent will be re-enabled in the current profile.
- * @return int The number of activities that matched the intent and were installed.
- */
- public int enableSystemApp(ComponentName admin, Intent intent) {
- if (mService != null) {
- try {
- return mService.enableSystemAppWithIntent(admin, intent);
- } catch (RemoteException e) {
- Log.w(TAG, "Failed to install packages matching filter: " + intent);
- }
- }
- return 0;
- }
-
- /**
* Called by a profile owner to disable account management for a specific type of account.
*
* <p>The calling device admin must be a profile owner. If it is not, a
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 7f754dc..7d7a312 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -135,9 +135,6 @@ interface IDevicePolicyManager {
UserHandle createUser(in ComponentName who, in String name);
boolean removeUser(in ComponentName who, in UserHandle userHandle);
- void enableSystemApp(in ComponentName admin, in String packageName);
- int enableSystemAppWithIntent(in ComponentName admin, in Intent intent);
-
void setAccountManagementDisabled(in ComponentName who, in String accountType, in boolean disabled);
String[] getAccountTypesWithManagementDisabled();
diff --git a/core/java/android/app/backup/BackupTransport.java b/core/java/android/app/backup/BackupTransport.java
index da5cb10..46f082e 100644
--- a/core/java/android/app/backup/BackupTransport.java
+++ b/core/java/android/app/backup/BackupTransport.java
@@ -22,7 +22,6 @@ import android.os.IBinder;
import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
-import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.IBackupTransport;
/**
@@ -32,6 +31,13 @@ import com.android.internal.backup.IBackupTransport;
* @hide
*/
public class BackupTransport {
+ public static final int TRANSPORT_OK = 0;
+ public static final int TRANSPORT_ERROR = 1;
+ public static final int TRANSPORT_NOT_INITIALIZED = 2;
+ public static final int TRANSPORT_PACKAGE_REJECTED = 3;
+ public static final int AGENT_ERROR = 4;
+ public static final int AGENT_UNKNOWN = 5;
+
IBackupTransport mBinderImpl = new TransportImpl();
/** @hide */
public IBinder getBinder() {
@@ -99,10 +105,50 @@ public class BackupTransport {
}
// ------------------------------------------------------------------------------------
+ // Device-level operations common to both key/value and full-data storage
+
+ /**
+ * Initialize the server side storage for this device, erasing all stored data.
+ * The transport may send the request immediately, or may buffer it. After
+ * this is called, {@link #finishBackup} will be called to ensure the request
+ * is sent and received successfully.
+ *
+ * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far) or
+ * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure).
+ */
+ public int initializeDevice() {
+ return BackupTransport.TRANSPORT_ERROR;
+ }
+
+ /**
+ * Erase the given application's data from the backup destination. This clears
+ * out the given package's data from the current backup set, making it as though
+ * the app had never yet been backed up. After this is called, {@link finishBackup}
+ * must be called to ensure that the operation is recorded successfully.
+ *
+ * @return the same error codes as {@link #performBackup}.
+ */
+ public int clearBackupData(PackageInfo packageInfo) {
+ return BackupTransport.TRANSPORT_ERROR;
+ }
+
+ /**
+ * Finish sending application data to the backup destination. This must be
+ * called after {@link #performBackup}, {@link #performFullBackup}, or {@link clearBackupData}
+ * to ensure that all data is sent and the operation properly finalized. Only when this
+ * method returns true can a backup be assumed to have succeeded.
+ *
+ * @return the same error codes as {@link #performBackup} or {@link #performFullBackup}.
+ */
+ public int finishBackup() {
+ return BackupTransport.TRANSPORT_ERROR;
+ }
+
+ // ------------------------------------------------------------------------------------
// Key/value incremental backup support interfaces
/**
- * Verify that this is a suitable time for a backup pass. This should return zero
+ * Verify that this is a suitable time for a key/value backup pass. This should return zero
* if a backup is reasonable right now, some positive value otherwise. This method
* will be called outside of the {@link #performBackup}/{@link #finishBackup} pair.
*
@@ -117,19 +163,6 @@ public class BackupTransport {
}
/**
- * Initialize the server side storage for this device, erasing all stored data.
- * The transport may send the request immediately, or may buffer it. After
- * this is called, {@link #finishBackup} will be called to ensure the request
- * is sent and received successfully.
- *
- * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far) or
- * {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure).
- */
- public int initializeDevice() {
- return BackupConstants.TRANSPORT_ERROR;
- }
-
- /**
* Send one application's key/value data update to the backup destination. The
* transport may send the data immediately, or may buffer it. After this is called,
* {@link #finishBackup} will be called to ensure the data is sent and recorded successfully.
@@ -143,37 +176,13 @@ public class BackupTransport {
* must be erased prior to the storage of the data provided here. The purpose of this
* is to provide a guarantee that no stale data exists in the restore set when the
* device begins providing incremental backups.
- * @return one of {@link BackupConstants#TRANSPORT_OK} (OK so far),
- * {@link BackupConstants#TRANSPORT_ERROR} (on network error or other failure), or
- * {@link BackupConstants#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has
+ * @return one of {@link BackupTransport#TRANSPORT_OK} (OK so far),
+ * {@link BackupTransport#TRANSPORT_ERROR} (on network error or other failure), or
+ * {@link BackupTransport#TRANSPORT_NOT_INITIALIZED} (if the backend dataset has
* become lost due to inactivity purge or some other reason and needs re-initializing)
*/
public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor inFd) {
- return BackupConstants.TRANSPORT_ERROR;
- }
-
- /**
- * Erase the give application's data from the backup destination. This clears
- * out the given package's data from the current backup set, making it as though
- * the app had never yet been backed up. After this is called, {@link finishBackup}
- * must be called to ensure that the operation is recorded successfully.
- *
- * @return the same error codes as {@link #performBackup}.
- */
- public int clearBackupData(PackageInfo packageInfo) {
- return BackupConstants.TRANSPORT_ERROR;
- }
-
- /**
- * Finish sending application data to the backup destination. This must be
- * called after {@link #performBackup} or {@link clearBackupData} to ensure that
- * all data is sent. Only when this method returns true can a backup be assumed
- * to have succeeded.
- *
- * @return the same error codes as {@link #performBackup}.
- */
- public int finishBackup() {
- return BackupConstants.TRANSPORT_ERROR;
+ return BackupTransport.TRANSPORT_ERROR;
}
// ------------------------------------------------------------------------------------
@@ -210,12 +219,12 @@ public class BackupTransport {
* or {@link #getCurrentRestoreSet}.
* @param packages List of applications to restore (if data is available).
* Application data will be restored in the order given.
- * @return One of {@link BackupConstants#TRANSPORT_OK} (OK so far, call
- * {@link #nextRestorePackage}) or {@link BackupConstants#TRANSPORT_ERROR}
+ * @return One of {@link BackupTransport#TRANSPORT_OK} (OK so far, call
+ * {@link #nextRestorePackage}) or {@link BackupTransport#TRANSPORT_ERROR}
* (an error occurred, the restore should be aborted and rescheduled).
*/
public int startRestore(long token, PackageInfo[] packages) {
- return BackupConstants.TRANSPORT_ERROR;
+ return BackupTransport.TRANSPORT_ERROR;
}
/**
@@ -235,7 +244,7 @@ public class BackupTransport {
* @return the same error codes as {@link #startRestore}.
*/
public int getRestoreData(ParcelFileDescriptor outFd) {
- return BackupConstants.TRANSPORT_ERROR;
+ return BackupTransport.TRANSPORT_ERROR;
}
/**
@@ -247,6 +256,78 @@ public class BackupTransport {
"Transport finishRestore() not implemented");
}
+ // ------------------------------------------------------------------------------------
+ // Full backup interfaces
+
+ /**
+ * Verify that this is a suitable time for a full-data backup pass. This should return zero
+ * if a backup is reasonable right now, some positive value otherwise. This method
+ * will be called outside of the {@link #performFullBackup}/{@link #finishBackup} pair.
+ *
+ * <p>If this is not a suitable time for a backup, the transport should return a
+ * backoff delay, in milliseconds, after which the Backup Manager should try again.
+ *
+ * @return Zero if this is a suitable time for a backup pass, or a positive time delay
+ * in milliseconds to suggest deferring the backup pass for a while.
+ *
+ * @see #requestBackupTime()
+ */
+ public long requestFullBackupTime() {
+ return 0;
+ }
+
+ /**
+ * Begin the process of sending an application's full-data archive to the backend.
+ * The description of the package whose data will be delivered is provided, as well as
+ * the socket file descriptor on which the transport will receive the data itself.
+ *
+ * <p>If the package is not eligible for backup, the transport should return
+ * {@link BackupTransport#TRANSPORT_PACKAGE_REJECTED}. In this case the system will
+ * simply proceed with the next candidate if any, or finish the full backup operation
+ * if all apps have been processed.
+ *
+ * <p>After the transport returns {@link BackupTransport#TRANSPORT_OK} from this
+ * method, the OS will proceed to call {@link #sendBackupData()} one or more times
+ * to deliver the application's data as a streamed tarball. The transport should not
+ * read() from the socket except as instructed to via the {@link #sendBackupData(int)}
+ * method.
+ *
+ * <p>After all data has been delivered to the transport, the system will call
+ * {@link #finishBackup()}. At this point the transport should commit the data to
+ * its datastore, if appropriate, and close the socket that had been provided in
+ * {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}.
+ *
+ * @param targetPackage The package whose data is to follow.
+ * @param socket The socket file descriptor through which the data will be provided.
+ * If the transport returns {@link #TRANSPORT_PACKAGE_REJECTED} here, it must still
+ * close this file descriptor now; otherwise it should be cached for use during
+ * succeeding calls to {@link #sendBackupData(int)}, and closed in response to
+ * {@link #finishBackup()}.
+ * @return TRANSPORT_PACKAGE_REJECTED to indicate that the stated application is not
+ * to be backed up; TRANSPORT_OK to indicate that the OS may proceed with delivering
+ * backup data; TRANSPORT_ERROR to indicate a fatal error condition that precludes
+ * performing a backup at this time.
+ */
+ public int performFullBackup(PackageInfo targetPackage, ParcelFileDescriptor socket) {
+ return BackupTransport.TRANSPORT_PACKAGE_REJECTED;
+ }
+
+ /**
+ * Tells the transport to read {@code numBytes} bytes of data from the socket file
+ * descriptor provided in the {@link #performFullBackup(PackageInfo, ParcelFileDescriptor)}
+ * call, and deliver those bytes to the datastore.
+ *
+ * @param numBytes The number of bytes of tarball data available to be read from the
+ * socket.
+ * @return TRANSPORT_OK on successful processing of the data; TRANSPORT_ERROR to
+ * indicate a fatal error situation. If an error is returned, the system will
+ * call finishBackup() and stop attempting backups until after a backoff and retry
+ * interval.
+ */
+ public int sendBackupData(int numBytes) {
+ return BackupTransport.TRANSPORT_ERROR;
+ }
+
/**
* Bridge between the actual IBackupTransport implementation and the stable API. If the
* binder interface needs to change, we use this layer to translate so that we can
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 7642e13..392bfbc 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1839,19 +1839,6 @@ public abstract class ContentResolver {
}
/**
- * Cancel any active or pending syncs that are running on this service.
- *
- * @param cname the service for which to cancel all active/pending operations.
- */
- public static void cancelSync(ComponentName cname) {
- try {
- getContentService().cancelSync(null, null, cname);
- } catch (RemoteException e) {
-
- }
- }
-
- /**
* Get information about the SyncAdapters that are known to the system.
* @return an array of SyncAdapters that have registered with the system
*/
@@ -1991,13 +1978,13 @@ public abstract class ContentResolver {
/**
* Remove the specified sync. This will cancel any pending or active syncs. If the request is
* for a periodic sync, this call will remove any future occurrences.
- * <p>If a periodic sync is specified, the caller must hold the permission
- * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}. If this SyncRequest targets a
- * SyncService adapter,the calling application must be signed with the same certificate as the
- * adapter.
- *</p>It is possible to cancel a sync using a SyncRequest object that is not the same object
+ * <p>
+ * If a periodic sync is specified, the caller must hold the permission
+ * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
+ *</p>
+ * It is possible to cancel a sync using a SyncRequest object that is not the same object
* with which you requested the sync. Do so by building a SyncRequest with the same
- * service/adapter, frequency, <b>and</b> extras bundle.
+ * adapter, frequency, <b>and</b> extras bundle.
*
* @param request SyncRequest object containing information about sync to cancel.
*/
@@ -2031,22 +2018,6 @@ public abstract class ContentResolver {
}
/**
- * Return periodic syncs associated with the provided component.
- * <p>The calling application must be signed with the same certificate as the target component,
- * otherwise this call will fail.
- */
- public static List<PeriodicSync> getPeriodicSyncs(ComponentName cname) {
- if (cname == null) {
- throw new IllegalArgumentException("Component must not be null");
- }
- try {
- return getContentService().getPeriodicSyncs(null, null, cname);
- } catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
- }
- }
-
- /**
* Check if this account/provider is syncable.
* <p>This method requires the caller to hold the permission
* {@link android.Manifest.permission#READ_SYNC_SETTINGS}.
@@ -2076,38 +2047,6 @@ public abstract class ContentResolver {
}
/**
- * Set whether the provided {@link SyncService} is available to process work.
- * <p>This method requires the caller to hold the permission
- * {@link android.Manifest.permission#WRITE_SYNC_SETTINGS}.
- * <p>The calling application must be signed with the same certificate as the target component,
- * otherwise this call will fail.
- */
- public static void setServiceActive(ComponentName cname, boolean active) {
- try {
- getContentService().setServiceActive(cname, active);
- } catch (RemoteException e) {
- // exception ignored; if this is thrown then it means the runtime is in the midst of
- // being restarted
- }
- }
-
- /**
- * Query the state of this sync service.
- * <p>Set with {@link #setServiceActive(ComponentName cname, boolean active)}.
- * <p>The calling application must be signed with the same certificate as the target component,
- * otherwise this call will fail.
- * @param cname ComponentName referring to a {@link SyncService}
- * @return true if jobs will be run on this service, false otherwise.
- */
- public static boolean isServiceActive(ComponentName cname) {
- try {
- return getContentService().isServiceActive(cname);
- } catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
- }
- }
-
- /**
* Gets the master auto-sync setting that applies to all the providers and accounts.
* If this is false then the per-provider auto-sync setting is ignored.
* <p>This method requires the caller to hold the permission
@@ -2164,17 +2103,6 @@ public abstract class ContentResolver {
}
}
- public static boolean isSyncActive(ComponentName cname) {
- if (cname == null) {
- throw new IllegalArgumentException("component name must not be null");
- }
- try {
- return getContentService().isSyncActive(null, null, cname);
- } catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
- }
- }
-
/**
* If a sync is active returns the information about it, otherwise returns null.
* <p>
@@ -2249,14 +2177,6 @@ public abstract class ContentResolver {
}
}
- public static boolean isSyncPending(ComponentName cname) {
- try {
- return getContentService().isSyncPending(null, null, cname);
- } catch (RemoteException e) {
- throw new RuntimeException("the ContentService should always be reachable", e);
- }
- }
-
/**
* Request notifications when the different aspects of the SyncManager change. The
* different items that can be requested are:
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c69e669..a040efb 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2751,11 +2751,11 @@ public abstract class Context {
/**
* Use with {@link #getSystemService} to retrieve a
- * {@link android.tv.TvInputManager} for interacting with TV inputs on the
- * device.
+ * {@link android.media.tv.TvInputManager} for interacting with TV inputs
+ * on the device.
*
* @see #getSystemService
- * @see android.tv.TvInputManager
+ * @see android.media.tv.TvInputManager
*/
public static final String TV_INPUT_SERVICE = "tv_input";
diff --git a/core/java/android/content/IContentService.aidl b/core/java/android/content/IContentService.aidl
index 73a76e8..373f2fb 100644
--- a/core/java/android/content/IContentService.aidl
+++ b/core/java/android/content/IContentService.aidl
@@ -121,19 +121,6 @@ interface IContentService {
*/
void setIsSyncable(in Account account, String providerName, int syncable);
- /**
- * Corresponds roughly to setIsSyncable(String account, String provider) for syncs that bind
- * to a SyncService.
- */
- void setServiceActive(in ComponentName cname, boolean active);
-
- /**
- * Corresponds roughly to getIsSyncable(String account, String provider) for syncs that bind
- * to a SyncService.
- * @return 0 if this SyncService is not enabled, 1 if enabled, <0 if unknown.
- */
- boolean isServiceActive(in ComponentName cname);
-
void setMasterSyncAutomatically(boolean flag);
boolean getMasterSyncAutomatically();
diff --git a/core/java/android/content/PeriodicSync.java b/core/java/android/content/PeriodicSync.java
index 836c6f8..3efd89a 100644
--- a/core/java/android/content/PeriodicSync.java
+++ b/core/java/android/content/PeriodicSync.java
@@ -29,14 +29,10 @@ public class PeriodicSync implements Parcelable {
public final Account account;
/** The authority of the sync. Can be null. */
public final String authority;
- /** The service for syncing, if this is an anonymous sync. Can be null.*/
- public final ComponentName service;
/** Any extras that parameters that are to be passed to the sync adapter. */
public final Bundle extras;
/** How frequently the sync should be scheduled, in seconds. Kept around for API purposes. */
public final long period;
- /** Whether this periodic sync runs on a {@link SyncService}. */
- public final boolean isService;
/**
* How much flexibility can be taken in scheduling the sync, in seconds.
* {@hide}
@@ -44,16 +40,11 @@ public class PeriodicSync implements Parcelable {
public final long flexTime;
/**
- * Creates a new PeriodicSync, copying the Bundle. SM no longer uses this ctor - kept around
- * becuse it is part of the API.
- * Note - even calls to the old API will not use this ctor, as
- * they are given a default flex time.
+ * Creates a new PeriodicSync, copying the Bundle. This constructor is no longer used.
*/
public PeriodicSync(Account account, String authority, Bundle extras, long periodInSeconds) {
this.account = account;
this.authority = authority;
- this.service = null;
- this.isService = false;
if (extras == null) {
this.extras = new Bundle();
} else {
@@ -71,8 +62,6 @@ public class PeriodicSync implements Parcelable {
public PeriodicSync(PeriodicSync other) {
this.account = other.account;
this.authority = other.authority;
- this.service = other.service;
- this.isService = other.isService;
this.extras = new Bundle(other.extras);
this.period = other.period;
this.flexTime = other.flexTime;
@@ -86,40 +75,14 @@ public class PeriodicSync implements Parcelable {
long period, long flexTime) {
this.account = account;
this.authority = authority;
- this.service = null;
- this.isService = false;
- this.extras = new Bundle(extras);
- this.period = period;
- this.flexTime = flexTime;
- }
-
- /**
- * A PeriodicSync for a sync with a specified SyncService.
- * {@hide}
- */
- public PeriodicSync(ComponentName service, Bundle extras,
- long period,
- long flexTime) {
- this.account = null;
- this.authority = null;
- this.service = service;
- this.isService = true;
this.extras = new Bundle(extras);
this.period = period;
this.flexTime = flexTime;
}
private PeriodicSync(Parcel in) {
- this.isService = (in.readInt() != 0);
- if (this.isService) {
- this.service = in.readParcelable(null);
- this.account = null;
- this.authority = null;
- } else {
- this.account = in.readParcelable(null);
- this.authority = in.readString();
- this.service = null;
- }
+ this.account = in.readParcelable(null);
+ this.authority = in.readString();
this.extras = in.readBundle();
this.period = in.readLong();
this.flexTime = in.readLong();
@@ -132,13 +95,8 @@ public class PeriodicSync implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(isService ? 1 : 0);
- if (account == null && authority == null) {
- dest.writeParcelable(service, flags);
- } else {
- dest.writeParcelable(account, flags);
- dest.writeString(authority);
- }
+ dest.writeParcelable(account, flags);
+ dest.writeString(authority);
dest.writeBundle(extras);
dest.writeLong(period);
dest.writeLong(flexTime);
@@ -165,24 +123,14 @@ public class PeriodicSync implements Parcelable {
return false;
}
final PeriodicSync other = (PeriodicSync) o;
- if (this.isService != other.isService) {
- return false;
- }
- boolean equal = false;
- if (this.isService) {
- equal = service.equals(other.service);
- } else {
- equal = account.equals(other.account)
- && authority.equals(other.authority);
- }
- return equal
- && period == other.period
- && syncExtrasEquals(extras, other.extras);
+ return account.equals(other.account)
+ && authority.equals(other.authority)
+ && period == other.period
+ && syncExtrasEquals(extras, other.extras);
}
/**
- * Periodic sync extra comparison function. Duplicated from
- * {@link com.android.server.content.SyncManager#syncExtrasEquals(Bundle b1, Bundle b2)}
+ * Periodic sync extra comparison function.
* {@hide}
*/
public static boolean syncExtrasEquals(Bundle b1, Bundle b2) {
@@ -207,7 +155,6 @@ public class PeriodicSync implements Parcelable {
public String toString() {
return "account: " + account +
", authority: " + authority +
- ", service: " + service +
". period: " + period + "s " +
", flex: " + flexTime;
}
diff --git a/core/java/android/content/SyncInfo.java b/core/java/android/content/SyncInfo.java
index 146dd99..a586d6f 100644
--- a/core/java/android/content/SyncInfo.java
+++ b/core/java/android/content/SyncInfo.java
@@ -28,24 +28,16 @@ public class SyncInfo implements Parcelable {
public final int authorityId;
/**
- * The {@link Account} that is currently being synced. Will be null if this sync is running via
- * a {@link SyncService}.
+ * The {@link Account} that is currently being synced.
*/
public final Account account;
/**
- * The authority of the provider that is currently being synced. Will be null if this sync
- * is running via a {@link SyncService}.
+ * The authority of the provider that is currently being synced.
*/
public final String authority;
/**
- * The {@link SyncService} that is targeted by this operation. Null if this sync is running via
- * a {@link AbstractThreadedSyncAdapter}.
- */
- public final ComponentName service;
-
- /**
* The start time of the current sync operation in milliseconds since boot.
* This is represented in elapsed real time.
* See {@link android.os.SystemClock#elapsedRealtime()}.
@@ -53,13 +45,11 @@ public class SyncInfo implements Parcelable {
public final long startTime;
/** @hide */
- public SyncInfo(int authorityId, Account account, String authority, ComponentName service,
- long startTime) {
+ public SyncInfo(int authorityId, Account account, String authority, long startTime) {
this.authorityId = authorityId;
this.account = account;
this.authority = authority;
this.startTime = startTime;
- this.service = service;
}
/** @hide */
@@ -68,7 +58,6 @@ public class SyncInfo implements Parcelable {
this.account = new Account(other.account.name, other.account.type);
this.authority = other.authority;
this.startTime = other.startTime;
- this.service = other.service;
}
/** @hide */
@@ -82,8 +71,6 @@ public class SyncInfo implements Parcelable {
parcel.writeParcelable(account, flags);
parcel.writeString(authority);
parcel.writeLong(startTime);
- parcel.writeParcelable(service, flags);
-
}
/** @hide */
@@ -92,7 +79,6 @@ public class SyncInfo implements Parcelable {
account = parcel.readParcelable(Account.class.getClassLoader());
authority = parcel.readString();
startTime = parcel.readLong();
- service = parcel.readParcelable(ComponentName.class.getClassLoader());
}
/** @hide */
diff --git a/core/java/android/content/SyncRequest.java b/core/java/android/content/SyncRequest.java
index 9ba45ca..869f85c 100644
--- a/core/java/android/content/SyncRequest.java
+++ b/core/java/android/content/SyncRequest.java
@@ -27,23 +27,11 @@ public class SyncRequest implements Parcelable {
private final Account mAccountToSync;
/** Authority string that corresponds to a ContentProvider. */
private final String mAuthority;
- /** {@link SyncService} identifier. */
- private final ComponentName mComponentInfo;
/** Bundle containing user info as well as sync settings. */
private final Bundle mExtras;
/** Don't allow this sync request on metered networks. */
private final boolean mDisallowMetered;
/**
- * Anticipated upload size in bytes.
- * TODO: Not yet used - we put this information into the bundle for simplicity.
- */
- private final long mTxBytes;
- /**
- * Anticipated download size in bytes.
- * TODO: Not yet used - we put this information into the bundle.
- */
- private final long mRxBytes;
- /**
* Amount of time before {@link #mSyncRunTimeSecs} from which the sync may optionally be
* started.
*/
@@ -75,25 +63,12 @@ public class SyncRequest implements Parcelable {
/**
* {@hide}
- * @return true if this sync uses an account/authority pair, or false if
- * this is an anonymous sync bound to an @link AnonymousSyncService.
- */
- public boolean hasAuthority() {
- return mIsAuthority;
- }
-
- /**
- * {@hide}
*
* @return account object for this sync.
* @throws IllegalArgumentException if this function is called for a request that targets a
* sync service.
*/
public Account getAccount() {
- if (!hasAuthority()) {
- throw new IllegalArgumentException("Cannot getAccount() for a sync that targets a sync"
- + "service.");
- }
return mAccountToSync;
}
@@ -105,30 +80,11 @@ public class SyncRequest implements Parcelable {
* sync service.
*/
public String getProvider() {
- if (!hasAuthority()) {
- throw new IllegalArgumentException("Cannot getProvider() for a sync that targets a"
- + "sync service.");
- }
return mAuthority;
}
/**
* {@hide}
- * Throws a runtime IllegalArgumentException if this function is called for a
- * SyncRequest that is bound to an account/provider.
- *
- * @return ComponentName for the service that this sync will bind to.
- */
- public ComponentName getService() {
- if (hasAuthority()) {
- throw new IllegalArgumentException(
- "Cannot getAnonymousService() for a sync that has specified a provider.");
- }
- return mComponentInfo;
- }
-
- /**
- * {@hide}
* Retrieve bundle for this SyncRequest. Will not be null.
*/
public Bundle getBundle() {
@@ -175,16 +131,10 @@ public class SyncRequest implements Parcelable {
parcel.writeLong(mSyncRunTimeSecs);
parcel.writeInt((mIsPeriodic ? 1 : 0));
parcel.writeInt((mDisallowMetered ? 1 : 0));
- parcel.writeLong(mTxBytes);
- parcel.writeLong(mRxBytes);
parcel.writeInt((mIsAuthority ? 1 : 0));
parcel.writeInt((mIsExpedited? 1 : 0));
- if (mIsAuthority) {
- parcel.writeParcelable(mAccountToSync, flags);
- parcel.writeString(mAuthority);
- } else {
- parcel.writeParcelable(mComponentInfo, flags);
- }
+ parcel.writeParcelable(mAccountToSync, flags);
+ parcel.writeString(mAuthority);
}
private SyncRequest(Parcel in) {
@@ -193,19 +143,10 @@ public class SyncRequest implements Parcelable {
mSyncRunTimeSecs = in.readLong();
mIsPeriodic = (in.readInt() != 0);
mDisallowMetered = (in.readInt() != 0);
- mTxBytes = in.readLong();
- mRxBytes = in.readLong();
mIsAuthority = (in.readInt() != 0);
mIsExpedited = (in.readInt() != 0);
- if (mIsAuthority) {
- mComponentInfo = null;
- mAccountToSync = in.readParcelable(null);
- mAuthority = in.readString();
- } else {
- mComponentInfo = in.readParcelable(null);
- mAccountToSync = null;
- mAuthority = null;
- }
+ mAccountToSync = in.readParcelable(null);
+ mAuthority = in.readString();
}
/** {@hide} Protected ctor to instantiate anonymous SyncRequest. */
@@ -214,7 +155,6 @@ public class SyncRequest implements Parcelable {
mSyncRunTimeSecs = b.mSyncRunTimeSecs;
mAccountToSync = b.mAccount;
mAuthority = b.mAuthority;
- mComponentInfo = b.mComponentName;
mIsPeriodic = (b.mSyncType == Builder.SYNC_TYPE_PERIODIC);
mIsAuthority = (b.mSyncTarget == Builder.SYNC_TARGET_ADAPTER);
mIsExpedited = b.mExpedited;
@@ -223,8 +163,6 @@ public class SyncRequest implements Parcelable {
// TODO: pass the configuration extras through separately.
mExtras.putAll(b.mSyncConfigExtras);
mDisallowMetered = b.mDisallowMetered;
- mTxBytes = b.mTxBytes;
- mRxBytes = b.mRxBytes;
}
/**
@@ -240,8 +178,6 @@ public class SyncRequest implements Parcelable {
private static final int SYNC_TYPE_ONCE = 2;
/** Unknown sync target. */
private static final int SYNC_TARGET_UNKNOWN = 0;
- /** Specify that this is an anonymous sync. */
- private static final int SYNC_TARGET_SERVICE = 1;
/** Specify that this is a sync with a provider. */
private static final int SYNC_TARGET_ADAPTER = 2;
/**
@@ -275,7 +211,7 @@ public class SyncRequest implements Parcelable {
* Whether this builder is building a periodic sync, or a one-time sync.
*/
private int mSyncType = SYNC_TYPE_UNKNOWN;
- /** Whether this will go to a sync adapter or to a sync service. */
+ /** Whether this will go to a sync adapter. */
private int mSyncTarget = SYNC_TARGET_UNKNOWN;
/** Whether this is a user-activated sync. */
private boolean mIsManual;
@@ -298,12 +234,6 @@ public class SyncRequest implements Parcelable {
private boolean mExpedited;
/**
- * The {@link SyncService} component that
- * contains the sync logic if this is a provider-less sync, otherwise
- * null.
- */
- private ComponentName mComponentName;
- /**
* The Account object that together with an Authority name define the SyncAdapter (if
* this sync is bound to a provider), otherwise null.
*/
@@ -336,7 +266,7 @@ public class SyncRequest implements Parcelable {
/**
* Build a periodic sync. Either this or syncOnce() <b>must</b> be called for this builder.
- * Syncs are identified by target {@link SyncService}/{@link android.provider} and by the
+ * Syncs are identified by target {@link android.provider} and by the
* contents of the extras bundle.
* You cannot reuse the same builder for one-time syncs after having specified a periodic
* sync (by calling this function). If you do, an <code>IllegalArgumentException</code>
@@ -395,23 +325,10 @@ public class SyncRequest implements Parcelable {
}
/**
- * Developer can provide insight into their payload size; optional. -1 specifies unknown,
- * so that you are not restricted to defining both fields.
- *
- * @param rxBytes Bytes expected to be downloaded.
- * @param txBytes Bytes expected to be uploaded.
- */
- public Builder setTransferSize(long rxBytes, long txBytes) {
- mRxBytes = rxBytes;
- mTxBytes = txBytes;
- return this;
- }
-
- /**
* Will throw an <code>IllegalArgumentException</code> if called and
* {@link #setIgnoreSettings(boolean ignoreSettings)} has already been called.
* @param disallow true to allow this transfer on metered networks. Default false.
- *
+ *
*/
public Builder setDisallowMetered(boolean disallow) {
if (mIgnoreSettings && disallow) {
@@ -423,10 +340,9 @@ public class SyncRequest implements Parcelable {
}
/**
- * Specify an authority and account for this transfer. Cannot be used with
- * {@link #setSyncAdapter(ComponentName cname)}.
+ * Specify an authority and account for this transfer.
*
- * @param authority
+ * @param authority A String identifying the content provider to be synced.
* @param account Account to sync. Can be null unless this is a periodic
* sync, for which verification by the ContentResolver will
* fail. If a sync is performed without an account, the
@@ -441,25 +357,6 @@ public class SyncRequest implements Parcelable {
mSyncTarget = SYNC_TARGET_ADAPTER;
mAccount = account;
mAuthority = authority;
- mComponentName = null;
- return this;
- }
-
- /**
- * Specify the {@link SyncService} component for this sync. This is not validated until
- * sync time so providing an incorrect component name here will not fail. Cannot be used
- * with {@link #setSyncAdapter(Account account, String authority)}.
- *
- * @param cname ComponentName to identify your Anonymous service
- */
- public Builder setSyncAdapter(ComponentName cname) {
- if (mSyncTarget != SYNC_TARGET_UNKNOWN) {
- throw new IllegalArgumentException("Sync target has already been defined.");
- }
- mSyncTarget = SYNC_TARGET_SERVICE;
- mComponentName = cname;
- mAccount = null;
- mAuthority = null;
return this;
}
@@ -630,25 +527,17 @@ public class SyncRequest implements Parcelable {
mSyncConfigExtras.putInt(ContentResolver.SYNC_EXTRAS_PRIORITY, mPriority);
if (mSyncType == SYNC_TYPE_PERIODIC) {
// If this is a periodic sync ensure than invalid extras were not set.
- if (ContentResolver.invalidPeriodicExtras(mCustomExtras) ||
+ if (ContentResolver.invalidPeriodicExtras(mCustomExtras) ||
ContentResolver.invalidPeriodicExtras(mSyncConfigExtras)) {
throw new IllegalArgumentException("Illegal extras were set");
}
- } else if (mSyncType == SYNC_TYPE_UNKNOWN) {
- throw new IllegalArgumentException("Must call either syncOnce() or syncPeriodic()");
- }
- if (mSyncTarget == SYNC_TARGET_SERVICE) {
- if (mSyncConfigExtras.getBoolean(ContentResolver.SYNC_EXTRAS_INITIALIZE, false)) {
- throw new IllegalArgumentException("Cannot specify an initialisation sync"
- + " that targets a service.");
- }
}
// Ensure that a target for the sync has been set.
if (mSyncTarget == SYNC_TARGET_UNKNOWN) {
- throw new IllegalArgumentException("Must specify an adapter with one of"
- + "setSyncAdapter(ComponentName) or setSyncAdapter(Account, String");
+ throw new IllegalArgumentException("Must specify an adapter with" +
+ " setSyncAdapter(Account, String");
}
return new SyncRequest(this);
}
- }
+ }
}
diff --git a/core/java/android/content/SyncService.java b/core/java/android/content/SyncService.java
deleted file mode 100644
index 4df998c..0000000
--- a/core/java/android/content/SyncService.java
+++ /dev/null
@@ -1,211 +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.content;
-
-import android.app.Service;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Process;
-import android.os.Trace;
-import android.util.SparseArray;
-import android.util.Log;
-
-import com.android.internal.annotations.GuardedBy;
-
-/**
- * Simplified @link android.content.AbstractThreadedSyncAdapter. Folds that
- * behaviour into a service to which the system can bind when requesting an
- * anonymous (providerless/accountless) sync.
- * <p>
- * In order to perform an anonymous sync operation you must extend this service, implementing the
- * abstract methods. This service must be declared in the application's manifest as usual. You
- * can use this service for other work, however you <b> must not </b> override the onBind() method
- * unless you know what you're doing, which limits the usefulness of this service for other work.
- * <p>A {@link SyncService} can either be active or inactive. Different to an
- * {@link AbstractThreadedSyncAdapter}, there is no
- * {@link ContentResolver#setSyncAutomatically(android.accounts.Account account, String provider, boolean sync)},
- * as well as no concept of initialisation (you can handle your own if needed).
- *
- * <pre>
- * &lt;service android:name=".MySyncService"/&gt;
- * </pre>
- * Like @link android.content.AbstractThreadedSyncAdapter this service supports
- * multiple syncs at the same time. Each incoming startSync() with a unique tag
- * will spawn a thread to do the work of that sync. If startSync() is called
- * with a tag that already exists, a SyncResult.ALREADY_IN_PROGRESS is returned.
- * Remember that your service will spawn multiple threads if you schedule multiple syncs
- * at once, so if you mutate local objects you must ensure synchronization.
- */
-public abstract class SyncService extends Service {
- private static final String TAG = "SyncService";
-
- private final SyncAdapterImpl mSyncAdapter = new SyncAdapterImpl();
-
- /** Keep track of on-going syncs, keyed by bundle. */
- @GuardedBy("mSyncThreadLock")
- private final SparseArray<SyncThread>
- mSyncThreads = new SparseArray<SyncThread>();
- /** Lock object for accessing the SyncThreads HashMap. */
- private final Object mSyncThreadLock = new Object();
- /**
- * Default key for if this sync service does not support parallel operations. Currently not
- * sure if null keys will make it into the ArrayMap for KLP, so keeping our default for now.
- */
- private static final int KEY_DEFAULT = 0;
- /** Identifier for this sync service. */
- private ComponentName mServiceComponent;
-
- /** {@hide} */
- public IBinder onBind(Intent intent) {
- mServiceComponent = new ComponentName(this, getClass());
- return mSyncAdapter.asBinder();
- }
-
- /** {@hide} */
- private class SyncAdapterImpl extends ISyncServiceAdapter.Stub {
- @Override
- public void startSync(ISyncContext syncContext, Bundle extras) {
- // Wrap the provided Sync Context because it may go away by the time
- // we call it.
- final SyncContext syncContextClient = new SyncContext(syncContext);
- boolean alreadyInProgress = false;
- final int extrasAsKey = extrasToKey(extras);
- synchronized (mSyncThreadLock) {
- if (mSyncThreads.get(extrasAsKey) == null) {
- if (Log.isLoggable(TAG, Log.VERBOSE)) {
- Log.v(TAG, "starting sync for : " + mServiceComponent);
- }
- // Start sync.
- SyncThread syncThread = new SyncThread(syncContextClient, extras);
- mSyncThreads.put(extrasAsKey, syncThread);
- syncThread.start();
- } else {
- // Don't want to call back to SyncManager while still
- // holding lock.
- alreadyInProgress = true;
- }
- }
- if (alreadyInProgress) {
- syncContextClient.onFinished(SyncResult.ALREADY_IN_PROGRESS);
- }
- }
-
- /**
- * Used by the SM to cancel a specific sync using the
- * com.android.server.content.SyncManager.ActiveSyncContext as a handle.
- */
- @Override
- public void cancelSync(ISyncContext syncContext) {
- SyncThread runningSync = null;
- synchronized (mSyncThreadLock) {
- for (int i = 0; i < mSyncThreads.size(); i++) {
- SyncThread thread = mSyncThreads.valueAt(i);
- if (thread.mSyncContext.getSyncContextBinder() == syncContext.asBinder()) {
- runningSync = thread;
- break;
- }
- }
- }
- if (runningSync != null) {
- runningSync.interrupt();
- }
- }
- }
-
- /**
- *
- * @param extras Bundle for which to compute hash
- * @return an integer hash that is equal to that of another bundle if they both contain the
- * same key -> value mappings, however, not necessarily in order.
- * Based on the toString() representation of the value mapped.
- */
- private int extrasToKey(Bundle extras) {
- int hash = KEY_DEFAULT; // Empty bundle, or no parallel operations enabled.
- if (parallelSyncsEnabled()) {
- for (String key : extras.keySet()) {
- String mapping = key + " " + extras.get(key).toString();
- hash += mapping.hashCode();
- }
- }
- return hash;
- }
-
- /**
- * {@hide}
- * Similar to {@link android.content.AbstractThreadedSyncAdapter.SyncThread}. However while
- * the ATSA considers an already in-progress sync to be if the account provided is currently
- * syncing, this anonymous sync has no notion of account and considers a sync unique if the
- * provided bundle is different.
- */
- private class SyncThread extends Thread {
- private final SyncContext mSyncContext;
- private final Bundle mExtras;
- private final int mThreadsKey;
-
- public SyncThread(SyncContext syncContext, Bundle extras) {
- mSyncContext = syncContext;
- mExtras = extras;
- mThreadsKey = extrasToKey(extras);
- }
-
- @Override
- public void run() {
- Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
-
- Trace.traceBegin(Trace.TRACE_TAG_SYNC_MANAGER, getApplication().getPackageName());
-
- SyncResult syncResult = new SyncResult();
- try {
- if (isCancelled()) return;
- // Run the sync.
- SyncService.this.onPerformSync(mExtras, syncResult);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_SYNC_MANAGER);
- if (!isCancelled()) {
- mSyncContext.onFinished(syncResult);
- }
- // Synchronize so that the assignment will be seen by other
- // threads that also synchronize accesses to mSyncThreads.
- synchronized (mSyncThreadLock) {
- mSyncThreads.remove(mThreadsKey);
- }
- }
- }
-
- private boolean isCancelled() {
- return Thread.currentThread().isInterrupted();
- }
- }
-
- /**
- * Initiate an anonymous sync using this service. SyncAdapter-specific
- * parameters may be specified in extras, which is guaranteed to not be
- * null.
- */
- public abstract void onPerformSync(Bundle extras, SyncResult syncResult);
-
- /**
- * Override this function to indicated whether you want to support parallel syncs.
- * <p>If you override and return true multiple threads will be spawned within your Service to
- * handle each concurrent sync request.
- *
- * @return false to indicate that this service does not support parallel operations by default.
- */
- protected boolean parallelSyncsEnabled() {
- return false;
- }
-}
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 44a6a5d..70668e1 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -433,6 +433,13 @@ interface IPackageManager {
in VerificationParams verificationParams,
in ContainerEncryptionParams encryptionParams);
+ void installPackageWithVerificationEncryptionAndAbiOverrideEtc(in Uri packageURI,
+ in IPackageInstallObserver observer, in IPackageInstallObserver2 observer2,
+ int flags, in String installerPackageName,
+ in VerificationParams verificationParams,
+ in ContainerEncryptionParams encryptionParams,
+ in String packageAbiOverride);
+
int installExistingPackageAsUser(String packageName, int userId);
void verifyPendingInstall(int id, int verificationCode);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index c5cd5c9..31bf465 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -520,7 +520,7 @@ public abstract class PackageManager {
* Installation return code: this is passed to the {@link IPackageInstallObserver} by
* {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
* the package being installed contains native code, but none that is
- * compatible with the the device's CPU_ABI.
+ * compatible with the device's CPU_ABI.
* @hide
*/
@PrivateApi
@@ -3454,7 +3454,7 @@ public abstract class PackageManager {
/**
- * Return the the enabled setting for a package component (activity,
+ * Return the enabled setting for a package component (activity,
* receiver, service, provider). This returns the last value set by
* {@link #setComponentEnabledSetting(ComponentName, int, int)}; in most
* cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since
@@ -3492,14 +3492,14 @@ public abstract class PackageManager {
int newState, int flags);
/**
- * Return the the enabled setting for an application. This returns
+ * Return the enabled setting for an application. This returns
* the last value set by
* {@link #setApplicationEnabledSetting(String, int, int)}; in most
* cases this value will be {@link #COMPONENT_ENABLED_STATE_DEFAULT} since
* the value originally specified in the manifest has not been modified.
*
- * @param packageName The component to retrieve.
- * @return Returns the current enabled state for the component. May
+ * @param packageName The package name of the application to retrieve.
+ * @return Returns the current enabled state for the application. May
* be one of {@link #COMPONENT_ENABLED_STATE_ENABLED},
* {@link #COMPONENT_ENABLED_STATE_DISABLED}, or
* {@link #COMPONENT_ENABLED_STATE_DEFAULT}. The last one means the
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index 3737638..9625578 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -702,12 +702,17 @@ public class Resources {
* Context.obtainStyledAttributes} with
* an array containing the resource ID of interest to create the TypedArray.</p>
*
+ * <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
+ * {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
+ * or {@link #getDrawable(int, Theme)} passing the desired theme.</p>
+ *
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
* entry. The value 0 is an invalid identifier.
* @return Drawable An object that can be used to draw this resource.
* @throws NotFoundException Throws NotFoundException if the given ID does
* not exist.
+ * @see #getDrawable(int, Theme)
*/
public Drawable getDrawable(int id) throws NotFoundException {
return getDrawable(id, null);
@@ -715,7 +720,9 @@ public class Resources {
/**
* Return a drawable object associated with a particular resource ID and
- * styled for the specified theme.
+ * styled for the specified theme. Various types of objects will be
+ * returned depending on the underlying resource -- for example, a solid
+ * color, PNG image, scalable image, etc.
*
* @param id The desired resource identifier, as generated by the aapt
* tool. This integer encodes the package, type, and resource
@@ -755,6 +762,11 @@ public class Resources {
* image, scalable image, etc. The Drawable API hides these implementation
* details.
*
+ * <p class="note"><strong>Note:</strong> To obtain a themed drawable, use
+ * {@link android.content.Context#getDrawable(int) Context.getDrawable(int)}
+ * or {@link #getDrawableForDensity(int, int, Theme)} passing the desired
+ * theme.</p>
+ *
* @param id The desired resource identifier, as generated by the aapt tool.
* This integer encodes the package, type, and resource entry.
* The value 0 is an invalid identifier.
@@ -2227,9 +2239,7 @@ public class Resources {
}
// First, check whether we have a cached version of this drawable
- // that's valid for the specified theme. This may apply a theme to a
- // cached drawable that has themeable attributes but was not previously
- // themed.
+ // that was inflated against the specified theme.
if (!mPreloading) {
final Drawable cachedDrawable = getCachedDrawable(caches, key, theme);
if (cachedDrawable != null) {
@@ -2255,8 +2265,8 @@ public class Resources {
dr = loadDrawableForCookie(value, id, theme);
}
- // If we were able to obtain a drawable, attempt to place it in the
- // appropriate cache (e.g. no theme, themed, themeable).
+ // If we were able to obtain a drawable, store it in the appropriate
+ // cache (either preload or themed).
if (dr != null) {
dr.setChangingConfigurations(value.changingConfigurations);
cacheDrawable(value, theme, isColorDrawable, caches, key, dr);
@@ -2340,12 +2350,12 @@ public class Resources {
if (file.endsWith(".xml")) {
final XmlResourceParser rp = loadXmlResourceParser(
file, id, value.assetCookie, "drawable");
- dr = Drawable.createFromXmlThemed(this, rp, theme);
+ dr = Drawable.createFromXml(this, rp, theme);
rp.close();
} else {
final InputStream is = mAssets.openNonAsset(
value.assetCookie, file, AssetManager.ACCESS_STREAMING);
- dr = Drawable.createFromResourceStreamThemed(this, value, is, file, null, theme);
+ dr = Drawable.createFromResourceStream(this, value, is, file, null);
is.close();
}
} catch (Exception e) {
@@ -2364,7 +2374,7 @@ public class Resources {
ArrayMap<String, LongSparseArray<WeakReference<ConstantState>>> caches,
long key, Theme theme) {
synchronized (mAccessLock) {
- final int themeKey = theme != null ? theme.mThemeResId : 0;
+ final String themeKey = theme != null ? theme.mKey : "";
final LongSparseArray<WeakReference<ConstantState>> themedCache = caches.get(themeKey);
if (themedCache != null) {
final Drawable themedDrawable = getCachedDrawableLocked(themedCache, key);
diff --git a/core/java/android/hardware/camera2/CameraCaptureSession.java b/core/java/android/hardware/camera2/CameraCaptureSession.java
index 7738d2d..5fd0f9b 100644
--- a/core/java/android/hardware/camera2/CameraCaptureSession.java
+++ b/core/java/android/hardware/camera2/CameraCaptureSession.java
@@ -54,7 +54,7 @@ import java.util.List;
public abstract class CameraCaptureSession implements AutoCloseable {
/**
- * Get the camera device that this session is created for
+ * Get the camera device that this session is created for.
*/
public abstract CameraDevice getDevice();
@@ -90,8 +90,9 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
- * @throws IllegalStateException if this session is no longer active, either because a new
- * session has been created or the camera device has been closed.
+ * @throws IllegalStateException if this session is no longer active, either because the session
+ * was explicitly closed, a new session has been created
+ * or the camera device has been closed.
* @throws IllegalArgumentException if the request targets Surfaces that are not configured as
* outputs for this session. Or if the handler is null, the
* listener is not null, and the calling thread has no looper.
@@ -99,6 +100,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* @see #captureBurst
* @see #setRepeatingRequest
* @see #setRepeatingBurst
+ * @see #abortCaptures
*/
public abstract int capture(CaptureRequest request, CaptureListener listener, Handler handler)
throws CameraAccessException;
@@ -132,8 +134,9 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
- * @throws IllegalStateException if this session is no longer active, either because a new
- * session has been created or the camera device has been closed.
+ * @throws IllegalStateException if this session is no longer active, either because the session
+ * was explicitly closed, a new session has been created
+ * or the camera device has been closed.
* @throws IllegalArgumentException If the requests target Surfaces not currently configured as
* outputs. Or if the handler is null, the listener is not
* null, and the calling thread has no looper.
@@ -141,6 +144,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* @see #capture
* @see #setRepeatingRequest
* @see #setRepeatingBurst
+ * @see #abortCaptures
*/
public abstract int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException;
@@ -188,11 +192,13 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
- * @throws IllegalStateException if this session is no longer active, either because a new
- * session has been created or the camera device has been closed.
+ * @throws IllegalStateException if this session is no longer active, either because the session
+ * was explicitly closed, a new session has been created
+ * or the camera device has been closed.
* @throws IllegalArgumentException If the requests reference Surfaces that are not currently
* configured as outputs. Or if the handler is null, the
* listener is not null, and the calling thread has no looper.
+ * Or if no requests were passed in.
*
* @see #capture
* @see #captureBurst
@@ -246,11 +252,13 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
- * @throws IllegalStateException if this session is no longer active, either because a new
- * session has been created or the camera device has been closed.
+ * @throws IllegalStateException if this session is no longer active, either because the session
+ * was explicitly closed, a new session has been created
+ * or the camera device has been closed.
* @throws IllegalArgumentException If the requests reference Surfaces not currently configured
* as outputs. Or if the handler is null, the listener is not
- * null, and the calling thread has no looper.
+ * null, and the calling thread has no looper. Or if no
+ * requests were passed in.
*
* @see #capture
* @see #captureBurst
@@ -274,8 +282,9 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
- * @throws IllegalStateException if this session is no longer active, either because a new
- * session has been created or the camera device has been closed.
+ * @throws IllegalStateException if this session is no longer active, either because the session
+ * was explicitly closed, a new session has been created
+ * or the camera device has been closed.
*
* @see #setRepeatingRequest
* @see #setRepeatingBurst
@@ -308,8 +317,9 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* @throws CameraAccessException if the camera device is no longer connected or has
* encountered a fatal error
- * @throws IllegalStateException if this session is no longer active, either because a new
- * session has been created or the camera device has been closed.
+ * @throws IllegalStateException if this session is no longer active, either because the session
+ * was explicitly closed, a new session has been created
+ * or the camera device has been closed.
*
* @see #setRepeatingRequest
* @see #setRepeatingBurst
@@ -320,8 +330,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
/**
* Close this capture session asynchronously.
*
- * <p>Closing a session frees up the target output Surfaces of the session for reuse with either a
- * new session, or to other APIs that can draw to Surfaces.</p>
+ * <p>Closing a session frees up the target output Surfaces of the session for reuse with either
+ * a new session, or to other APIs that can draw to Surfaces.</p>
*
* <p>Note that creating a new capture session with {@link CameraDevice#createCaptureSession}
* will close any existing capture session automatically, and call the older session listener's
@@ -334,6 +344,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* However, any in-progress capture requests submitted to the session will be completed as
* normal; once all captures have completed and the session has been torn down,
* {@link StateListener#onClosed} will be called.</p>
+ *
+ * <p>Closing a session is idempotent; closing more than once has no effect.</p>
*/
@Override
public abstract void close();
@@ -358,6 +370,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* <p>If the camera device configuration fails, then {@link #onConfigureFailed} will
* be invoked instead of this callback.</p>
*
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
*/
public abstract void onConfigured(CameraCaptureSession session);
@@ -371,6 +384,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* callback is invoked will throw an IllegalStateException. Any capture requests submitted
* to the session prior to this callback will be discarded and will not produce any
* callbacks on their listeners.</p>
+ *
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
*/
public abstract void onConfigureFailed(CameraCaptureSession session);
@@ -384,6 +399,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* <p>Otherwise, this callback will be invoked any time the session finishes processing
* all of its active capture requests, and no repeating request or burst is set up.</p>
*
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
+ *
*/
public void onReady(CameraCaptureSession session) {
// default empty implementation
@@ -398,6 +415,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>If the session runs out of capture requests to process and calls {@link #onReady},
* then this callback will be invoked again once new requests are submitted for capture.</p>
+ *
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
*/
public void onActive(CameraCaptureSession session) {
// default empty implementation
@@ -414,6 +433,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* any repeating requests or bursts are stopped (as if {@link #stopRepeating()} was called).
* However, any in-progress capture requests submitted to the session will be completed
* as normal.</p>
+ *
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
*/
public void onClosed(CameraCaptureSession session) {
// default empty implementation
@@ -466,13 +487,13 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>The default implementation of this method does nothing.</p>
*
- * @param camera the CameraDevice sending the callback
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
* @param request the request for the capture that just begun
* @param timestamp the timestamp at start of capture, in nanoseconds.
*
* @see android.media.MediaActionSound
*/
- public void onCaptureStarted(CameraDevice camera,
+ public void onCaptureStarted(CameraCaptureSession session,
CaptureRequest request, long timestamp) {
// default empty implementation
}
@@ -490,7 +511,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>The default implementation of this method does nothing.</p>
*
- * @param camera The CameraDevice sending the callback.
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
* @param request The request that was given to the CameraDevice
* @param result The partial output metadata from the capture, which
* includes a subset of the CaptureResult fields.
@@ -502,7 +523,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* @hide
*/
- public void onCapturePartial(CameraDevice camera,
+ public void onCapturePartial(CameraCaptureSession session,
CaptureRequest request, CaptureResult result) {
// default empty implementation
}
@@ -533,7 +554,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>The default implementation of this method does nothing.</p>
*
- * @param camera The CameraDevice sending the callback.
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
* @param request The request that was given to the CameraDevice
* @param partialResult The partial output metadata from the capture, which
* includes a subset of the {@link TotalCaptureResult} fields.
@@ -543,7 +564,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* @see #setRepeatingRequest
* @see #setRepeatingBurst
*/
- public void onCaptureProgressed(CameraDevice camera,
+ public void onCaptureProgressed(CameraCaptureSession session,
CaptureRequest request, CaptureResult partialResult) {
// default empty implementation
}
@@ -561,7 +582,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>The default implementation of this method does nothing.</p>
*
- * @param camera The CameraDevice sending the callback.
+ * @param session the session returned by {@link CameraDevice#createCaptureSession}
* @param request The request that was given to the CameraDevice
* @param result The total output metadata from the capture, including the
* final capture parameters and the state of the camera system during
@@ -572,7 +593,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* @see #setRepeatingRequest
* @see #setRepeatingBurst
*/
- public void onCaptureCompleted(CameraDevice camera,
+ public void onCaptureCompleted(CameraCaptureSession session,
CaptureRequest request, TotalCaptureResult result) {
// default empty implementation
}
@@ -588,8 +609,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>The default implementation of this method does nothing.</p>
*
- * @param camera
- * The CameraDevice sending the callback.
+ * @param session
+ * The session returned by {@link CameraDevice#createCaptureSession}
* @param request
* The request that was given to the CameraDevice
* @param failure
@@ -601,7 +622,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* @see #setRepeatingRequest
* @see #setRepeatingBurst
*/
- public void onCaptureFailed(CameraDevice camera,
+ public void onCaptureFailed(CameraCaptureSession session,
CaptureRequest request, CaptureFailure failure) {
// default empty implementation
}
@@ -617,8 +638,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>The default implementation does nothing.</p>
*
- * @param camera
- * The CameraDevice sending the callback.
+ * @param session
+ * The session returned by {@link CameraDevice#createCaptureSession}
* @param sequenceId
* A sequence ID returned by the {@link #capture} family of functions.
* @param frameNumber
@@ -631,7 +652,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* @see CaptureFailure#getSequenceId()
* @see #onCaptureSequenceAborted
*/
- public void onCaptureSequenceCompleted(CameraDevice camera,
+ public void onCaptureSequenceCompleted(CameraCaptureSession session,
int sequenceId, long frameNumber) {
// default empty implementation
}
@@ -649,8 +670,8 @@ public abstract class CameraCaptureSession implements AutoCloseable {
*
* <p>The default implementation does nothing.</p>
*
- * @param camera
- * The CameraDevice sending the callback.
+ * @param session
+ * The session returned by {@link CameraDevice#createCaptureSession}
* @param sequenceId
* A sequence ID returned by the {@link #capture} family of functions.
*
@@ -660,7 +681,7 @@ public abstract class CameraCaptureSession implements AutoCloseable {
* @see CaptureFailure#getSequenceId()
* @see #onCaptureSequenceCompleted
*/
- public void onCaptureSequenceAborted(CameraDevice camera,
+ public void onCaptureSequenceAborted(CameraCaptureSession session,
int sequenceId) {
// default empty implementation
}
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 2f5b4fe..222374a 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -810,6 +810,7 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* {@link CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL android.info.supportedHardwareLevel} <code>==</code> FULL devices:</p>
* <ul>
* <li>MANUAL_SENSOR</li>
+ * <li>MANUAL_POST_PROCESSING</li>
* </ul>
* <p>Other capabilities may be available on either FULL or LIMITED
* devices, but the app. should query this field to be sure.</p>
@@ -1033,8 +1034,6 @@ public final class CameraCharacteristics extends CameraMetadata<CameraCharacteri
* (i.e. format, width, height, output/input stream).</p>
* <p>The configurations are listed as <code>(format, width, height, input?)</code>
* tuples.</p>
- * <p>All camera devices will support sensor maximum resolution (defined by
- * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE android.sensor.info.activeArraySize}) for the JPEG format.</p>
* <p>For a given use case, the actual maximum supported resolution
* may be lower than what is listed here, depending on the destination
* Surface for the image data. For example, for recording video,
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 6f5099b..e9213c5 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -24,7 +24,7 @@ import android.view.Surface;
import java.util.List;
/**
- * <p>The CameraDevice class is an interface to a single camera connected to an
+ * <p>The CameraDevice class is a representation of a single camera connected to an
* Android device, allowing for fine-grain control of image capture and
* post-processing at high frame rates.</p>
*
@@ -46,7 +46,7 @@ import java.util.List;
* @see CameraManager#openCamera
* @see android.Manifest.permission#CAMERA
*/
-public interface CameraDevice extends AutoCloseable {
+public abstract class CameraDevice implements AutoCloseable {
/**
* Create a request suitable for a camera preview window. Specifically, this
@@ -127,7 +127,7 @@ public interface CameraDevice extends AutoCloseable {
* @see CameraManager#getCameraCharacteristics
* @see CameraManager#getCameraIdList
*/
- public String getId();
+ public abstract String getId();
/**
* <p>Set up a new output set of Surfaces for the camera device.</p>
@@ -244,7 +244,8 @@ public interface CameraDevice extends AutoCloseable {
* @see StreamConfigurationMap#getOutputSizes(Class)
* @deprecated Use {@link #createCaptureSession} instead
*/
- public void configureOutputs(List<Surface> outputs) throws CameraAccessException;
+ @Deprecated
+ public abstract void configureOutputs(List<Surface> outputs) throws CameraAccessException;
/**
* <p>Create a new camera capture session by providing the target output set of Surfaces to the
@@ -357,7 +358,7 @@ public interface CameraDevice extends AutoCloseable {
* @see StreamConfigurationMap#getOutputSizes(int)
* @see StreamConfigurationMap#getOutputSizes(Class)
*/
- public void createCaptureSession(List<Surface> outputs,
+ public abstract void createCaptureSession(List<Surface> outputs,
CameraCaptureSession.StateListener listener, Handler handler)
throws CameraAccessException;
@@ -386,7 +387,7 @@ public interface CameraDevice extends AutoCloseable {
* @see #TEMPLATE_VIDEO_SNAPSHOT
* @see #TEMPLATE_MANUAL
*/
- public CaptureRequest.Builder createCaptureRequest(int templateType)
+ public abstract CaptureRequest.Builder createCaptureRequest(int templateType)
throws CameraAccessException;
/**
@@ -432,7 +433,8 @@ public interface CameraDevice extends AutoCloseable {
* @see #setRepeatingBurst
* @deprecated Use {@link CameraCaptureSession} instead
*/
- public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
+ @Deprecated
+ public abstract int capture(CaptureRequest request, CaptureListener listener, Handler handler)
throws CameraAccessException;
/**
@@ -470,14 +472,16 @@ public interface CameraDevice extends AutoCloseable {
* or the camera device has been closed.
* @throws IllegalArgumentException If the requests target Surfaces not
* currently configured as outputs. Or if the handler is null, the listener
- * is not null, and the calling thread has no looper.
+ * is not null, and the calling thread has no looper. Or if no requests were
+ * passed in.
*
* @see #capture
* @see #setRepeatingRequest
* @see #setRepeatingBurst
* @deprecated Use {@link CameraCaptureSession} instead
*/
- public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+ @Deprecated
+ public abstract int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException;
/**
@@ -536,7 +540,8 @@ public interface CameraDevice extends AutoCloseable {
* @see #flush
* @deprecated Use {@link CameraCaptureSession} instead
*/
- public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+ @Deprecated
+ public abstract int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
Handler handler) throws CameraAccessException;
/**
@@ -586,7 +591,8 @@ public interface CameraDevice extends AutoCloseable {
* or the camera device has been closed.
* @throws IllegalArgumentException If the requests reference Surfaces not
* currently configured as outputs. Or if the handler is null, the listener
- * is not null, and the calling thread has no looper.
+ * is not null, and the calling thread has no looper. Or if no requests were
+ * passed in.
*
* @see #capture
* @see #captureBurst
@@ -595,7 +601,8 @@ public interface CameraDevice extends AutoCloseable {
* @see #flush
* @deprecated Use {@link CameraCaptureSession} instead
*/
- public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
+ @Deprecated
+ public abstract int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException;
/**
@@ -620,7 +627,8 @@ public interface CameraDevice extends AutoCloseable {
* @see StateListener#onIdle
* @deprecated Use {@link CameraCaptureSession} instead
*/
- public void stopRepeating() throws CameraAccessException;
+ @Deprecated
+ public abstract void stopRepeating() throws CameraAccessException;
/**
* Flush all captures currently pending and in-progress as fast as
@@ -657,7 +665,8 @@ public interface CameraDevice extends AutoCloseable {
* @see #configureOutputs
* @deprecated Use {@link CameraCaptureSession} instead
*/
- public void flush() throws CameraAccessException;
+ @Deprecated
+ public abstract void flush() throws CameraAccessException;
/**
* Close the connection to this camera device as quickly as possible.
@@ -675,7 +684,7 @@ public interface CameraDevice extends AutoCloseable {
*
*/
@Override
- public void close();
+ public abstract void close();
/**
* <p>A listener for tracking the progress of a {@link CaptureRequest}
@@ -691,6 +700,7 @@ public interface CameraDevice extends AutoCloseable {
* @see #setRepeatingBurst
* @deprecated Use {@link CameraCaptureSession} instead
*/
+ @Deprecated
public static abstract class CaptureListener {
/**
@@ -1042,6 +1052,7 @@ public interface CameraDevice extends AutoCloseable {
* @param camera the camera device has that become unconfigured
* @deprecated Use {@link CameraCaptureSession.StateListener} instead.
*/
+ @Deprecated
public void onUnconfigured(CameraDevice camera) {
// Default empty implementation
}
@@ -1072,6 +1083,7 @@ public interface CameraDevice extends AutoCloseable {
* @see CameraDevice#setRepeatingRequest
* @deprecated Use {@link CameraCaptureSession.StateListener} instead.
*/
+ @Deprecated
public void onActive(CameraDevice camera) {
// Default empty implementation
}
@@ -1106,6 +1118,7 @@ public interface CameraDevice extends AutoCloseable {
* @see CameraDevice#flush
* @deprecated Use {@link CameraCaptureSession.StateListener} instead.
*/
+ @Deprecated
public void onBusy(CameraDevice camera) {
// Default empty implementation
}
@@ -1154,6 +1167,7 @@ public interface CameraDevice extends AutoCloseable {
* @see CameraDevice#flush
* @deprecated Use {@link CameraCaptureSession.StateListener} instead.
*/
+ @Deprecated
public void onIdle(CameraDevice camera) {
// Default empty implementation
}
@@ -1216,4 +1230,10 @@ public interface CameraDevice extends AutoCloseable {
*/
public abstract void onError(CameraDevice camera, int error); // Must implement
}
+
+ /**
+ * To be inherited by android.hardware.camera2.* code only.
+ * @hide
+ */
+ public CameraDevice() {}
}
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 4a89fe7..781301e 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -227,8 +227,8 @@ public final class CameraManager {
ICameraDeviceUser cameraUser;
- android.hardware.camera2.impl.CameraDevice deviceImpl =
- new android.hardware.camera2.impl.CameraDevice(
+ android.hardware.camera2.impl.CameraDeviceImpl deviceImpl =
+ new android.hardware.camera2.impl.CameraDeviceImpl(
cameraId,
listener,
handler,
diff --git a/core/java/android/hardware/camera2/DngCreator.java b/core/java/android/hardware/camera2/DngCreator.java
index 54568ed..3e3303c 100644
--- a/core/java/android/hardware/camera2/DngCreator.java
+++ b/core/java/android/hardware/camera2/DngCreator.java
@@ -22,12 +22,16 @@ import android.hardware.camera2.impl.CameraMetadataNative;
import android.location.Location;
import android.media.ExifInterface;
import android.media.Image;
+import android.os.SystemClock;
import android.util.Size;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.TimeZone;
/**
* The {@link DngCreator} class provides functions to write raw pixel data as a DNG file.
@@ -55,6 +59,7 @@ import java.nio.ByteBuffer;
*/
public final class DngCreator implements AutoCloseable {
+ private static final String TAG = "DngCreator";
/**
* Create a new DNG object.
*
@@ -75,7 +80,25 @@ public final class DngCreator implements AutoCloseable {
if (characteristics == null || metadata == null) {
throw new NullPointerException("Null argument to DngCreator constructor");
}
- nativeInit(characteristics.getNativeCopy(), metadata.getNativeCopy());
+
+ // Find current time
+ long currentTime = System.currentTimeMillis();
+
+ // Find boot time
+ long bootTimeMillis = currentTime - SystemClock.elapsedRealtime();
+
+ // Find capture time (nanos since boot)
+ Long timestamp = metadata.get(CaptureResult.SENSOR_TIMESTAMP);
+ long captureTime = currentTime;
+ if (timestamp != null) {
+ captureTime = timestamp / 1000000 + bootTimeMillis;
+ }
+
+ // Format for metadata
+ String formattedCaptureTime = sDateTimeStampFormat.format(captureTime);
+
+ nativeInit(characteristics.getNativeCopy(), metadata.getNativeCopy(),
+ formattedCaptureTime);
}
/**
@@ -98,6 +121,7 @@ public final class DngCreator implements AutoCloseable {
* <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_270}</li>
* </ul>
* @return this {@link #DngCreator} object.
+ * @hide
*/
public DngCreator setOrientation(int orientation) {
@@ -124,6 +148,7 @@ public final class DngCreator implements AutoCloseable {
*
* @param pixels a {@link android.graphics.Bitmap} of pixel data.
* @return this {@link #DngCreator} object.
+ * @hide
*/
public DngCreator setThumbnail(Bitmap pixels) {
if (pixels == null) {
@@ -157,6 +182,7 @@ public final class DngCreator implements AutoCloseable {
* @param pixels an {@link android.media.Image} object with the format
* {@link android.graphics.ImageFormat#YUV_420_888}.
* @return this {@link #DngCreator} object.
+ * @hide
*/
public DngCreator setThumbnail(Image pixels) {
if (pixels == null) {
@@ -193,6 +219,7 @@ public final class DngCreator implements AutoCloseable {
*
* @throws java.lang.IllegalArgumentException if the given location object doesn't
* contain enough information to set location metadata.
+ * @hide
*/
public DngCreator setLocation(Location location) {
/*TODO*/
@@ -208,6 +235,7 @@ public final class DngCreator implements AutoCloseable {
*
* @param description the user description string.
* @return this {@link #DngCreator} object.
+ * @hide
*/
public DngCreator setDescription(String description) {
/*TODO*/
@@ -240,6 +268,7 @@ public final class DngCreator implements AutoCloseable {
* @throws java.lang.IllegalStateException if not enough metadata information has been
* set to write a well-formatted DNG file.
* @throws java.lang.IllegalArgumentException if the size passed in does not match the
+ * @hide
*/
public void writeInputStream(OutputStream dngOutput, Size size, InputStream pixels, long offset)
throws IOException {
@@ -274,6 +303,7 @@ public final class DngCreator implements AutoCloseable {
* @throws IOException if an error was encountered in the input or output stream.
* @throws java.lang.IllegalStateException if not enough metadata information has been
* set to write a well-formatted DNG file.
+ * @hide
*/
public void writeByteBuffer(OutputStream dngOutput, Size size, ByteBuffer pixels, long offset)
throws IOException {
@@ -329,6 +359,13 @@ public final class DngCreator implements AutoCloseable {
}
}
+ private static final String TIFF_DATETIME_FORMAT = "yyyy:MM:dd kk:mm:ss";
+ private static final DateFormat sDateTimeStampFormat =
+ new SimpleDateFormat(TIFF_DATETIME_FORMAT);
+
+ static {
+ sDateTimeStampFormat.setTimeZone(TimeZone.getDefault());
+ }
/**
* This field is used by native code, do not access or modify.
*/
@@ -337,7 +374,8 @@ public final class DngCreator implements AutoCloseable {
private static native void nativeClassInit();
private synchronized native void nativeInit(CameraMetadataNative nativeCharacteristics,
- CameraMetadataNative nativeResult);
+ CameraMetadataNative nativeResult,
+ String captureTime);
private synchronized native void nativeDestroy();
diff --git a/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java b/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java
new file mode 100644
index 0000000..866f370
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/ArgumentReplacingDispatcher.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * A dispatcher that replaces one argument with another; replaces any argument at an index
+ * with another argument.
+ *
+ * <p>For example, we can override an {@code void onSomething(int x)} calls to have {@code x} always
+ * equal to 1. Or, if using this with a duck typing dispatcher, we could even overwrite {@code x} to
+ * be something
+ * that's not an {@code int}.</p>
+ *
+ * @param <T>
+ * source dispatch type, whose methods with {@link #dispatch} will be called
+ * @param <TArg>
+ * argument replacement type, args in {@link #dispatch} matching {@code argumentIndex}
+ * will be overriden to objects of this type
+ */
+public class ArgumentReplacingDispatcher<T, TArg> implements Dispatchable<T> {
+
+ private final Dispatchable<T> mTarget;
+ private final int mArgumentIndex;
+ private final TArg mReplaceWith;
+
+ /**
+ * Create a new argument replacing dispatcher; dispatches are forwarded to {@code target}
+ * after the argument is replaced.
+ *
+ * <p>For example, if a method {@code onAction(T1 a, Integer b, T2 c)} is invoked, and we wanted
+ * to replace all occurrences of {@code b} with {@code 0xDEADBEEF}, we would set
+ * {@code argumentIndex = 1} and {@code replaceWith = 0xDEADBEEF}.</p>
+ *
+ * <p>If a method dispatched has less arguments than {@code argumentIndex}, it is
+ * passed through with the arguments unchanged.</p>
+ *
+ * @param target destination dispatch type, methods will be redirected to this dispatcher
+ * @param argumentIndex the numeric index of the argument {@code >= 0}
+ * @param replaceWith arguments matching {@code argumentIndex} will be replaced with this object
+ */
+ public ArgumentReplacingDispatcher(Dispatchable<T> target, int argumentIndex,
+ TArg replaceWith) {
+ mTarget = checkNotNull(target, "target must not be null");
+ mArgumentIndex = checkArgumentNonnegative(argumentIndex,
+ "argumentIndex must not be negative");
+ mReplaceWith = checkNotNull(replaceWith, "replaceWith must not be null");
+ }
+
+ @Override
+ public Object dispatch(Method method, Object[] args) throws Throwable {
+
+ if (args.length > mArgumentIndex) {
+ args = arrayCopy(args); // don't change in-place since it can affect upstream dispatches
+ args[mArgumentIndex] = mReplaceWith;
+ }
+
+ return mTarget.dispatch(method, args);
+ }
+
+ private static Object[] arrayCopy(Object[] array) {
+ int length = array.length;
+ Object[] newArray = new Object[length];
+ for (int i = 0; i < length; ++i) {
+ newArray[i] = array[i];
+ }
+ return newArray;
+ }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java b/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java
new file mode 100644
index 0000000..fe575b2
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/BroadcastDispatcher.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Broadcast a single dispatch into multiple other dispatchables.
+ *
+ * <p>Every time {@link #dispatch} is invoked, all the broadcast targets will
+ * see the same dispatch as well. The first target's return value is returned.</p>
+ *
+ * <p>This enables a single listener to be converted into a multi-listener.</p>
+ */
+public class BroadcastDispatcher<T> implements Dispatchable<T> {
+
+ private final List<Dispatchable<T>> mDispatchTargets;
+
+ /**
+ * Create a broadcast dispatcher from the supplied dispatch targets.
+ *
+ * @param dispatchTargets one or more targets to dispatch to
+ */
+ @SafeVarargs
+ public BroadcastDispatcher(Dispatchable<T>... dispatchTargets) {
+ mDispatchTargets = Arrays.asList(
+ checkNotNull(dispatchTargets, "dispatchTargets must not be null"));
+ }
+
+ @Override
+ public Object dispatch(Method method, Object[] args) throws Throwable {
+ Object result = null;
+ boolean gotResult = false;
+
+ for (Dispatchable<T> dispatchTarget : mDispatchTargets) {
+ Object localResult = dispatchTarget.dispatch(method, args);
+
+ if (!gotResult) {
+ gotResult = true;
+ result = localResult;
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/Dispatchable.java b/core/java/android/hardware/camera2/dispatch/Dispatchable.java
new file mode 100644
index 0000000..753103f
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/Dispatchable.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+import java.lang.reflect.Method;
+
+/**
+ * Dynamically dispatch a method and its argument to some object.
+ *
+ * <p>This can be used to intercept method calls and do work around them, redirect work,
+ * or block calls entirely.</p>
+ */
+public interface Dispatchable<T> {
+ /**
+ * Dispatch the method and arguments to this object.
+ * @param method a method defined in class {@code T}
+ * @param args arguments corresponding to said {@code method}
+ * @return the object returned when invoking {@code method}
+ * @throws Throwable any exception that might have been raised while invoking the method
+ */
+ public Object dispatch(Method method, Object[] args) throws Throwable;
+}
diff --git a/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java b/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java
new file mode 100644
index 0000000..75f97e4
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/DuckTypingDispatcher.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Duck typing dispatcher; converts dispatch methods calls from one class to another by
+ * looking up equivalently methods at runtime by name.
+ *
+ * <p>For example, if two types have identical method names and arguments, but
+ * are not subclasses/subinterfaces of each other, this dispatcher will allow calls to be
+ * made from one type to the other.</p>
+ *
+ * @param <TFrom> source dispatch type, whose methods with {@link #dispatch} will be called
+ * @param <T> destination dispatch type, methods will be converted to the class of {@code T}
+ */
+public class DuckTypingDispatcher<TFrom, T> implements Dispatchable<TFrom> {
+
+ private final MethodNameInvoker<T> mDuck;
+
+ /**
+ * Create a new duck typing dispatcher.
+ *
+ * @param target destination dispatch type, methods will be redirected to this dispatcher
+ * @param targetClass destination dispatch class, methods will be converted to this class's
+ */
+ public DuckTypingDispatcher(Dispatchable<T> target, Class<T> targetClass) {
+ checkNotNull(targetClass, "targetClass must not be null");
+ checkNotNull(target, "target must not be null");
+
+ mDuck = new MethodNameInvoker<T>(target, targetClass);
+ }
+
+ @Override
+ public Object dispatch(Method method, Object[] args) {
+ return mDuck.invoke(method.getName(), args);
+ }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java b/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java
new file mode 100644
index 0000000..f8e9d49
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/HandlerDispatcher.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+import android.hardware.camera2.utils.UncheckedThrow;
+import android.os.Handler;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Forward all interface calls into a handler by posting it as a {@code Runnable}.
+ *
+ * <p>All calls will return immediately; functions with return values will return a default
+ * value of {@code null}, {@code 0}, or {@code false} where that value is legal.</p>
+ *
+ * <p>Any exceptions thrown on the handler while trying to invoke a method
+ * will be re-thrown. Throwing checked exceptions on a handler which doesn't expect any
+ * checked exceptions to be thrown will result in "undefined" behavior
+ * (although in practice it is usually thrown as normal).</p>
+ */
+public class HandlerDispatcher<T> implements Dispatchable<T> {
+
+ private static final String TAG = "HandlerDispatcher";
+
+ private final Dispatchable<T> mDispatchTarget;
+ private final Handler mHandler;
+
+ /**
+ * Create a dispatcher that forwards it's dispatch calls by posting
+ * them onto the {@code handler} as a {@code Runnable}.
+ *
+ * @param dispatchTarget the destination whose method calls will be redirected into the handler
+ * @param handler all calls into {@code dispatchTarget} will be posted onto this handler
+ * @param <T> the type of the element you want to wrap.
+ * @return a dispatcher that will forward it's dispatch calls to a handler
+ */
+ public HandlerDispatcher(Dispatchable<T> dispatchTarget, Handler handler) {
+ mDispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+ mHandler = checkNotNull(handler, "handler must not be null");
+ }
+
+ @Override
+ public Object dispatch(final Method method, final Object[] args) throws Throwable {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ mDispatchTarget.dispatch(method, args);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ // Potential UB. Hopefully 't' is a runtime exception.
+ UncheckedThrow.throwAnyException(t);
+ } catch (IllegalAccessException e) {
+ // Impossible
+ Log.wtf(TAG, "IllegalAccessException while invoking " + method, e);
+ } catch (IllegalArgumentException e) {
+ // Impossible
+ Log.wtf(TAG, "IllegalArgumentException while invoking " + method, e);
+ } catch (Throwable e) {
+ UncheckedThrow.throwAnyException(e);
+ }
+ }
+ });
+
+ // TODO handle primitive return values that would avoid NPE if unboxed
+ return null;
+ }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java b/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java
new file mode 100644
index 0000000..ac5f526
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/InvokeDispatcher.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+import android.hardware.camera2.utils.UncheckedThrow;
+import android.util.Log;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import static com.android.internal.util.Preconditions.*;
+
+
+public class InvokeDispatcher<T> implements Dispatchable<T> {
+
+ private static final String TAG = "InvocationSink";
+ private final T mTarget;
+
+ public InvokeDispatcher(T target) {
+ mTarget = checkNotNull(target, "target must not be null");
+ }
+
+ @Override
+ public Object dispatch(Method method, Object[] args) {
+ try {
+ return method.invoke(mTarget, args);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getTargetException();
+ // Potential UB. Hopefully 't' is a runtime exception.
+ UncheckedThrow.throwAnyException(t);
+ } catch (IllegalAccessException e) {
+ // Impossible
+ Log.wtf(TAG, "IllegalAccessException while invoking " + method, e);
+ } catch (IllegalArgumentException e) {
+ // Impossible
+ Log.wtf(TAG, "IllegalArgumentException while invoking " + method, e);
+ }
+
+ // unreachable
+ return null;
+ }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
new file mode 100644
index 0000000..02c3d87
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/MethodNameInvoker.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+import android.hardware.camera2.utils.UncheckedThrow;
+
+import java.lang.reflect.Method;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Invoke a method on a dispatchable by its name (without knowing the {@code Method} ahead of time).
+ *
+ * @param <T> destination dispatch type, methods will be looked up in the class of {@code T}
+ */
+public class MethodNameInvoker<T> {
+
+ private final Dispatchable<T> mTarget;
+ private final Class<T> mTargetClass;
+ private final ConcurrentHashMap<String, Method> mMethods =
+ new ConcurrentHashMap<>();
+
+ /**
+ * Create a new method name invoker.
+ *
+ * @param target destination dispatch type, invokes will be redirected to this dispatcher
+ * @param targetClass destination dispatch class, the invoked methods will be from this class
+ */
+ public MethodNameInvoker(Dispatchable<T> target, Class<T> targetClass) {
+ mTargetClass = targetClass;
+ mTarget = target;
+ }
+
+ /**
+ * Invoke a method by its name.
+ *
+ * <p>If more than one method exists in {@code targetClass}, the first method will be used.</p>
+ *
+ * @param methodName
+ * The name of the method, which will be matched 1:1 to the destination method
+ * @param params
+ * Variadic parameter list.
+ * @return
+ * The same kind of value that would normally be returned by calling {@code methodName}
+ * statically.
+ *
+ * @throws IllegalArgumentException if {@code methodName} does not exist on the target class
+ * @throws Throwable will rethrow anything that the target method would normally throw
+ */
+ @SuppressWarnings("unchecked")
+ public <K> K invoke(String methodName, Object... params) {
+ checkNotNull(methodName, "methodName must not be null");
+
+ Method targetMethod = mMethods.get(methodName);
+ if (targetMethod == null) {
+ for (Method method : mTargetClass.getMethods()) {
+ // TODO future: match by # of params and types of params if possible
+ if (method.getName().equals(methodName)) {
+ targetMethod = method;
+ mMethods.put(methodName, targetMethod);
+ break;
+ }
+ }
+
+ if (targetMethod == null) {
+ throw new IllegalArgumentException(
+ "Method " + methodName + " does not exist on class " + mTargetClass);
+ }
+ }
+
+ try {
+ return (K) mTarget.dispatch(targetMethod, params);
+ } catch (Throwable e) {
+ UncheckedThrow.throwAnyException(e);
+ // unreachable
+ return null;
+ }
+ }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/NullDispatcher.java b/core/java/android/hardware/camera2/dispatch/NullDispatcher.java
new file mode 100644
index 0000000..fada075
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/NullDispatcher.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.dispatch;
+
+
+import java.lang.reflect.Method;
+
+/**
+ * Do nothing when dispatching; follows the null object pattern.
+ */
+public class NullDispatcher<T> implements Dispatchable<T> {
+ /**
+ * Create a dispatcher that does nothing when dispatched to.
+ */
+ public NullDispatcher() {
+ }
+
+ /**
+ * Do nothing; all parameters are ignored.
+ */
+ @Override
+ public Object dispatch(Method method, Object[] args) {
+ return null;
+ }
+}
diff --git a/core/java/android/hardware/camera2/dispatch/package.html b/core/java/android/hardware/camera2/dispatch/package.html
new file mode 100644
index 0000000..783d0a1
--- /dev/null
+++ b/core/java/android/hardware/camera2/dispatch/package.html
@@ -0,0 +1,3 @@
+<body>
+{@hide}
+</body>
diff --git a/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
new file mode 100644
index 0000000..f74fbaa
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/CameraCaptureSessionImpl.java
@@ -0,0 +1,579 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.impl;
+
+import android.hardware.camera2.CameraAccessException;
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.dispatch.ArgumentReplacingDispatcher;
+import android.hardware.camera2.dispatch.BroadcastDispatcher;
+import android.hardware.camera2.dispatch.Dispatchable;
+import android.hardware.camera2.dispatch.DuckTypingDispatcher;
+import android.hardware.camera2.dispatch.HandlerDispatcher;
+import android.hardware.camera2.dispatch.InvokeDispatcher;
+import android.hardware.camera2.dispatch.NullDispatcher;
+import android.hardware.camera2.utils.TaskDrainer;
+import android.hardware.camera2.utils.TaskSingleDrainer;
+import android.os.Handler;
+import android.util.Log;
+import android.view.Surface;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static android.hardware.camera2.impl.CameraDeviceImpl.checkHandler;
+import static com.android.internal.util.Preconditions.*;
+
+public class CameraCaptureSessionImpl extends CameraCaptureSession {
+ private static final String TAG = "CameraCaptureSession";
+ private static final boolean VERBOSE = Log.isLoggable(TAG, Log.VERBOSE);
+
+ /** User-specified set of surfaces used as the configuration outputs */
+ private final List<Surface> mOutputs;
+ /**
+ * User-specified state listener, used for outgoing events; calls to this object will be
+ * automatically {@link Handler#post(Runnable) posted} to {@code mStateHandler}.
+ */
+ private final CameraCaptureSession.StateListener mStateListener;
+ /** User-specified state handler used for outgoing state listener events */
+ private final Handler mStateHandler;
+
+ /** Internal camera device; used to translate calls into existing deprecated API */
+ private final android.hardware.camera2.impl.CameraDeviceImpl mDeviceImpl;
+ /** Internal handler; used for all incoming events to preserve total order */
+ private final Handler mDeviceHandler;
+
+ /** Drain Sequence IDs which have been queued but not yet finished with aborted/completed */
+ private final TaskDrainer<Integer> mSequenceDrainer;
+ /** Drain state transitions from ACTIVE -> IDLE */
+ private final TaskSingleDrainer mIdleDrainer;
+ /** Drain state transitions from BUSY -> IDLE */
+ private final TaskSingleDrainer mAbortDrainer;
+ /** Drain the UNCONFIGURED state transition */
+ private final TaskSingleDrainer mUnconfigureDrainer;
+
+ /** This session is closed; all further calls will throw ISE */
+ private boolean mClosed = false;
+ /** Do not unconfigure if this is set; another session will overwrite configuration */
+ private boolean mSkipUnconfigure = false;
+
+ /** Is the session in the process of aborting? Pay attention to BUSY->IDLE transitions. */
+ private boolean mAborting;
+
+ /**
+ * Create a new CameraCaptureSession.
+ *
+ * <p>The camera device must already be in the {@code IDLE} state when this is invoked.
+ * There must be no pending actions
+ * (e.g. no pending captures, no repeating requests, no flush).</p>
+ */
+ CameraCaptureSessionImpl(List<Surface> outputs,
+ CameraCaptureSession.StateListener listener, Handler stateHandler,
+ android.hardware.camera2.impl.CameraDeviceImpl deviceImpl,
+ Handler deviceStateHandler, boolean configureSuccess) {
+ if (outputs == null || outputs.isEmpty()) {
+ throw new IllegalArgumentException("outputs must be a non-null, non-empty list");
+ } else if (listener == null) {
+ throw new IllegalArgumentException("listener must not be null");
+ }
+
+ // TODO: extra verification of outputs
+ mOutputs = outputs;
+ mStateHandler = checkHandler(stateHandler);
+ mStateListener = createUserStateListenerProxy(mStateHandler, listener);
+
+ mDeviceHandler = checkNotNull(deviceStateHandler, "deviceStateHandler must not be null");
+ mDeviceImpl = checkNotNull(deviceImpl, "deviceImpl must not be null");
+
+ /*
+ * Use the same handler as the device's StateListener for all the internal coming events
+ *
+ * This ensures total ordering between CameraDevice.StateListener and
+ * CameraDevice.CaptureListener events.
+ */
+ mSequenceDrainer = new TaskDrainer<>(mDeviceHandler, new SequenceDrainListener(),
+ /*name*/"seq");
+ mIdleDrainer = new TaskSingleDrainer(mDeviceHandler, new IdleDrainListener(),
+ /*name*/"idle");
+ mAbortDrainer = new TaskSingleDrainer(mDeviceHandler, new AbortDrainListener(),
+ /*name*/"abort");
+ mUnconfigureDrainer = new TaskSingleDrainer(mDeviceHandler, new UnconfigureDrainListener(),
+ /*name*/"unconf");
+
+ // CameraDevice should call configureOutputs and have it finish before constructing us
+
+ if (configureSuccess) {
+ mStateListener.onConfigured(this);
+ } else {
+ mStateListener.onConfigureFailed(this);
+ mClosed = true; // do not fire any other callbacks, do not allow any other work
+ }
+ }
+
+ @Override
+ public CameraDevice getDevice() {
+ return mDeviceImpl;
+ }
+
+ @Override
+ public synchronized int capture(CaptureRequest request, CaptureListener listener,
+ Handler handler) throws CameraAccessException {
+ checkNotClosed();
+ checkLegalToCapture();
+
+ handler = checkHandler(handler);
+
+ if (VERBOSE) {
+ Log.v(TAG, "capture - request " + request + ", listener " + listener + " handler" +
+ "" + handler);
+ }
+
+ return addPendingSequence(mDeviceImpl.capture(request,
+ createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ }
+
+ @Override
+ public synchronized int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
+ Handler handler) throws CameraAccessException {
+ checkNotClosed();
+ checkLegalToCapture();
+
+ handler = checkHandler(handler);
+
+ if (VERBOSE) {
+ CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
+ Log.v(TAG, "captureBurst - requests " + Arrays.toString(requestArray) + ", listener " +
+ listener + " handler" + "" + handler);
+ }
+
+ return addPendingSequence(mDeviceImpl.captureBurst(requests,
+ createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ }
+
+ @Override
+ public synchronized int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
+ Handler handler) throws CameraAccessException {
+ checkNotClosed();
+ checkLegalToCapture();
+
+ handler = checkHandler(handler);
+
+ return addPendingSequence(mDeviceImpl.setRepeatingRequest(request,
+ createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ }
+
+ @Override
+ public synchronized int setRepeatingBurst(List<CaptureRequest> requests,
+ CaptureListener listener, Handler handler) throws CameraAccessException {
+ checkNotClosed();
+ checkLegalToCapture();
+
+ handler = checkHandler(handler);
+
+ if (VERBOSE) {
+ CaptureRequest[] requestArray = requests.toArray(new CaptureRequest[0]);
+ Log.v(TAG, "setRepeatingBurst - requests " + Arrays.toString(requestArray) +
+ ", listener " + listener + " handler" + "" + handler);
+ }
+
+ return addPendingSequence(mDeviceImpl.setRepeatingBurst(requests,
+ createCaptureListenerProxy(handler, listener), mDeviceHandler));
+ }
+
+ @Override
+ public synchronized void stopRepeating() throws CameraAccessException {
+ checkNotClosed();
+
+ if (VERBOSE) {
+ Log.v(TAG, "stopRepeating");
+ }
+
+ mDeviceImpl.stopRepeating();
+ }
+
+ @Override
+ public synchronized void abortCaptures() throws CameraAccessException {
+ checkNotClosed();
+
+ if (VERBOSE) {
+ Log.v(TAG, "abortCaptures");
+ }
+
+ if (mAborting) {
+ Log.w(TAG, "abortCaptures - Session is already aborting; doing nothing");
+ return;
+ }
+
+ mAborting = true;
+ mAbortDrainer.taskStarted();
+
+ mDeviceImpl.flush();
+ // The next BUSY -> IDLE set of transitions will mark the end of the abort.
+ }
+
+ /**
+ * Replace this session with another session.
+ *
+ * <p>This is an optimization to avoid unconfiguring and then immediately having to
+ * reconfigure again.</p>
+ *
+ * <p>The semantics are identical to {@link #close}, except that unconfiguring will be skipped.
+ * <p>
+ *
+ * @see CameraCaptureSession#close
+ */
+ synchronized void replaceSessionClose(CameraCaptureSession other) {
+ /*
+ * In order for creating new sessions to be fast, the new session should be created
+ * before the old session is closed.
+ *
+ * Otherwise the old session will always unconfigure if there is no new session to
+ * replace it.
+ *
+ * Unconfiguring could add hundreds of milliseconds of delay. We could race and attempt
+ * to skip unconfigure if a new session is created before the captures are all drained,
+ * but this would introduce nondeterministic behavior.
+ */
+
+ // #close was already called explicitly, keep going the slow route
+ if (mClosed) {
+ return;
+ }
+
+ mSkipUnconfigure = true;
+ close();
+ }
+
+ @Override
+ public synchronized void close() {
+ if (mClosed) {
+ return;
+ }
+
+ mClosed = true;
+
+ /*
+ * Flush out any repeating request. Since camera is closed, no new requests
+ * can be queued, and eventually the entire request queue will be drained.
+ *
+ * Once this is done, wait for camera to idle, then unconfigure the camera.
+ * Once that's done, fire #onClosed.
+ */
+ try {
+ mDeviceImpl.stopRepeating();
+ } catch (CameraAccessException e) {
+ // OK: close does not throw checked exceptions.
+ Log.e(TAG, "Exception while stopping repeating: ", e);
+
+ // TODO: call onError instead of onClosed if this happens
+ }
+
+ // If no sequences are pending, fire #onClosed immediately
+ mSequenceDrainer.beginDrain();
+ }
+
+ /**
+ * Post calls into a CameraCaptureSession.StateListener to the user-specified {@code handler}.
+ */
+ private StateListener createUserStateListenerProxy(Handler handler, StateListener listener) {
+ InvokeDispatcher<StateListener> userListenerSink = new InvokeDispatcher<>(listener);
+ HandlerDispatcher<StateListener> handlerPassthrough =
+ new HandlerDispatcher<>(userListenerSink, handler);
+
+ return new ListenerProxies.SessionStateListenerProxy(handlerPassthrough);
+ }
+
+ /**
+ * Forward callbacks from
+ * CameraDevice.CaptureListener to the CameraCaptureSession.CaptureListener.
+ *
+ * <p>In particular, all calls are automatically split to go both to our own
+ * internal listener, and to the user-specified listener (by transparently posting
+ * to the user-specified handler).</p>
+ *
+ * <p>When a capture sequence finishes, update the pending checked sequences set.</p>
+ */
+ @SuppressWarnings("deprecation")
+ private CameraDevice.CaptureListener createCaptureListenerProxy(
+ Handler handler, CaptureListener listener) {
+ CameraDevice.CaptureListener localListener = new CameraDevice.CaptureListener() {
+ @Override
+ public void onCaptureSequenceCompleted(CameraDevice camera,
+ int sequenceId, long frameNumber) {
+ finishPendingSequence(sequenceId);
+ }
+
+ @Override
+ public void onCaptureSequenceAborted(CameraDevice camera,
+ int sequenceId) {
+ finishPendingSequence(sequenceId);
+ }
+ };
+
+ /*
+ * Split the calls from the device listener into local listener and the following chain:
+ * - replace the first CameraDevice arg with a CameraCaptureSession
+ * - duck type from device listener to session listener
+ * - then forward the call to a handler
+ * - then finally invoke the destination method on the session listener object
+ */
+ Dispatchable<CaptureListener> userListenerSink;
+ if (listener == null) { // OK: API allows the user to not specify a listener
+ userListenerSink = new NullDispatcher<>();
+ } else {
+ userListenerSink = new InvokeDispatcher<>(listener);
+ }
+
+ InvokeDispatcher<CameraDevice.CaptureListener> localSink =
+ new InvokeDispatcher<>(localListener);
+ HandlerDispatcher<CaptureListener> handlerPassthrough =
+ new HandlerDispatcher<>(userListenerSink, handler);
+ DuckTypingDispatcher<CameraDevice.CaptureListener, CaptureListener> duckToSession
+ = new DuckTypingDispatcher<>(handlerPassthrough, CaptureListener.class);
+ ArgumentReplacingDispatcher<CameraDevice.CaptureListener, CameraCaptureSessionImpl>
+ replaceDeviceWithSession = new ArgumentReplacingDispatcher<>(duckToSession,
+ /*argumentIndex*/0, this);
+
+ BroadcastDispatcher<CameraDevice.CaptureListener> broadcaster =
+ new BroadcastDispatcher<CameraDevice.CaptureListener>(
+ replaceDeviceWithSession,
+ localSink);
+
+ return new ListenerProxies.DeviceCaptureListenerProxy(broadcaster);
+ }
+
+ /**
+ *
+ * Create an internal state listener, to be invoked on the mDeviceHandler
+ *
+ * <p>It has a few behaviors:
+ * <ul>
+ * <li>Convert device state changes into session state changes.
+ * <li>Keep track of async tasks that the session began (idle, abort).
+ * </ul>
+ * </p>
+ * */
+ CameraDevice.StateListener getDeviceStateListener() {
+ final CameraCaptureSession session = this;
+
+ return new CameraDevice.StateListener() {
+ private boolean mBusy = false;
+ private boolean mActive = false;
+
+ @Override
+ public void onOpened(CameraDevice camera) {
+ throw new AssertionError("Camera must already be open before creating a session");
+ }
+
+ @Override
+ public void onDisconnected(CameraDevice camera) {
+ close();
+ }
+
+ @Override
+ public void onError(CameraDevice camera, int error) {
+ // TODO: Handle errors somehow.
+ Log.wtf(TAG, "Got device error " + error);
+ }
+
+ @Override
+ public void onActive(CameraDevice camera) {
+ mIdleDrainer.taskStarted();
+ mActive = true;
+
+ mStateListener.onActive(session);
+ }
+
+ @Override
+ public void onIdle(CameraDevice camera) {
+ boolean isAborting;
+ synchronized (session) {
+ isAborting = mAborting;
+ }
+
+ /*
+ * Check which states we transitioned through:
+ *
+ * (ACTIVE -> IDLE)
+ * (BUSY -> IDLE)
+ *
+ * Note that this is also legal:
+ * (ACTIVE -> BUSY -> IDLE)
+ *
+ * and mark those tasks as finished
+ */
+ if (mBusy && isAborting) {
+ mAbortDrainer.taskFinished();
+
+ synchronized (session) {
+ mAborting = false;
+ }
+ }
+
+ if (mActive) {
+ mIdleDrainer.taskFinished();
+ }
+
+ mBusy = false;
+ mActive = false;
+
+ mStateListener.onReady(session);
+ }
+
+ @Override
+ public void onBusy(CameraDevice camera) {
+ mBusy = true;
+
+ // TODO: Queue captures during abort instead of failing them
+ // since the app won't be able to distinguish the two actives
+ Log.w(TAG, "Device is now busy; do not submit new captures (TODO: allow this)");
+ mStateListener.onActive(session);
+ }
+
+ @Override
+ public void onUnconfigured(CameraDevice camera) {
+ mUnconfigureDrainer.taskFinished();
+ }
+ };
+
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ close();
+ } finally {
+ super.finalize();
+ }
+ }
+
+ private void checkLegalToCapture() {
+ if (mAborting) {
+ throw new IllegalStateException(
+ "Session is aborting captures; new captures are not permitted");
+ }
+ }
+
+ private void checkNotClosed() {
+ if (mClosed) {
+ throw new IllegalStateException(
+ "Session has been closed; further changes are illegal.");
+ }
+ }
+
+ /**
+ * Notify the session that a pending capture sequence has just been queued.
+ *
+ * <p>During a shutdown/close, the session waits until all pending sessions are finished
+ * before taking any further steps to shut down itself.</p>
+ *
+ * @see #finishPendingSequence
+ */
+ private int addPendingSequence(int sequenceId) {
+ mSequenceDrainer.taskStarted(sequenceId);
+ return sequenceId;
+ }
+
+ /**
+ * Notify the session that a pending capture sequence is now finished.
+ *
+ * <p>During a shutdown/close, once all pending sequences finish, it is safe to
+ * close the camera further by unconfiguring and then firing {@code onClosed}.</p>
+ */
+ private void finishPendingSequence(int sequenceId) {
+ mSequenceDrainer.taskFinished(sequenceId);
+ }
+
+ private class SequenceDrainListener implements TaskDrainer.DrainListener {
+ @Override
+ public void onDrained() {
+ /*
+ * No repeating request is set; and the capture queue has fully drained.
+ *
+ * If no captures were queued to begin with, and an abort was queued,
+ * it's still possible to get another BUSY before the last IDLE.
+ *
+ * If the camera is already "IDLE" and no aborts are pending,
+ * then the drain immediately finishes.
+ */
+ mAbortDrainer.beginDrain();
+ }
+ }
+
+ private class AbortDrainListener implements TaskDrainer.DrainListener {
+ @Override
+ public void onDrained() {
+ synchronized (CameraCaptureSessionImpl.this) {
+ /*
+ * Any queued aborts have now completed.
+ *
+ * It's now safe to wait to receive the final "IDLE" event, as the camera device
+ * will no longer again transition to "ACTIVE" by itself.
+ *
+ * If the camera is already "IDLE", then the drain immediately finishes.
+ */
+ mIdleDrainer.beginDrain();
+ }
+ }
+ }
+
+ private class IdleDrainListener implements TaskDrainer.DrainListener {
+ @Override
+ public void onDrained() {
+ synchronized (CameraCaptureSessionImpl.this) {
+ /*
+ * The device is now IDLE, and has settled. It will not transition to
+ * ACTIVE or BUSY again by itself.
+ *
+ * It's now safe to unconfigure the outputs and after it's done invoke #onClosed.
+ *
+ * This operation is idempotent; a session will not be closed twice.
+ */
+
+ // Fast path: A new capture session has replaced this one; don't unconfigure.
+ if (mSkipUnconfigure) {
+ mStateListener.onClosed(CameraCaptureSessionImpl.this);
+ return;
+ }
+
+ // Slow path: #close was called explicitly on this session; unconfigure first
+
+ try {
+ mUnconfigureDrainer.taskStarted();
+ mDeviceImpl.configureOutputs(null); // begin transition to unconfigured state
+ } catch (CameraAccessException e) {
+ // OK: do not throw checked exceptions.
+ Log.e(TAG, "Exception while configuring outputs: ", e);
+
+ // TODO: call onError instead of onClosed if this happens
+ }
+
+ mUnconfigureDrainer.beginDrain();
+ }
+ }
+ }
+
+ private class UnconfigureDrainListener implements TaskDrainer.DrainListener {
+ @Override
+ public void onDrained() {
+ synchronized (CameraCaptureSessionImpl.this) {
+ // The device has finished unconfiguring. It's now fully closed.
+ mStateListener.onClosed(CameraCaptureSessionImpl.this);
+ }
+ }
+ }
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 9a4c531..81bd2fd 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -21,7 +21,6 @@ import static android.hardware.camera2.CameraAccessException.CAMERA_IN_USE;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.ICameraDeviceCallbacks;
@@ -48,7 +47,7 @@ import java.util.TreeSet;
/**
* HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
*/
-public class CameraDevice implements android.hardware.camera2.CameraDevice {
+public class CameraDeviceImpl extends android.hardware.camera2.CameraDevice {
private final String TAG;
private final boolean DEBUG;
@@ -62,10 +61,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
private final CameraDeviceCallbacks mCallbacks = new CameraDeviceCallbacks();
private final StateListener mDeviceListener;
+ private volatile StateListener mSessionStateListener;
private final Handler mDeviceHandler;
private boolean mIdle = true;
+ /** map request IDs to listener/request data */
private final SparseArray<CaptureListenerHolder> mCaptureListenerMap =
new SparseArray<CaptureListenerHolder>();
@@ -90,14 +91,20 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
*/
private final FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker();
+ private CameraCaptureSessionImpl mCurrentSession;
+
// Runnables for all state transitions, except error, which needs the
// error code argument
private final Runnable mCallOnOpened = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
- mDeviceListener.onOpened(CameraDevice.this);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ mDeviceListener.onOpened(CameraDeviceImpl.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onOpened(CameraDeviceImpl.this);
+ }
}
}
};
@@ -105,8 +112,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
private final Runnable mCallOnUnconfigured = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
- mDeviceListener.onUnconfigured(CameraDevice.this);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ mDeviceListener.onUnconfigured(CameraDeviceImpl.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onUnconfigured(CameraDeviceImpl.this);
+ }
}
}
};
@@ -114,8 +125,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
private final Runnable mCallOnActive = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
- mDeviceListener.onActive(CameraDevice.this);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ mDeviceListener.onActive(CameraDeviceImpl.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onActive(CameraDeviceImpl.this);
+ }
}
}
};
@@ -123,8 +138,12 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
private final Runnable mCallOnBusy = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
- mDeviceListener.onBusy(CameraDevice.this);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ mDeviceListener.onBusy(CameraDeviceImpl.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onBusy(CameraDeviceImpl.this);
+ }
}
}
};
@@ -132,15 +151,23 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
private final Runnable mCallOnClosed = new Runnable() {
@Override
public void run() {
- mDeviceListener.onClosed(CameraDevice.this);
+ mDeviceListener.onClosed(CameraDeviceImpl.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onClosed(CameraDeviceImpl.this);
+ }
}
};
private final Runnable mCallOnIdle = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
- mDeviceListener.onIdle(CameraDevice.this);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ mDeviceListener.onIdle(CameraDeviceImpl.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onIdle(CameraDeviceImpl.this);
+ }
}
}
};
@@ -148,13 +175,17 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
private final Runnable mCallOnDisconnected = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
- mDeviceListener.onDisconnected(CameraDevice.this);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ mDeviceListener.onDisconnected(CameraDeviceImpl.this);
+ StateListener sessionListener = mSessionStateListener;
+ if (sessionListener != null) {
+ sessionListener.onDisconnected(CameraDeviceImpl.this);
+ }
}
}
};
- public CameraDevice(String cameraId, StateListener listener, Handler handler,
+ public CameraDeviceImpl(String cameraId, StateListener listener, Handler handler,
CameraCharacteristics characteristics) {
if (cameraId == null || listener == null || handler == null) {
throw new IllegalArgumentException("Null argument given");
@@ -170,7 +201,6 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
tag = tag.substring(0, MAX_TAG_LEN);
}
TAG = tag;
-
DEBUG = Log.isLoggable(TAG, Log.DEBUG);
}
@@ -263,7 +293,43 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
public void createCaptureSession(List<Surface> outputs,
CameraCaptureSession.StateListener listener, Handler handler)
throws CameraAccessException {
- // TODO
+ synchronized (mLock) {
+ if (DEBUG) {
+ Log.d(TAG, "createCaptureSession");
+ }
+
+ checkIfCameraClosed();
+
+ // TODO: we must be in UNCONFIGURED mode to begin with, or using another session
+
+ // TODO: dont block for this
+ boolean configureSuccess = true;
+ CameraAccessException pendingException = null;
+ try {
+ configureOutputs(outputs); // and then block until IDLE
+ } catch (CameraAccessException e) {
+ configureSuccess = false;
+ pendingException = e;
+ }
+
+ // Fire onConfigured if configureOutputs succeeded, fire onConfigureFailed otherwise.
+ CameraCaptureSessionImpl newSession =
+ new CameraCaptureSessionImpl(outputs, listener, handler, this, mDeviceHandler,
+ configureSuccess);
+
+ if (mCurrentSession != null) {
+ mCurrentSession.replaceSessionClose(newSession);
+ }
+
+ // TODO: wait until current session closes, then create the new session
+ mCurrentSession = newSession;
+
+ if (pendingException != null) {
+ throw pendingException;
+ }
+
+ mSessionStateListener = mCurrentSession.getDeviceStateListener();
+ }
}
@Override
@@ -275,7 +341,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
CameraMetadataNative templatedRequest = new CameraMetadataNative();
try {
- mRemoteDevice.createDefaultRequest(templateType, /* out */templatedRequest);
+ mRemoteDevice.createDefaultRequest(templateType, /*out*/templatedRequest);
} catch (CameraRuntimeException e) {
throw e.asChecked();
} catch (RemoteException e) {
@@ -304,10 +370,8 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
@Override
public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
- // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
- if (requests.isEmpty()) {
- Log.w(TAG, "Capture burst request list is empty, do nothing!");
- return -1;
+ if (requests == null || requests.isEmpty()) {
+ throw new IllegalArgumentException("At least one request must be given");
}
return submitCaptureRequest(requests, listener, handler, /*streaming*/false);
}
@@ -352,7 +416,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
Runnable resultDispatch = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
+ if (!CameraDeviceImpl.this.isClosed()) {
if (DEBUG) {
Log.d(TAG, String.format(
"early trigger sequence complete for request %d",
@@ -363,7 +427,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
throw new AssertionError(lastFrameNumber + " cannot be cast to int");
}
holder.getListener().onCaptureSequenceCompleted(
- CameraDevice.this,
+ CameraDeviceImpl.this,
requestId,
lastFrameNumber);
}
@@ -454,10 +518,8 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
@Override
public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
Handler handler) throws CameraAccessException {
- // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
- if (requests.isEmpty()) {
- Log.w(TAG, "Set Repeating burst request list is empty, do nothing!");
- return -1;
+ if (requests == null || requests.isEmpty()) {
+ throw new IllegalArgumentException("At least one request must be given");
}
return submitCaptureRequest(requests, listener, handler, /*streaming*/true);
}
@@ -707,7 +769,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
Runnable resultDispatch = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()){
+ if (!CameraDeviceImpl.this.isClosed()){
if (DEBUG) {
Log.d(TAG, String.format(
"fire sequence complete for request %d",
@@ -721,7 +783,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
+ " cannot be cast to int");
}
holder.getListener().onCaptureSequenceCompleted(
- CameraDevice.this,
+ CameraDeviceImpl.this,
requestId,
lastFrameNumber);
}
@@ -785,14 +847,14 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
r = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
- mDeviceListener.onError(CameraDevice.this, errorCode);
+ if (!CameraDeviceImpl.this.isClosed()) {
+ mDeviceListener.onError(CameraDeviceImpl.this, errorCode);
}
}
};
break;
}
- CameraDevice.this.mDeviceHandler.post(r);
+ CameraDeviceImpl.this.mDeviceHandler.post(r);
}
// Fire onCaptureSequenceCompleted
@@ -812,10 +874,10 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
Log.d(TAG, "Camera now idle");
}
synchronized (mLock) {
- if (!CameraDevice.this.mIdle) {
- CameraDevice.this.mDeviceHandler.post(mCallOnIdle);
+ if (!CameraDeviceImpl.this.mIdle) {
+ CameraDeviceImpl.this.mDeviceHandler.post(mCallOnIdle);
}
- CameraDevice.this.mIdle = true;
+ CameraDeviceImpl.this.mIdle = true;
}
}
@@ -829,7 +891,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
// Get the listener for this frame ID, if there is one
synchronized (mLock) {
- holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
+ holder = CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
}
if (holder == null) {
@@ -843,9 +905,9 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()) {
+ if (!CameraDeviceImpl.this.isClosed()) {
holder.getListener().onCaptureStarted(
- CameraDevice.this,
+ CameraDeviceImpl.this,
holder.getRequest(resultExtras.getSubsequenceId()),
timestamp);
}
@@ -870,7 +932,7 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
final CaptureListenerHolder holder;
synchronized (mLock) {
- holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
+ holder = CameraDeviceImpl.this.mCaptureListenerMap.get(requestId);
}
Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT);
@@ -914,9 +976,9 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
resultDispatch = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()){
+ if (!CameraDeviceImpl.this.isClosed()){
holder.getListener().onCapturePartial(
- CameraDevice.this,
+ CameraDeviceImpl.this,
request,
resultAsCapture);
}
@@ -930,9 +992,9 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
resultDispatch = new Runnable() {
@Override
public void run() {
- if (!CameraDevice.this.isClosed()){
+ if (!CameraDeviceImpl.this.isClosed()){
holder.getListener().onCaptureCompleted(
- CameraDevice.this,
+ CameraDeviceImpl.this,
request,
resultAsCapture);
}
@@ -951,10 +1013,14 @@ public class CameraDevice implements android.hardware.camera2.CameraDevice {
}
/**
- * Default handler management. If handler is null, get the current thread's
- * Looper to create a Handler with. If no looper exists, throw exception.
+ * Default handler management.
+ *
+ * <p>
+ * If handler is null, get the current thread's
+ * Looper to create a Handler with. If no looper exists, throw {@code IllegalArgumentException}.
+ * </p>
*/
- private Handler checkHandler(Handler handler) {
+ static Handler checkHandler(Handler handler) {
if (handler == null) {
Looper looper = Looper.myLooper();
if (looper == null) {
diff --git a/core/java/android/hardware/camera2/impl/ListenerProxies.java b/core/java/android/hardware/camera2/impl/ListenerProxies.java
new file mode 100644
index 0000000..04c43e3
--- /dev/null
+++ b/core/java/android/hardware/camera2/impl/ListenerProxies.java
@@ -0,0 +1,168 @@
+package android.hardware.camera2.impl;
+
+import android.hardware.camera2.CameraCaptureSession;
+import android.hardware.camera2.CameraDevice;
+import android.hardware.camera2.CaptureFailure;
+import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.TotalCaptureResult;
+import android.hardware.camera2.dispatch.Dispatchable;
+import android.hardware.camera2.dispatch.MethodNameInvoker;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Proxy out invocations to the camera2 API listeners into a {@link Dispatchable}.
+ *
+ * <p>Since abstract classes do not support Java's dynamic {@code Proxy}, we have to
+ * to use our own proxy mechanism.</p>
+ */
+public class ListenerProxies {
+
+ // TODO: replace with codegen
+
+ public static class DeviceStateListenerProxy extends CameraDevice.StateListener {
+ private final MethodNameInvoker<CameraDevice.StateListener> mProxy;
+
+ public DeviceStateListenerProxy(
+ Dispatchable<CameraDevice.StateListener> dispatchTarget) {
+ dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+ mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDevice.StateListener.class);
+ }
+
+ @Override
+ public void onOpened(CameraDevice camera) {
+ mProxy.invoke("onOpened", camera);
+ }
+
+ @Override
+ public void onDisconnected(CameraDevice camera) {
+ mProxy.invoke("onDisconnected", camera);
+ }
+
+ @Override
+ public void onError(CameraDevice camera, int error) {
+ mProxy.invoke("onError", camera, error);
+ }
+
+ @Override
+ public void onUnconfigured(CameraDevice camera) {
+ mProxy.invoke("onUnconfigured", camera);
+ }
+
+ @Override
+ public void onActive(CameraDevice camera) {
+ mProxy.invoke("onActive", camera);
+ }
+
+ @Override
+ public void onBusy(CameraDevice camera) {
+ mProxy.invoke("onBusy", camera);
+ }
+
+ @Override
+ public void onClosed(CameraDevice camera) {
+ mProxy.invoke("onClosed", camera);
+ }
+
+ @Override
+ public void onIdle(CameraDevice camera) {
+ mProxy.invoke("onIdle", camera);
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ public static class DeviceCaptureListenerProxy extends CameraDevice.CaptureListener {
+ private final MethodNameInvoker<CameraDevice.CaptureListener> mProxy;
+
+ public DeviceCaptureListenerProxy(
+ Dispatchable<CameraDevice.CaptureListener> dispatchTarget) {
+ dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+ mProxy = new MethodNameInvoker<>(dispatchTarget, CameraDevice.CaptureListener.class);
+ }
+
+ @Override
+ public void onCaptureStarted(CameraDevice camera,
+ CaptureRequest request, long timestamp) {
+ mProxy.invoke("onCaptureStarted", camera, request, timestamp);
+ }
+
+ @Override
+ public void onCapturePartial(CameraDevice camera,
+ CaptureRequest request, CaptureResult result) {
+ mProxy.invoke("onCapturePartial", camera, request, result);
+ }
+
+ @Override
+ public void onCaptureProgressed(CameraDevice camera,
+ CaptureRequest request, CaptureResult partialResult) {
+ mProxy.invoke("onCaptureProgressed", camera, request, partialResult);
+ }
+
+ @Override
+ public void onCaptureCompleted(CameraDevice camera,
+ CaptureRequest request, TotalCaptureResult result) {
+ mProxy.invoke("onCaptureCompleted", camera, request, result);
+ }
+
+ @Override
+ public void onCaptureFailed(CameraDevice camera,
+ CaptureRequest request, CaptureFailure failure) {
+ mProxy.invoke("onCaptureFailed", camera, request, failure);
+ }
+
+ @Override
+ public void onCaptureSequenceCompleted(CameraDevice camera,
+ int sequenceId, long frameNumber) {
+ mProxy.invoke("onCaptureSequenceCompleted", camera, sequenceId, frameNumber);
+ }
+
+ @Override
+ public void onCaptureSequenceAborted(CameraDevice camera,
+ int sequenceId) {
+ mProxy.invoke("onCaptureSequenceAborted", camera, sequenceId);
+ }
+ }
+
+ public static class SessionStateListenerProxy
+ extends CameraCaptureSession.StateListener {
+ private final MethodNameInvoker<CameraCaptureSession.StateListener> mProxy;
+
+ public SessionStateListenerProxy(
+ Dispatchable<CameraCaptureSession.StateListener> dispatchTarget) {
+ dispatchTarget = checkNotNull(dispatchTarget, "dispatchTarget must not be null");
+ mProxy = new MethodNameInvoker<>(dispatchTarget,
+ CameraCaptureSession.StateListener.class);
+ }
+
+ @Override
+ public void onConfigured(CameraCaptureSession session) {
+ mProxy.invoke("onConfigured", session);
+ }
+
+
+ @Override
+ public void onConfigureFailed(CameraCaptureSession session) {
+ mProxy.invoke("onConfigureFailed", session);
+ }
+
+ @Override
+ public void onReady(CameraCaptureSession session) {
+ mProxy.invoke("onReady", session);
+ }
+
+ @Override
+ public void onActive(CameraCaptureSession session) {
+ mProxy.invoke("onActive", session);
+ }
+
+ @Override
+ public void onClosed(CameraCaptureSession session) {
+ mProxy.invoke("onClosed", session);
+ }
+ }
+
+ private ListenerProxies() {
+ throw new AssertionError();
+ }
+}
diff --git a/core/java/android/hardware/camera2/utils/TaskDrainer.java b/core/java/android/hardware/camera2/utils/TaskDrainer.java
new file mode 100644
index 0000000..3cba9a1
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/TaskDrainer.java
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.utils;
+
+import android.os.Handler;
+import android.util.Log;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import static com.android.internal.util.Preconditions.*;
+
+/**
+ * Keep track of multiple concurrent tasks starting and finishing by their key;
+ * allow draining existing tasks and figuring out when all tasks have finished
+ * (and new ones won't begin).
+ *
+ * <p>The initial state is to allow all tasks to be started and finished. A task may only be started
+ * once, after which it must be finished before starting again. Likewise, finishing a task
+ * that hasn't been started is also not allowed.</p>
+ *
+ * <p>When draining begins, no more new tasks can be started. This guarantees that at some
+ * point when all the tasks are finished there will be no more collective new tasks,
+ * at which point the {@link DrainListener#onDrained} callback will be invoked.</p>
+ *
+ *
+ * @param <T>
+ * a type for the key that will represent tracked tasks;
+ * must implement {@code Object#equals}
+ */
+public class TaskDrainer<T> {
+ /**
+ * Fired asynchronously after draining has begun with {@link TaskDrainer#beginDrain}
+ * <em>and</em> all tasks that were started have finished.
+ */
+ public interface DrainListener {
+ /** All tasks have fully finished draining; there will be no more pending tasks. */
+ public void onDrained();
+ }
+
+ private static final String TAG = "TaskDrainer";
+ private static final boolean VERBOSE = false;
+
+ private final Handler mHandler;
+ private final DrainListener mListener;
+ private final String mName;
+
+ /** Set of tasks which have been started but not yet finished with #taskFinished */
+ private final Set<T> mTaskSet = new HashSet<T>();
+ private final Object mLock = new Object();
+
+ private boolean mDraining = false;
+ private boolean mDrainFinished = false;
+
+ /**
+ * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
+ * via the {@code handler}.
+ *
+ * @param handler a non-{@code null} handler to use to post runnables to
+ * @param listener a non-{@code null} listener where {@code onDrained} will be called
+ */
+ public TaskDrainer(Handler handler, DrainListener listener) {
+ mHandler = checkNotNull(handler, "handler must not be null");
+ mListener = checkNotNull(listener, "listener must not be null");
+ mName = null;
+ }
+
+ /**
+ * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
+ * via the {@code handler}.
+ *
+ * @param handler a non-{@code null} handler to use to post runnables to
+ * @param listener a non-{@code null} listener where {@code onDrained} will be called
+ * @param name an optional name used for debug logging
+ */
+ public TaskDrainer(Handler handler, DrainListener listener, String name) {
+ // XX: Probably don't need a handler at all here
+ mHandler = checkNotNull(handler, "handler must not be null");
+ mListener = checkNotNull(listener, "listener must not be null");
+ mName = name;
+ }
+
+ /**
+ * Mark an asynchronous task as having started.
+ *
+ * <p>A task cannot be started more than once without first having finished. Once
+ * draining begins with {@link #beginDrain}, no new tasks can be started.</p>
+ *
+ * @param task a key to identify a task
+ *
+ * @see #taskFinished
+ * @see #beginDrain
+ *
+ * @throws IllegalStateException
+ * If attempting to start a task which is already started (and not finished),
+ * or if attempting to start a task after draining has begun.
+ */
+ public void taskStarted(T task) {
+ synchronized (mLock) {
+ if (VERBOSE) {
+ Log.v(TAG + "[" + mName + "]", "taskStarted " + task);
+ }
+
+ if (mDraining) {
+ throw new IllegalStateException("Can't start more tasks after draining has begun");
+ }
+
+ if (!mTaskSet.add(task)) {
+ throw new IllegalStateException("Task " + task + " was already started");
+ }
+ }
+ }
+
+
+ /**
+ * Mark an asynchronous task as having finished.
+ *
+ * <p>A task cannot be finished if it hasn't started. Once finished, a task
+ * cannot be finished again (unless it's started again).</p>
+ *
+ * @param task a key to identify a task
+ *
+ * @see #taskStarted
+ * @see #beginDrain
+ *
+ * @throws IllegalStateException
+ * If attempting to start a task which is already finished (and not re-started),
+ */
+ public void taskFinished(T task) {
+ synchronized (mLock) {
+ if (VERBOSE) {
+ Log.v(TAG + "[" + mName + "]", "taskFinished " + task);
+ }
+
+ if (!mTaskSet.remove(task)) {
+ throw new IllegalStateException("Task " + task + " was already finished");
+ }
+
+ // If this is the last finished task and draining has already begun, fire #onDrained
+ checkIfDrainFinished();
+ }
+ }
+
+ /**
+ * Do not allow any more tasks to be started; once all existing started tasks are finished,
+ * fire the {@link DrainListener#onDrained} callback asynchronously.
+ *
+ * <p>This operation is idempotent; calling it more than once has no effect.</p>
+ */
+ public void beginDrain() {
+ synchronized (mLock) {
+ if (!mDraining) {
+ if (VERBOSE) {
+ Log.v(TAG + "[" + mName + "]", "beginDrain started");
+ }
+
+ mDraining = true;
+
+ // If all tasks that had started had already finished by now, fire #onDrained
+ checkIfDrainFinished();
+ } else {
+ if (VERBOSE) {
+ Log.v(TAG + "[" + mName + "]", "beginDrain ignored");
+ }
+ }
+ }
+ }
+
+ private void checkIfDrainFinished() {
+ if (mTaskSet.isEmpty() && mDraining && !mDrainFinished) {
+ mDrainFinished = true;
+ postDrained();
+ }
+ }
+
+ private void postDrained() {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (VERBOSE) {
+ Log.v(TAG + "[" + mName + "]", "onDrained");
+ }
+
+ mListener.onDrained();
+ }
+ });
+ }
+}
diff --git a/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java b/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java
new file mode 100644
index 0000000..f6272c9
--- /dev/null
+++ b/core/java/android/hardware/camera2/utils/TaskSingleDrainer.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2.utils;
+
+import android.hardware.camera2.utils.TaskDrainer.DrainListener;
+import android.os.Handler;
+
+/**
+ * Keep track of a single concurrent task starting and finishing;
+ * allow draining the existing task and figuring out when the task has finished
+ * (and won't restart).
+ *
+ * <p>The initial state is to allow all tasks to be started and finished. A task may only be started
+ * once, after which it must be finished before starting again. Likewise, finishing a task
+ * that hasn't been started is also not allowed.</p>
+ *
+ * <p>When draining begins, the task cannot be started again. This guarantees that at some
+ * point the task will be finished forever, at which point the {@link DrainListener#onDrained}
+ * callback will be invoked.</p>
+ */
+public class TaskSingleDrainer {
+
+ private final TaskDrainer<Object> mTaskDrainer;
+ private final Object mSingleTask = new Object();
+
+ /**
+ * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
+ * via the {@code handler}.
+ *
+ * @param handler a non-{@code null} handler to use to post runnables to
+ * @param listener a non-{@code null} listener where {@code onDrained} will be called
+ */
+ public TaskSingleDrainer(Handler handler, DrainListener listener) {
+ mTaskDrainer = new TaskDrainer<>(handler, listener);
+ }
+
+ /**
+ * Create a new task drainer; {@code onDrained} callbacks will be posted to the listener
+ * via the {@code handler}.
+ *
+ * @param handler a non-{@code null} handler to use to post runnables to
+ * @param listener a non-{@code null} listener where {@code onDrained} will be called
+ * @param name an optional name used for debug logging
+ */
+ public TaskSingleDrainer(Handler handler, DrainListener listener, String name) {
+ mTaskDrainer = new TaskDrainer<>(handler, listener, name);
+ }
+
+ /**
+ * Mark this asynchronous task as having started.
+ *
+ * <p>The task cannot be started more than once without first having finished. Once
+ * draining begins with {@link #beginDrain}, no new tasks can be started.</p>
+ *
+ * @see #taskFinished
+ * @see #beginDrain
+ *
+ * @throws IllegalStateException
+ * If attempting to start a task which is already started (and not finished),
+ * or if attempting to start a task after draining has begun.
+ */
+ public void taskStarted() {
+ mTaskDrainer.taskStarted(mSingleTask);
+ }
+
+ /**
+ * Do not allow any more task re-starts; once the existing task is finished,
+ * fire the {@link DrainListener#onDrained} callback asynchronously.
+ *
+ * <p>This operation is idempotent; calling it more than once has no effect.</p>
+ */
+ public void beginDrain() {
+ mTaskDrainer.beginDrain();
+ }
+
+ /**
+ * Mark this asynchronous task as having finished.
+ *
+ * <p>The task cannot be finished if it hasn't started. Once finished, a task
+ * cannot be finished again (unless it's started again).</p>
+ *
+ * @see #taskStarted
+ * @see #beginDrain
+ *
+ * @throws IllegalStateException
+ * If attempting to start a task which is already finished (and not re-started),
+ */
+ public void taskFinished() {
+ mTaskDrainer.taskFinished(mSingleTask);
+ }
+}
diff --git a/core/java/android/hardware/camera2/utils/UncheckedThrow.java b/core/java/android/hardware/camera2/utils/UncheckedThrow.java
index 8224fed..ffcb78b 100644
--- a/core/java/android/hardware/camera2/utils/UncheckedThrow.java
+++ b/core/java/android/hardware/camera2/utils/UncheckedThrow.java
@@ -33,8 +33,20 @@ public class UncheckedThrow {
UncheckedThrow.<RuntimeException>throwAnyImpl(e);
}
+ /**
+ * Throw any kind of throwable without needing it to be checked
+ * @param e any instance of a Throwable
+ */
+ public static void throwAnyException(Throwable e) {
+ /**
+ * Abuse type erasure by making the compiler think we are throwing RuntimeException,
+ * which is unchecked, but then inserting any exception in there.
+ */
+ UncheckedThrow.<RuntimeException>throwAnyImpl(e);
+ }
+
@SuppressWarnings("unchecked")
- private static<T extends Exception> void throwAnyImpl(Exception e) throws T {
+ private static<T extends Throwable> void throwAnyImpl(Throwable e) throws T {
throw (T) e;
}
}
diff --git a/core/java/android/hardware/hdmi/HdmiCec.java b/core/java/android/hardware/hdmi/HdmiCec.java
index a71a74d..723eda1 100644
--- a/core/java/android/hardware/hdmi/HdmiCec.java
+++ b/core/java/android/hardware/hdmi/HdmiCec.java
@@ -194,6 +194,8 @@ public final class HdmiCec {
DEVICE_RECORDER, // ADDR_RECORDER_3
DEVICE_TUNER, // ADDR_TUNER_4
DEVICE_PLAYBACK, // ADDR_PLAYBACK_3
+ DEVICE_RESERVED,
+ DEVICE_RESERVED,
DEVICE_TV, // ADDR_SPECIFIC_USE
};
@@ -210,6 +212,8 @@ public final class HdmiCec {
"Recorder_3",
"Tuner_4",
"Playback_3",
+ "Reserved_1",
+ "Reserved_2",
"Secondary_TV",
};
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 2f2aba3..b96f166 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -40,6 +40,7 @@ import android.util.ArrayMap;
import android.util.Log;
import com.android.internal.telephony.ITelephony;
+import com.android.internal.telephony.PhoneConstants;
import com.android.internal.util.Protocol;
import java.net.InetAddress;
@@ -807,11 +808,34 @@ public class ConnectivityManager {
* @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
*/
public int startUsingNetworkFeature(int networkType, String feature) {
- try {
- return mService.startUsingNetworkFeature(networkType, feature,
- new Binder());
- } catch (RemoteException e) {
- return -1;
+ NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
+ if (netCap == null) {
+ Log.d(TAG, "Can't satisfy startUsingNetworkFeature for " + networkType + ", " +
+ feature);
+ return PhoneConstants.APN_REQUEST_FAILED;
+ }
+
+ NetworkRequest request = null;
+ synchronized (sLegacyRequests) {
+ LegacyRequest l = sLegacyRequests.get(netCap);
+ if (l != null) {
+ Log.d(TAG, "renewing startUsingNetworkFeature request " + l.networkRequest);
+ renewRequestLocked(l);
+ if (l.currentNetwork != null) {
+ return PhoneConstants.APN_ALREADY_ACTIVE;
+ } else {
+ return PhoneConstants.APN_REQUEST_STARTED;
+ }
+ }
+
+ request = requestNetworkForFeatureLocked(netCap);
+ }
+ if (request != null) {
+ Log.d(TAG, "starting startUsingNeworkFeature for request " + request);
+ return PhoneConstants.APN_REQUEST_STARTED;
+ } else {
+ Log.d(TAG, " request Failed");
+ return PhoneConstants.APN_REQUEST_FAILED;
}
}
@@ -831,11 +855,208 @@ public class ConnectivityManager {
* @deprecated Deprecated in favor of the cleaner {@link #requestNetwork} api.
*/
public int stopUsingNetworkFeature(int networkType, String feature) {
- try {
- return mService.stopUsingNetworkFeature(networkType, feature);
- } catch (RemoteException e) {
+ NetworkCapabilities netCap = networkCapabilitiesForFeature(networkType, feature);
+ if (netCap == null) {
+ Log.d(TAG, "Can't satisfy stopUsingNetworkFeature for " + networkType + ", " +
+ feature);
return -1;
}
+
+ NetworkRequest request = removeRequestForFeature(netCap);
+ if (request != null) {
+ Log.d(TAG, "stopUsingNetworkFeature for " + networkType + ", " + feature);
+ releaseNetworkRequest(request);
+ }
+ return 1;
+ }
+
+ /**
+ * Removes the NET_CAPABILITY_NOT_RESTRICTED capability from the given
+ * NetworkCapabilities object if all the capabilities it provides are
+ * typically provided by restricted networks.
+ *
+ * TODO: consider:
+ * - Moving to NetworkCapabilities
+ * - Renaming it to guessRestrictedCapability and make it set the
+ * restricted capability bit in addition to clearing it.
+ * @hide
+ */
+ public static void maybeMarkCapabilitiesRestricted(NetworkCapabilities nc) {
+ for (Integer capability : nc.getNetworkCapabilities()) {
+ switch (capability.intValue()) {
+ case NetworkCapabilities.NET_CAPABILITY_CBS:
+ case NetworkCapabilities.NET_CAPABILITY_DUN:
+ case NetworkCapabilities.NET_CAPABILITY_EIMS:
+ case NetworkCapabilities.NET_CAPABILITY_FOTA:
+ case NetworkCapabilities.NET_CAPABILITY_IA:
+ case NetworkCapabilities.NET_CAPABILITY_IMS:
+ case NetworkCapabilities.NET_CAPABILITY_RCS:
+ case NetworkCapabilities.NET_CAPABILITY_XCAP:
+ continue;
+ default:
+ // At least one capability usually provided by unrestricted
+ // networks. Conclude that this network is unrestricted.
+ return;
+ }
+ }
+ // All the capabilities are typically provided by restricted networks.
+ // Conclude that this network is restricted.
+ nc.removeNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
+ }
+
+ private NetworkCapabilities networkCapabilitiesForFeature(int networkType, String feature) {
+ if (networkType == TYPE_MOBILE) {
+ int cap = -1;
+ if ("enableMMS".equals(feature)) {
+ cap = NetworkCapabilities.NET_CAPABILITY_MMS;
+ } else if ("enableSUPL".equals(feature)) {
+ cap = NetworkCapabilities.NET_CAPABILITY_SUPL;
+ } else if ("enableDUN".equals(feature) || "enableDUNAlways".equals(feature)) {
+ cap = NetworkCapabilities.NET_CAPABILITY_DUN;
+ } else if ("enableHIPRI".equals(feature)) {
+ cap = NetworkCapabilities.NET_CAPABILITY_INTERNET;
+ } else if ("enableFOTA".equals(feature)) {
+ cap = NetworkCapabilities.NET_CAPABILITY_FOTA;
+ } else if ("enableIMS".equals(feature)) {
+ cap = NetworkCapabilities.NET_CAPABILITY_IMS;
+ } else if ("enableCBS".equals(feature)) {
+ cap = NetworkCapabilities.NET_CAPABILITY_CBS;
+ } else {
+ return null;
+ }
+ NetworkCapabilities netCap = new NetworkCapabilities();
+ netCap.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ netCap.addNetworkCapability(cap);
+ maybeMarkCapabilitiesRestricted(netCap);
+ return netCap;
+ } else if (networkType == TYPE_WIFI) {
+ if ("p2p".equals(feature)) {
+ NetworkCapabilities netCap = new NetworkCapabilities();
+ netCap.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
+ netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P);
+ maybeMarkCapabilitiesRestricted(netCap);
+ return netCap;
+ }
+ }
+ return null;
+ }
+
+ private int legacyTypeForNetworkCapabilities(NetworkCapabilities netCap) {
+ if (netCap == null) return TYPE_NONE;
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_CBS)) {
+ return TYPE_MOBILE_CBS;
+ }
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_IMS)) {
+ return TYPE_MOBILE_IMS;
+ }
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA)) {
+ return TYPE_MOBILE_FOTA;
+ }
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_DUN)) {
+ return TYPE_MOBILE_DUN;
+ }
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_SUPL)) {
+ return TYPE_MOBILE_SUPL;
+ }
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+ return TYPE_MOBILE_MMS;
+ }
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)) {
+ return TYPE_MOBILE_HIPRI;
+ }
+ if (netCap.hasCapability(NetworkCapabilities.NET_CAPABILITY_WIFI_P2P)) {
+ return TYPE_WIFI_P2P;
+ }
+ return TYPE_NONE;
+ }
+
+ private static class LegacyRequest {
+ NetworkCapabilities networkCapabilities;
+ NetworkRequest networkRequest;
+ int expireSequenceNumber;
+ Network currentNetwork;
+ int delay = -1;
+ NetworkCallbackListener networkCallbackListener = new NetworkCallbackListener() {
+ @Override
+ public void onAvailable(NetworkRequest request, Network network) {
+ currentNetwork = network;
+ Log.d(TAG, "startUsingNetworkFeature got Network:" + network);
+ network.bindProcessForHostResolution();
+ }
+ @Override
+ public void onLost(NetworkRequest request, Network network) {
+ if (network.equals(currentNetwork)) {
+ currentNetwork = null;
+ network.unbindProcessForHostResolution();
+ }
+ Log.d(TAG, "startUsingNetworkFeature lost Network:" + network);
+ }
+ };
+ }
+
+ private HashMap<NetworkCapabilities, LegacyRequest> sLegacyRequests =
+ new HashMap<NetworkCapabilities, LegacyRequest>();
+
+ private NetworkRequest findRequestForFeature(NetworkCapabilities netCap) {
+ synchronized (sLegacyRequests) {
+ LegacyRequest l = sLegacyRequests.get(netCap);
+ if (l != null) return l.networkRequest;
+ }
+ return null;
+ }
+
+ private void renewRequestLocked(LegacyRequest l) {
+ l.expireSequenceNumber++;
+ Log.d(TAG, "renewing request to seqNum " + l.expireSequenceNumber);
+ sendExpireMsgForFeature(l.networkCapabilities, l.expireSequenceNumber, l.delay);
+ }
+
+ private void expireRequest(NetworkCapabilities netCap, int sequenceNum) {
+ int ourSeqNum = -1;
+ synchronized (sLegacyRequests) {
+ LegacyRequest l = sLegacyRequests.get(netCap);
+ if (l == null) return;
+ ourSeqNum = l.expireSequenceNumber;
+ if (l.expireSequenceNumber == sequenceNum) {
+ releaseNetworkRequest(l.networkRequest);
+ sLegacyRequests.remove(netCap);
+ }
+ }
+ Log.d(TAG, "expireRequest with " + ourSeqNum + ", " + sequenceNum);
+ }
+
+ private NetworkRequest requestNetworkForFeatureLocked(NetworkCapabilities netCap) {
+ int delay = -1;
+ int type = legacyTypeForNetworkCapabilities(netCap);
+ try {
+ delay = mService.getRestoreDefaultNetworkDelay(type);
+ } catch (RemoteException e) {}
+ LegacyRequest l = new LegacyRequest();
+ l.networkCapabilities = netCap;
+ l.delay = delay;
+ l.expireSequenceNumber = 0;
+ l.networkRequest = sendRequestForNetwork(netCap, l.networkCallbackListener, 0,
+ REQUEST, type);
+ if (l.networkRequest == null) return null;
+ sLegacyRequests.put(netCap, l);
+ sendExpireMsgForFeature(netCap, l.expireSequenceNumber, delay);
+ return l.networkRequest;
+ }
+
+ private void sendExpireMsgForFeature(NetworkCapabilities netCap, int seqNum, int delay) {
+ if (delay >= 0) {
+ Log.d(TAG, "sending expire msg with seqNum " + seqNum + " and delay " + delay);
+ Message msg = sCallbackHandler.obtainMessage(EXPIRE_LEGACY_REQUEST, seqNum, 0, netCap);
+ sCallbackHandler.sendMessageDelayed(msg, delay);
+ }
+ }
+
+ private NetworkRequest removeRequestForFeature(NetworkCapabilities netCap) {
+ synchronized (sLegacyRequests) {
+ LegacyRequest l = sLegacyRequests.remove(netCap);
+ if (l == null) return null;
+ return l.networkRequest;
+ }
}
/**
@@ -1782,8 +2003,10 @@ public class ConnectivityManager {
public static final int CALLBACK_RELEASED = BASE + 8;
/** @hide */
public static final int CALLBACK_EXIT = BASE + 9;
+ /** @hide obj = NetworkCapabilities, arg1 = seq number */
+ private static final int EXPIRE_LEGACY_REQUEST = BASE + 10;
- private static class CallbackHandler extends Handler {
+ private class CallbackHandler extends Handler {
private final HashMap<NetworkRequest, NetworkCallbackListener>mCallbackMap;
private final AtomicInteger mRefCount;
private static final String TAG = "ConnectivityManager.CallbackHandler";
@@ -1903,6 +2126,10 @@ public class ConnectivityManager {
getLooper().quit();
break;
}
+ case EXPIRE_LEGACY_REQUEST: {
+ expireRequest((NetworkCapabilities)message.obj, message.arg1);
+ break;
+ }
}
}
@@ -1954,8 +2181,9 @@ public class ConnectivityManager {
private final static int LISTEN = 1;
private final static int REQUEST = 2;
- private NetworkRequest somethingForNetwork(NetworkCapabilities need,
- NetworkCallbackListener networkCallbackListener, int timeoutSec, int action) {
+ private NetworkRequest sendRequestForNetwork(NetworkCapabilities need,
+ NetworkCallbackListener networkCallbackListener, int timeoutSec, int action,
+ int legacyType) {
NetworkRequest networkRequest = null;
if (networkCallbackListener == null) {
throw new IllegalArgumentException("null NetworkCallbackListener");
@@ -1968,7 +2196,7 @@ public class ConnectivityManager {
new Binder());
} else {
networkRequest = mService.requestNetwork(need, new Messenger(sCallbackHandler),
- timeoutSec, new Binder());
+ timeoutSec, new Binder(), legacyType);
}
if (networkRequest != null) {
synchronized(sNetworkCallbackListener) {
@@ -1998,7 +2226,7 @@ public class ConnectivityManager {
*/
public NetworkRequest requestNetwork(NetworkCapabilities need,
NetworkCallbackListener networkCallbackListener) {
- return somethingForNetwork(need, networkCallbackListener, 0, REQUEST);
+ return sendRequestForNetwork(need, networkCallbackListener, 0, REQUEST, TYPE_NONE);
}
/**
@@ -2021,7 +2249,8 @@ public class ConnectivityManager {
*/
public NetworkRequest requestNetwork(NetworkCapabilities need,
NetworkCallbackListener networkCallbackListener, int timeoutSec) {
- return somethingForNetwork(need, networkCallbackListener, timeoutSec, REQUEST);
+ return sendRequestForNetwork(need, networkCallbackListener, timeoutSec, REQUEST,
+ TYPE_NONE);
}
/**
@@ -2099,7 +2328,7 @@ public class ConnectivityManager {
*/
public NetworkRequest listenForNetwork(NetworkCapabilities need,
NetworkCallbackListener networkCallbackListener) {
- return somethingForNetwork(need, networkCallbackListener, 0, LISTEN);
+ return sendRequestForNetwork(need, networkCallbackListener, 0, LISTEN, TYPE_NONE);
}
/**
diff --git a/core/java/android/net/ConnectivityServiceProtocol.java b/core/java/android/net/ConnectivityServiceProtocol.java
deleted file mode 100644
index 74096b4..0000000
--- a/core/java/android/net/ConnectivityServiceProtocol.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.net;
-
-import static com.android.internal.util.Protocol.BASE_CONNECTIVITY_SERVICE;
-
-/**
- * Describes the Internal protocols used to communicate with ConnectivityService.
- * @hide
- */
-public class ConnectivityServiceProtocol {
-
- private static final int BASE = BASE_CONNECTIVITY_SERVICE;
-
- private ConnectivityServiceProtocol() {}
-
- /**
- * This is a contract between ConnectivityService and various bearers.
- * A NetworkFactory is an abstract entity that creates NetworkAgent objects.
- * The bearers register with ConnectivityService using
- * ConnectivityManager.registerNetworkFactory, where they pass in a Messenger
- * to be used to deliver the following Messages.
- */
- public static class NetworkFactoryProtocol {
- private NetworkFactoryProtocol() {}
- /**
- * Pass a network request to the bearer. If the bearer believes it can
- * satisfy the request it should connect to the network and create a
- * NetworkAgent. Once the NetworkAgent is fully functional it will
- * register itself with ConnectivityService using registerNetworkAgent.
- * If the bearer cannot immediately satisfy the request (no network,
- * user disabled the radio, lower-scored network) it should remember
- * any NetworkRequests it may be able to satisfy in the future. It may
- * disregard any that it will never be able to service, for example
- * those requiring a different bearer.
- * msg.obj = NetworkRequest
- * msg.arg1 = score - the score of the any network currently satisfying this
- * request. If this bearer knows in advance it cannot
- * exceed this score it should not try to connect, holding the request
- * for the future.
- * Note that subsequent events may give a different (lower
- * or higher) score for this request, transmitted to each
- * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
- * with the same NetworkRequest but an updated score.
- * Also, network conditions may change for this bearer
- * allowing for a better score in the future.
- */
- public static final int CMD_REQUEST_NETWORK = BASE;
-
- /**
- * Cancel a network request
- * msg.obj = NetworkRequest
- */
- public static final int CMD_CANCEL_REQUEST = BASE + 1;
- }
-}
diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl
index baec36a..5f1ff3e 100644
--- a/core/java/android/net/IConnectivityManager.aidl
+++ b/core/java/android/net/IConnectivityManager.aidl
@@ -158,7 +158,7 @@ interface IConnectivityManager
in NetworkCapabilities nc, int score);
NetworkRequest requestNetwork(in NetworkCapabilities networkCapabilities,
- in Messenger messenger, int timeoutSec, in IBinder binder);
+ in Messenger messenger, int timeoutSec, in IBinder binder, int legacy);
NetworkRequest pendingRequestForNetwork(in NetworkCapabilities networkCapabilities,
in PendingIntent operation);
@@ -170,4 +170,6 @@ interface IConnectivityManager
in PendingIntent operation);
void releaseNetworkRequest(in NetworkRequest networkRequest);
+
+ int getRestoreDefaultNetworkDelay(int networkType);
}
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 1c18ba5..7e8b1f1 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -24,85 +24,39 @@ import android.os.Messenger;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;
-import android.util.SparseArray;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.Protocol;
+import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
/**
- * A Utility class for handling NetworkRequests.
- *
- * Created by bearer-specific code to handle tracking requests, scores,
- * network data and handle communicating with ConnectivityService. Two
- * abstract methods: connect and disconnect are used to act on the
- * underlying bearer code. Connect is called when we have a NetworkRequest
- * and our score is better than the current handling network's score, while
- * disconnect is used when ConnectivityService requests a disconnect.
+ * A Utility class for handling for communicating between bearer-specific
+ * code and ConnectivityService.
*
* A bearer may have more than one NetworkAgent if it can simultaneously
* support separate networks (IMS / Internet / MMS Apns on cellular, or
- * perhaps connections with different SSID or P2P for Wi-Fi). The bearer
- * code should pass its NetworkAgents the NetworkRequests each NetworkAgent
- * can handle, demultiplexing for different network types. The bearer code
- * can also filter out requests it can never handle.
+ * perhaps connections with different SSID or P2P for Wi-Fi).
*
- * Each NetworkAgent needs to be given a score and NetworkCapabilities for
- * their potential network. While disconnected, the NetworkAgent will check
- * each time its score changes or a NetworkRequest changes to see if
- * the NetworkAgent can provide a higher scored network for a NetworkRequest
- * that the NetworkAgent's NetworkCapabilties can satisfy. This condition will
- * trigger a connect request via connect(). After connection, connection data
- * should be given to the NetworkAgent by the bearer, including LinkProperties
- * NetworkCapabilties and NetworkInfo. After that the NetworkAgent will register
- * with ConnectivityService and forward the data on.
* @hide
*/
public abstract class NetworkAgent extends Handler {
- private final SparseArray<NetworkRequestAndScore> mNetworkRequests = new SparseArray<>();
- private boolean mConnectionRequested = false;
-
- private AsyncChannel mAsyncChannel;
+ private volatile AsyncChannel mAsyncChannel;
private final String LOG_TAG;
private static final boolean DBG = true;
private static final boolean VDBG = true;
- // TODO - this class shouldn't cache data or it runs the risk of getting out of sync
- // Make the API require each of these when any is updated so we have the data we need,
- // without caching.
- private LinkProperties mLinkProperties;
- private NetworkInfo mNetworkInfo;
- private NetworkCapabilities mNetworkCapabilities;
- private int mNetworkScore;
- private boolean mRegistered = false;
private final Context mContext;
- private AtomicBoolean mHasRequests = new AtomicBoolean(false);
-
- // TODO - add a name member for logging purposes.
-
- protected final Object mLockObj = new Object();
-
+ private final ArrayList<Message>mPreConnectedQueue = new ArrayList<Message>();
private static final int BASE = Protocol.BASE_NETWORK_AGENT;
/**
- * Sent by self to queue up a new/modified request.
- * obj = NetworkRequestAndScore
- */
- private static final int CMD_ADD_REQUEST = BASE + 1;
-
- /**
- * Sent by self to queue up the removal of a request.
- * obj = NetworkRequest
- */
- private static final int CMD_REMOVE_REQUEST = BASE + 2;
-
- /**
* Sent by ConnectivityService to the NetworkAgent to inform it of
* suspected connectivity problems on its network. The NetworkAgent
* should take steps to verify and correct connectivity.
*/
- public static final int CMD_SUSPECT_BAD = BASE + 3;
+ public static final int CMD_SUSPECT_BAD = BASE;
/**
* Sent by the NetworkAgent (note the EVENT vs CMD prefix) to
@@ -110,84 +64,63 @@ public abstract class NetworkAgent extends Handler {
* Sent when the NetworkInfo changes, mainly due to change of state.
* obj = NetworkInfo
*/
- public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 4;
+ public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1;
/**
* Sent by the NetworkAgent to ConnectivityService to pass the current
* NetworkCapabilties.
* obj = NetworkCapabilities
*/
- public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 5;
+ public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2;
/**
* Sent by the NetworkAgent to ConnectivityService to pass the current
* NetworkProperties.
* obj = NetworkProperties
*/
- public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 6;
+ public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3;
/**
* Sent by the NetworkAgent to ConnectivityService to pass the current
* network score.
- * arg1 = network score int
+ * obj = network score Integer
*/
- public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 7;
+ public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4;
- public NetworkAgent(Looper looper, Context context, String logTag) {
+ public NetworkAgent(Looper looper, Context context, String logTag, NetworkInfo ni,
+ NetworkCapabilities nc, LinkProperties lp, int score) {
super(looper);
LOG_TAG = logTag;
mContext = context;
- }
-
- /**
- * When conditions are right, register with ConnectivityService.
- * Connditions include having a well defined network and a request
- * that justifies it. The NetworkAgent will remain registered until
- * disconnected.
- * TODO - this should have all data passed in rather than caching
- */
- private void registerSelf() {
- synchronized(mLockObj) {
- if (!mRegistered && mConnectionRequested &&
- mNetworkInfo != null && mNetworkInfo.isConnected() &&
- mNetworkCapabilities != null &&
- mLinkProperties != null &&
- mNetworkScore != 0) {
- if (DBG) log("Registering NetworkAgent");
- mRegistered = true;
- ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
- Context.CONNECTIVITY_SERVICE);
- cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(mNetworkInfo),
- new LinkProperties(mLinkProperties),
- new NetworkCapabilities(mNetworkCapabilities), mNetworkScore);
- } else if (DBG && !mRegistered) {
- String err = "Not registering due to ";
- if (mConnectionRequested == false) err += "no Connect requested ";
- if (mNetworkInfo == null) err += "null NetworkInfo ";
- if (mNetworkInfo != null && mNetworkInfo.isConnected() == false) {
- err += "NetworkInfo disconnected ";
- }
- if (mLinkProperties == null) err += "null LinkProperties ";
- if (mNetworkCapabilities == null) err += "null NetworkCapabilities ";
- if (mNetworkScore == 0) err += "null NetworkScore";
- log(err);
- }
+ if (ni == null || nc == null || lp == null) {
+ throw new IllegalArgumentException();
}
+
+ if (DBG) log("Registering NetworkAgent");
+ ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ cm.registerNetworkAgent(new Messenger(this), new NetworkInfo(ni),
+ new LinkProperties(lp), new NetworkCapabilities(nc), score);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION: {
- synchronized (mLockObj) {
- if (mAsyncChannel != null) {
- log("Received new connection while already connected!");
- } else {
- if (DBG) log("NetworkAgent fully connected");
- mAsyncChannel = new AsyncChannel();
- mAsyncChannel.connected(null, this, msg.replyTo);
- mAsyncChannel.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
- AsyncChannel.STATUS_SUCCESSFUL);
+ if (mAsyncChannel != null) {
+ log("Received new connection while already connected!");
+ } else {
+ if (DBG) log("NetworkAgent fully connected");
+ AsyncChannel ac = new AsyncChannel();
+ ac.connected(null, this, msg.replyTo);
+ ac.replyToMessage(msg, AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED,
+ AsyncChannel.STATUS_SUCCESSFUL);
+ synchronized (mPreConnectedQueue) {
+ mAsyncChannel = ac;
+ for (Message m : mPreConnectedQueue) {
+ ac.sendMessage(m);
+ }
+ mPreConnectedQueue.clear();
}
}
break;
@@ -199,213 +132,69 @@ public abstract class NetworkAgent extends Handler {
}
case AsyncChannel.CMD_CHANNEL_DISCONNECTED: {
if (DBG) log("NetworkAgent channel lost");
- disconnect();
- clear();
+ // let the client know CS is done with us.
+ unwanted();
+ synchronized (mPreConnectedQueue) {
+ mAsyncChannel = null;
+ }
break;
}
case CMD_SUSPECT_BAD: {
log("Unhandled Message " + msg);
break;
}
- case CMD_ADD_REQUEST: {
- handleAddRequest(msg);
- break;
- }
- case CMD_REMOVE_REQUEST: {
- handleRemoveRequest(msg);
- break;
- }
- }
- }
-
- private void clear() {
- synchronized(mLockObj) {
- mNetworkRequests.clear();
- mHasRequests.set(false);
- mConnectionRequested = false;
- mAsyncChannel = null;
- mRegistered = false;
- }
- }
-
- private static class NetworkRequestAndScore {
- NetworkRequest req;
- int score;
-
- NetworkRequestAndScore(NetworkRequest networkRequest, int score) {
- req = networkRequest;
- this.score = score;
}
}
- private void handleAddRequest(Message msg) {
- NetworkRequestAndScore n = (NetworkRequestAndScore)msg.obj;
- // replaces old request, updating score
- mNetworkRequests.put(n.req.requestId, n);
- mHasRequests.set(true);
- evalScores();
- }
-
- private void handleRemoveRequest(Message msg) {
- NetworkRequest networkRequest = (NetworkRequest)msg.obj;
-
- if (mNetworkRequests.get(networkRequest.requestId) != null) {
- mNetworkRequests.remove(networkRequest.requestId);
- if (mNetworkRequests.size() == 0) mHasRequests.set(false);
- evalScores();
- }
- }
-
- /**
- * Called to go through our list of requests and see if we're
- * good enough to try connecting, or if we have gotten worse and
- * need to disconnect.
- *
- * Once we are registered, does nothing: we disconnect when requested via
- * CMD_CHANNEL_DISCONNECTED, generated by either a loss of connection
- * between modules (bearer or ConnectivityService dies) or more commonly
- * when the NetworkInfo reports to ConnectivityService it is disconnected.
- */
- private void evalScores() {
- synchronized(mLockObj) {
- if (mRegistered) {
- if (VDBG) log("evalScores - already connected - size=" + mNetworkRequests.size());
- // already trying
- return;
- }
- if (VDBG) log("evalScores!");
- for (int i=0; i < mNetworkRequests.size(); i++) {
- int score = mNetworkRequests.valueAt(i).score;
- if (VDBG) log(" checking request Min " + score + " vs my score " + mNetworkScore);
- if (score < mNetworkScore) {
- // have a request that has a lower scored network servicing it
- // (or no network) than we could provide, so let's connect!
- mConnectionRequested = true;
- connect();
- return;
- }
- }
- // Our score is not high enough to satisfy any current request.
- // This can happen if our score goes down after a connection is
- // requested but before we actually connect. In this case, disconnect
- // rather than continue trying - there's no point connecting if we know
- // we'll just be torn down as soon as we do.
- if (mConnectionRequested) {
- mConnectionRequested = false;
- disconnect();
+ private void queueOrSendMessage(int what, Object obj) {
+ synchronized (mPreConnectedQueue) {
+ if (mAsyncChannel != null) {
+ mAsyncChannel.sendMessage(what, obj);
+ } else {
+ Message msg = Message.obtain();
+ msg.what = what;
+ msg.obj = obj;
+ mPreConnectedQueue.add(msg);
}
}
}
- public void addNetworkRequest(NetworkRequest networkRequest, int score) {
- if (DBG) log("adding NetworkRequest " + networkRequest + " with score " + score);
- sendMessage(obtainMessage(CMD_ADD_REQUEST,
- new NetworkRequestAndScore(networkRequest, score)));
- }
-
- public void removeNetworkRequest(NetworkRequest networkRequest) {
- if (DBG) log("removing NetworkRequest " + networkRequest);
- sendMessage(obtainMessage(CMD_REMOVE_REQUEST, networkRequest));
- }
-
/**
* Called by the bearer code when it has new LinkProperties data.
- * If we're a registered NetworkAgent, this new data will get forwarded on,
- * otherwise we store a copy in anticipation of registering. This call
- * may also prompt registration if it causes the NetworkAgent to meet
- * the conditions (fully configured, connected, satisfys a request and
- * has sufficient score).
*/
public void sendLinkProperties(LinkProperties linkProperties) {
- linkProperties = new LinkProperties(linkProperties);
- synchronized(mLockObj) {
- mLinkProperties = linkProperties;
- if (mAsyncChannel != null) {
- mAsyncChannel.sendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, linkProperties);
- } else {
- registerSelf();
- }
- }
+ queueOrSendMessage(EVENT_NETWORK_PROPERTIES_CHANGED, new LinkProperties(linkProperties));
}
/**
* Called by the bearer code when it has new NetworkInfo data.
- * If we're a registered NetworkAgent, this new data will get forwarded on,
- * otherwise we store a copy in anticipation of registering. This call
- * may also prompt registration if it causes the NetworkAgent to meet
- * the conditions (fully configured, connected, satisfys a request and
- * has sufficient score).
*/
public void sendNetworkInfo(NetworkInfo networkInfo) {
- networkInfo = new NetworkInfo(networkInfo);
- synchronized(mLockObj) {
- mNetworkInfo = networkInfo;
- if (mAsyncChannel != null) {
- mAsyncChannel.sendMessage(EVENT_NETWORK_INFO_CHANGED, networkInfo);
- } else {
- registerSelf();
- }
- }
+ queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
}
/**
* Called by the bearer code when it has new NetworkCapabilities data.
- * If we're a registered NetworkAgent, this new data will get forwarded on,
- * otherwise we store a copy in anticipation of registering. This call
- * may also prompt registration if it causes the NetworkAgent to meet
- * the conditions (fully configured, connected, satisfys a request and
- * has sufficient score).
- * Note that if these capabilities make the network non-useful,
- * ConnectivityServce will tear this network down.
*/
public void sendNetworkCapabilities(NetworkCapabilities networkCapabilities) {
- networkCapabilities = new NetworkCapabilities(networkCapabilities);
- synchronized(mLockObj) {
- mNetworkCapabilities = networkCapabilities;
- if (mAsyncChannel != null) {
- mAsyncChannel.sendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED, networkCapabilities);
- } else {
- registerSelf();
- }
- }
- }
-
- public NetworkCapabilities getNetworkCapabilities() {
- synchronized(mLockObj) {
- return new NetworkCapabilities(mNetworkCapabilities);
- }
+ queueOrSendMessage(EVENT_NETWORK_CAPABILITIES_CHANGED,
+ new NetworkCapabilities(networkCapabilities));
}
/**
* Called by the bearer code when it has a new score for this network.
- * If we're a registered NetworkAgent, this new data will get forwarded on,
- * otherwise we store a copy.
*/
- public synchronized void sendNetworkScore(int score) {
- synchronized(mLockObj) {
- mNetworkScore = score;
- evalScores();
- if (mAsyncChannel != null) {
- mAsyncChannel.sendMessage(EVENT_NETWORK_SCORE_CHANGED, mNetworkScore);
- } else {
- registerSelf();
- }
- }
- }
-
- public boolean hasRequests() {
- return mHasRequests.get();
+ public void sendNetworkScore(int score) {
+ queueOrSendMessage(EVENT_NETWORK_SCORE_CHANGED, new Integer(score));
}
- public boolean isConnectionRequested() {
- synchronized(mLockObj) {
- return mConnectionRequested;
- }
- }
-
-
- abstract protected void connect();
- abstract protected void disconnect();
+ /**
+ * Called when ConnectivityService has indicated they no longer want this network.
+ * The parent factory should (previously) have received indication of the change
+ * as well, either canceling NetworkRequests or altering their score such that this
+ * network won't be immediately requested again.
+ */
+ abstract protected void unwanted();
protected void log(String s) {
Log.d(LOG_TAG, "NetworkAgent: " + s);
diff --git a/core/java/android/net/NetworkFactory.java b/core/java/android/net/NetworkFactory.java
new file mode 100644
index 0000000..a20e8e7
--- /dev/null
+++ b/core/java/android/net/NetworkFactory.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.content.Context;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Messenger;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.util.AsyncChannel;
+import com.android.internal.util.Protocol;
+
+/**
+ * A NetworkFactory is an entity that creates NetworkAgent objects.
+ * The bearers register with ConnectivityService using {@link #register} and
+ * their factory will start receiving scored NetworkRequests. NetworkRequests
+ * can be filtered 3 ways: by NetworkCapabilities, by score and more complexly by
+ * overridden function. All of these can be dynamic - changing NetworkCapabilities
+ * or score forces re-evaluation of all current requests.
+ *
+ * If any requests pass the filter some overrideable functions will be called.
+ * If the bearer only cares about very simple start/stopNetwork callbacks, those
+ * functions can be overridden. If the bearer needs more interaction, it can
+ * override addNetworkRequest and removeNetworkRequest which will give it each
+ * request that passes their current filters.
+ * @hide
+ **/
+public class NetworkFactory extends Handler {
+ private static final boolean DBG = true;
+
+ private static final int BASE = Protocol.BASE_NETWORK_FACTORY;
+ /**
+ * Pass a network request to the bearer. If the bearer believes it can
+ * satisfy the request it should connect to the network and create a
+ * NetworkAgent. Once the NetworkAgent is fully functional it will
+ * register itself with ConnectivityService using registerNetworkAgent.
+ * If the bearer cannot immediately satisfy the request (no network,
+ * user disabled the radio, lower-scored network) it should remember
+ * any NetworkRequests it may be able to satisfy in the future. It may
+ * disregard any that it will never be able to service, for example
+ * those requiring a different bearer.
+ * msg.obj = NetworkRequest
+ * msg.arg1 = score - the score of the any network currently satisfying this
+ * request. If this bearer knows in advance it cannot
+ * exceed this score it should not try to connect, holding the request
+ * for the future.
+ * Note that subsequent events may give a different (lower
+ * or higher) score for this request, transmitted to each
+ * NetworkFactory through additional CMD_REQUEST_NETWORK msgs
+ * with the same NetworkRequest but an updated score.
+ * Also, network conditions may change for this bearer
+ * allowing for a better score in the future.
+ */
+ public static final int CMD_REQUEST_NETWORK = BASE;
+
+ /**
+ * Cancel a network request
+ * msg.obj = NetworkRequest
+ */
+ public static final int CMD_CANCEL_REQUEST = BASE + 1;
+
+ /**
+ * Internally used to set our best-guess score.
+ * msg.arg1 = new score
+ */
+ private static final int CMD_SET_SCORE = BASE + 2;
+
+ /**
+ * Internally used to set our current filter for coarse bandwidth changes with
+ * technology changes.
+ * msg.obj = new filter
+ */
+ private static final int CMD_SET_FILTER = BASE + 3;
+
+ private final Context mContext;
+ private final String LOG_TAG;
+
+ private final SparseArray<NetworkRequestInfo> mNetworkRequests =
+ new SparseArray<NetworkRequestInfo>();
+
+ private int mScore;
+ private NetworkCapabilities mCapabilityFilter;
+
+ private int mRefCount = 0;
+ private Messenger mMessenger = null;
+
+ public NetworkFactory(Looper looper, Context context, String logTag,
+ NetworkCapabilities filter) {
+ super(looper);
+ LOG_TAG = logTag;
+ mContext = context;
+ mCapabilityFilter = filter;
+ }
+
+ public void register() {
+ if (DBG) log("Registering NetworkFactory");
+ if (mMessenger == null) {
+ mMessenger = new Messenger(this);
+ ConnectivityManager.from(mContext).registerNetworkFactory(mMessenger, LOG_TAG);
+ }
+ }
+
+ public void unregister() {
+ if (DBG) log("Unregistering NetworkFactory");
+ if (mMessenger != null) {
+ ConnectivityManager.from(mContext).unregisterNetworkFactory(mMessenger);
+ mMessenger = null;
+ }
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case CMD_REQUEST_NETWORK: {
+ handleAddRequest((NetworkRequest)msg.obj, msg.arg1);
+ break;
+ }
+ case CMD_CANCEL_REQUEST: {
+ handleRemoveRequest((NetworkRequest) msg.obj);
+ break;
+ }
+ case CMD_SET_SCORE: {
+ handleSetScore(msg.arg1);
+ break;
+ }
+ case CMD_SET_FILTER: {
+ handleSetFilter((NetworkCapabilities) msg.obj);
+ break;
+ }
+ }
+ }
+
+ private class NetworkRequestInfo {
+ public final NetworkRequest request;
+ public int score;
+ public boolean requested; // do we have a request outstanding, limited by score
+
+ public NetworkRequestInfo(NetworkRequest request, int score) {
+ this.request = request;
+ this.score = score;
+ this.requested = false;
+ }
+ }
+
+ private void handleAddRequest(NetworkRequest request, int score) {
+ NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
+ if (n == null) {
+ n = new NetworkRequestInfo(request, score);
+ mNetworkRequests.put(n.request.requestId, n);
+ } else {
+ n.score = score;
+ }
+ if (DBG) log("got request " + request + " with score " + score);
+ if (DBG) log(" my score=" + mScore + ", my filter=" + mCapabilityFilter);
+
+ evalRequest(n);
+ }
+
+ private void handleRemoveRequest(NetworkRequest request) {
+ NetworkRequestInfo n = mNetworkRequests.get(request.requestId);
+ if (n != null && n.requested) {
+ mNetworkRequests.remove(request.requestId);
+ releaseNetworkFor(n.request);
+ }
+ }
+
+ private void handleSetScore(int score) {
+ mScore = score;
+ evalRequests();
+ }
+
+ private void handleSetFilter(NetworkCapabilities netCap) {
+ mCapabilityFilter = netCap;
+ evalRequests();
+ }
+
+ /**
+ * Overridable function to provide complex filtering.
+ * Called for every request every time a new NetworkRequest is seen
+ * and whenever the filterScore or filterNetworkCapabilities change.
+ *
+ * acceptRequest can be overriden to provide complex filter behavior
+ * for the incoming requests
+ *
+ * For output, this class will call {@link #needNetworkFor} and
+ * {@link #releaseNetworkFor} for every request that passes the filters.
+ * If you don't need to see every request, you can leave the base
+ * implementations of those two functions and instead override
+ * {@link #startNetwork} and {@link #stopNetwork}.
+ *
+ * If you want to see every score fluctuation on every request, set
+ * your score filter to a very high number and watch {@link #needNetworkFor}.
+ *
+ * @return {@code true} to accept the request.
+ */
+ public boolean acceptRequest(NetworkRequest request, int score) {
+ return true;
+ }
+
+ private void evalRequest(NetworkRequestInfo n) {
+ if (n.requested == false && n.score < mScore &&
+ n.request.networkCapabilities.satisfiedByNetworkCapabilities(
+ mCapabilityFilter) && acceptRequest(n.request, n.score)) {
+ needNetworkFor(n.request, n.score);
+ n.requested = true;
+ } else if (n.requested == true &&
+ (n.score > mScore || n.request.networkCapabilities.satisfiedByNetworkCapabilities(
+ mCapabilityFilter) == false || acceptRequest(n.request, n.score) == false)) {
+ releaseNetworkFor(n.request);
+ n.requested = false;
+ }
+ }
+
+ private void evalRequests() {
+ for (int i = 0; i < mNetworkRequests.size(); i++) {
+ NetworkRequestInfo n = mNetworkRequests.valueAt(i);
+
+ evalRequest(n);
+ }
+ }
+
+ // override to do simple mode (request independent)
+ protected void startNetwork() { }
+ protected void stopNetwork() { }
+
+ // override to do fancier stuff
+ protected void needNetworkFor(NetworkRequest networkRequest, int score) {
+ if (++mRefCount == 1) startNetwork();
+ }
+
+ protected void releaseNetworkFor(NetworkRequest networkRequest) {
+ if (--mRefCount == 0) stopNetwork();
+ }
+
+
+ public void addNetworkRequest(NetworkRequest networkRequest, int score) {
+ sendMessage(obtainMessage(CMD_REQUEST_NETWORK,
+ new NetworkRequestInfo(networkRequest, score)));
+ }
+
+ public void removeNetworkRequest(NetworkRequest networkRequest) {
+ sendMessage(obtainMessage(CMD_CANCEL_REQUEST, networkRequest));
+ }
+
+ public void setScoreFilter(int score) {
+ sendMessage(obtainMessage(CMD_SET_SCORE, score, 0));
+ }
+
+ public void setCapabilityFilter(NetworkCapabilities netCap) {
+ sendMessage(obtainMessage(CMD_SET_FILTER, new NetworkCapabilities(netCap)));
+ }
+
+ protected void log(String s) {
+ Log.d(LOG_TAG, s);
+ }
+}
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 9e656ee..d279412 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -188,6 +188,15 @@ public class NetworkInfo implements Parcelable {
}
/**
+ * @hide
+ */
+ public void setType(int type) {
+ synchronized (this) {
+ mNetworkType = type;
+ }
+ }
+
+ /**
* Return a network-type-specific integer describing the subtype
* of the network.
* @return the network subtype
@@ -198,7 +207,10 @@ public class NetworkInfo implements Parcelable {
}
}
- void setSubtype(int subtype, String subtypeName) {
+ /**
+ * @hide
+ */
+ public void setSubtype(int subtype, String subtypeName) {
synchronized (this) {
mSubtype = subtype;
mSubtypeName = subtypeName;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 480cb05..47377e9 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -47,19 +47,19 @@ public class NetworkRequest implements Parcelable {
public final int requestId;
/**
- * Set for legacy requests and the default.
+ * Set for legacy requests and the default. Set to TYPE_NONE for none.
* Causes CONNECTIVITY_ACTION broadcasts to be sent.
* @hide
*/
- public final boolean needsBroadcasts;
+ public final int legacyType;
/**
* @hide
*/
- public NetworkRequest(NetworkCapabilities nc, boolean needsBroadcasts, int rId) {
+ public NetworkRequest(NetworkCapabilities nc, int legacyType, int rId) {
requestId = rId;
networkCapabilities = nc;
- this.needsBroadcasts = needsBroadcasts;
+ this.legacyType = legacyType;
}
/**
@@ -68,7 +68,7 @@ public class NetworkRequest implements Parcelable {
public NetworkRequest(NetworkRequest that) {
networkCapabilities = new NetworkCapabilities(that.networkCapabilities);
requestId = that.requestId;
- needsBroadcasts = that.needsBroadcasts;
+ this.legacyType = that.legacyType;
}
// implement the Parcelable interface
@@ -77,16 +77,16 @@ public class NetworkRequest implements Parcelable {
}
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(networkCapabilities, flags);
- dest.writeInt(needsBroadcasts ? 1 : 0);
+ dest.writeInt(legacyType);
dest.writeInt(requestId);
}
public static final Creator<NetworkRequest> CREATOR =
new Creator<NetworkRequest>() {
public NetworkRequest createFromParcel(Parcel in) {
NetworkCapabilities nc = (NetworkCapabilities)in.readParcelable(null);
- boolean needsBroadcasts = (in.readInt() == 1);
+ int legacyType = in.readInt();
int requestId = in.readInt();
- NetworkRequest result = new NetworkRequest(nc, needsBroadcasts, requestId);
+ NetworkRequest result = new NetworkRequest(nc, legacyType, requestId);
return result;
}
public NetworkRequest[] newArray(int size) {
@@ -95,14 +95,14 @@ public class NetworkRequest implements Parcelable {
};
public String toString() {
- return "NetworkRequest [ id=" + requestId + ", needsBroadcasts=" + needsBroadcasts +
+ return "NetworkRequest [ id=" + requestId + ", legacyType=" + legacyType +
", " + networkCapabilities.toString() + " ]";
}
public boolean equals(Object obj) {
if (obj instanceof NetworkRequest == false) return false;
NetworkRequest that = (NetworkRequest)obj;
- return (that.needsBroadcasts == this.needsBroadcasts &&
+ return (that.legacyType == this.legacyType &&
that.requestId == this.requestId &&
((that.networkCapabilities == null && this.networkCapabilities == null) ||
(that.networkCapabilities != null &&
@@ -110,7 +110,7 @@ public class NetworkRequest implements Parcelable {
}
public int hashCode() {
- return requestId + (needsBroadcasts ? 1013 : 2026) +
+ return requestId + (legacyType * 1013) +
(networkCapabilities.hashCode() * 1051);
}
}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index bc57b33..e627d49 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -931,6 +931,14 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ /**
+ * Don't allow any more batching in to the current history event. This
+ * is called when printing partial histories, so to ensure that the next
+ * history event will go in to a new batch after what was printed in the
+ * last partial history.
+ */
+ public abstract void commitCurrentHistoryBatchLocked();
+
public abstract int getHistoryTotalSize();
public abstract int getHistoryUsedSize();
@@ -3366,6 +3374,7 @@ public abstract class BatteryStats implements Parcelable {
}
}
if (histStart >= 0) {
+ commitCurrentHistoryBatchLocked();
pw.print(checkin ? "NEXT: " : " NEXT: "); pw.println(lastTime+1);
}
}
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 112ec1d..86c749a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -156,6 +156,12 @@ public class Process {
public static final int LAST_ISOLATED_UID = 99999;
/**
+ * Defines the gid shared by all applications running under the same profile.
+ * @hide
+ */
+ public static final int SHARED_USER_GID = 9997;
+
+ /**
* First gid for applications to share resources. Used when forward-locking
* is enabled but all UserHandles need to be able to read the resources.
* @hide
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index 6e693a4..914c170 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -145,6 +145,14 @@ public final class UserHandle implements Parcelable {
}
/**
+ * Returns the gid shared between all apps with this userId.
+ * @hide
+ */
+ public static final int getUserGid(int userId) {
+ return getUid(userId, Process.SHARED_USER_GID);
+ }
+
+ /**
* Returns the shared app gid for a given uid or appId.
* @hide
*/
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
index d02fc7b..68a3d30 100644
--- a/core/java/android/service/notification/ZenModeConfig.java
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -21,6 +21,7 @@ import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
+import android.util.Slog;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
@@ -37,6 +38,7 @@ import java.util.Objects;
* @hide
*/
public class ZenModeConfig implements Parcelable {
+ private static String TAG = "ZenModeConfig";
public static final String SLEEP_MODE_NIGHTS = "nights";
public static final String SLEEP_MODE_WEEKNIGHTS = "weeknights";
@@ -65,6 +67,9 @@ public class ZenModeConfig implements Parcelable {
private static final String CONDITION_ATT_COMPONENT = "component";
private static final String CONDITION_ATT_ID = "id";
+ private static final String EXIT_CONDITION_TAG = "exitCondition";
+ private static final String EXIT_CONDITION_ATT_ID = "id";
+
public boolean allowCalls;
public boolean allowMessages;
public int allowFrom = SOURCE_ANYONE;
@@ -76,6 +81,7 @@ public class ZenModeConfig implements Parcelable {
public int sleepEndMinute;
public ComponentName[] conditionComponents;
public Uri[] conditionIds;
+ public Uri exitConditionId;
public ZenModeConfig() { }
@@ -100,6 +106,7 @@ public class ZenModeConfig implements Parcelable {
source.readTypedArray(conditionIds, Uri.CREATOR);
}
allowFrom = source.readInt();
+ exitConditionId = source.readParcelable(null);
}
@Override
@@ -129,6 +136,7 @@ public class ZenModeConfig implements Parcelable {
dest.writeInt(0);
}
dest.writeInt(allowFrom);
+ dest.writeParcelable(exitConditionId, 0);
}
@Override
@@ -144,6 +152,7 @@ public class ZenModeConfig implements Parcelable {
.append(conditionComponents == null ? null : TextUtils.join(",", conditionComponents))
.append(",conditionIds=")
.append(conditionIds == null ? null : TextUtils.join(",", conditionIds))
+ .append(",exitConditionId=").append(exitConditionId)
.append(']').toString();
}
@@ -174,14 +183,16 @@ public class ZenModeConfig implements Parcelable {
&& other.sleepEndHour == sleepEndHour
&& other.sleepEndMinute == sleepEndMinute
&& Objects.deepEquals(other.conditionComponents, conditionComponents)
- && Objects.deepEquals(other.conditionIds, conditionIds);
+ && Objects.deepEquals(other.conditionIds, conditionIds)
+ && Objects.equals(other.exitConditionId, exitConditionId);
}
@Override
public int hashCode() {
return Objects.hash(allowCalls, allowMessages, allowFrom, sleepMode,
sleepStartHour, sleepStartMinute, sleepEndHour, sleepEndMinute,
- Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds));
+ Arrays.hashCode(conditionComponents), Arrays.hashCode(conditionIds),
+ exitConditionId);
}
public boolean isValid() {
@@ -239,6 +250,8 @@ public class ZenModeConfig implements Parcelable {
conditionComponents.add(component);
conditionIds.add(conditionId);
}
+ } else if (EXIT_CONDITION_TAG.equals(tag)) {
+ rt.exitConditionId = safeUri(parser, EXIT_CONDITION_ATT_ID);
}
}
}
@@ -275,6 +288,11 @@ public class ZenModeConfig implements Parcelable {
out.endTag(null, CONDITION_TAG);
}
}
+ if (exitConditionId != null) {
+ out.startTag(null, EXIT_CONDITION_TAG);
+ out.attribute(null, EXIT_CONDITION_ATT_ID, exitConditionId.toString());
+ out.endTag(null, EXIT_CONDITION_TAG);
+ }
out.endTag(null, ZEN_TAG);
}
@@ -338,4 +356,33 @@ public class ZenModeConfig implements Parcelable {
return new ZenModeConfig[size];
}
};
+
+ // Built-in countdown conditions, e.g. condition://android/countdown/1399917958951
+
+ private static final String COUNTDOWN_AUTHORITY = "android";
+ private static final String COUNTDOWN_PATH = "countdown";
+
+ public static Uri toCountdownConditionId(long time) {
+ return new Uri.Builder().scheme(Condition.SCHEME)
+ .authority(COUNTDOWN_AUTHORITY)
+ .appendPath(COUNTDOWN_PATH)
+ .appendPath(Long.toString(time))
+ .build();
+ }
+
+ public static long tryParseCountdownConditionId(Uri conditionId) {
+ if (!Condition.isValidId(conditionId, COUNTDOWN_AUTHORITY)) return 0;
+ if (conditionId.getPathSegments().size() != 2
+ || !COUNTDOWN_PATH.equals(conditionId.getPathSegments().get(0))) return 0;
+ try {
+ return Long.parseLong(conditionId.getPathSegments().get(1));
+ } catch (RuntimeException e) {
+ Slog.w(TAG, "Error parsing countdown condition: " + conditionId, e);
+ return 0;
+ }
+ }
+
+ public static boolean isValidCountdownConditionId(Uri conditionId) {
+ return tryParseCountdownConditionId(conditionId) != 0;
+ }
}
diff --git a/core/java/android/service/trust/TrustAgentService.java b/core/java/android/service/trust/TrustAgentService.java
index 98f70f4..a6cddae 100644
--- a/core/java/android/service/trust/TrustAgentService.java
+++ b/core/java/android/service/trust/TrustAgentService.java
@@ -33,6 +33,8 @@ import android.util.Slog;
* A service that notifies the system about whether it believes the environment of the device
* to be trusted.
*
+ * <p>Trust agents may only be provided by the platform.</p>
+ *
* <p>To extend this class, you must declare the service in your manifest file with
* the {@link android.Manifest.permission#BIND_TRUST_AGENT} permission
* and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
diff --git a/core/java/android/speech/tts/TextToSpeechClient.java b/core/java/android/speech/tts/TextToSpeechClient.java
index e17b498..0c0be83 100644
--- a/core/java/android/speech/tts/TextToSpeechClient.java
+++ b/core/java/android/speech/tts/TextToSpeechClient.java
@@ -793,15 +793,14 @@ public class TextToSpeechClient {
return mService != null && mEstablished;
}
- boolean runAction(Action action) {
+ <T> ActionResult<T> runAction(Action<T> action) {
synchronized (mLock) {
try {
- action.run(mService);
- return true;
+ return new ActionResult<T>(true, action.run(mService));
} catch (Exception ex) {
Log.e(TAG, action.getName() + " failed", ex);
disconnect();
- return false;
+ return new ActionResult<T>(false);
}
}
}
@@ -821,7 +820,7 @@ public class TextToSpeechClient {
}
}
- private abstract class Action {
+ private abstract class Action<T> {
private final String mName;
public Action(String name) {
@@ -829,7 +828,21 @@ public class TextToSpeechClient {
}
public String getName() {return mName;}
- abstract void run(ITextToSpeechService service) throws RemoteException;
+ abstract T run(ITextToSpeechService service) throws RemoteException;
+ }
+
+ private class ActionResult<T> {
+ boolean mSuccess;
+ T mResult;
+
+ ActionResult(boolean success) {
+ mSuccess = success;
+ }
+
+ ActionResult(boolean success, T result) {
+ mSuccess = success;
+ mResult = result;
+ }
}
private IBinder getCallerIdentity() {
@@ -839,18 +852,17 @@ public class TextToSpeechClient {
return null;
}
- private boolean runAction(Action action) {
+ private <T> ActionResult<T> runAction(Action<T> action) {
synchronized (mLock) {
if (mServiceConnection == null) {
Log.w(TAG, action.getName() + " failed: not bound to TTS engine");
- return false;
+ return new ActionResult<T>(false);
}
if (!mServiceConnection.isEstablished()) {
Log.w(TAG, action.getName() + " failed: not fully bound to TTS engine");
- return false;
+ return new ActionResult<T>(false);
}
- mServiceConnection.runAction(action);
- return true;
+ return mServiceConnection.runAction(action);
}
}
@@ -861,13 +873,14 @@ public class TextToSpeechClient {
* other utterances in the queue.
*/
public void stop() {
- runAction(new Action(ACTION_STOP_NAME) {
+ runAction(new Action<Void>(ACTION_STOP_NAME) {
@Override
- public void run(ITextToSpeechService service) throws RemoteException {
+ public Void run(ITextToSpeechService service) throws RemoteException {
if (service.stop(getCallerIdentity()) != Status.SUCCESS) {
Log.e(TAG, "Stop failed");
}
mCallbacks.clear();
+ return null;
}
});
}
@@ -915,9 +928,9 @@ public class TextToSpeechClient {
final UtteranceId utteranceId,
final RequestConfig config,
final RequestCallbacks callbacks) {
- runAction(new Action(ACTION_QUEUE_SPEAK_NAME) {
+ runAction(new Action<Void>(ACTION_QUEUE_SPEAK_NAME) {
@Override
- public void run(ITextToSpeechService service) throws RemoteException {
+ public Void run(ITextToSpeechService service) throws RemoteException {
RequestCallbacks c = mDefaultRequestCallbacks;
if (callbacks != null) {
c = callbacks;
@@ -925,7 +938,7 @@ public class TextToSpeechClient {
int addCallbackStatus = addCallback(utteranceId, c);
if (addCallbackStatus != Status.SUCCESS) {
c.onSynthesisFailure(utteranceId, Status.ERROR_INVALID_REQUEST);
- return;
+ return null;
}
int queueResult = service.speakV2(
@@ -934,6 +947,7 @@ public class TextToSpeechClient {
if (queueResult != Status.SUCCESS) {
removeCallbackAndErr(utteranceId.toUniqueString(), queueResult);
}
+ return null;
}
});
}
@@ -984,9 +998,9 @@ public class TextToSpeechClient {
final UtteranceId utteranceId,
final File outputFile, final RequestConfig config,
final RequestCallbacks callbacks) {
- runAction(new Action(ACTION_QUEUE_SYNTHESIZE_TO_FILE) {
+ runAction(new Action<Void>(ACTION_QUEUE_SYNTHESIZE_TO_FILE) {
@Override
- public void run(ITextToSpeechService service) throws RemoteException {
+ public Void run(ITextToSpeechService service) throws RemoteException {
RequestCallbacks c = mDefaultRequestCallbacks;
if (callbacks != null) {
c = callbacks;
@@ -994,7 +1008,7 @@ public class TextToSpeechClient {
int addCallbackStatus = addCallback(utteranceId, c);
if (addCallbackStatus != Status.SUCCESS) {
c.onSynthesisFailure(utteranceId, Status.ERROR_INVALID_REQUEST);
- return;
+ return null;
}
ParcelFileDescriptor fileDescriptor = null;
@@ -1002,7 +1016,7 @@ public class TextToSpeechClient {
if (outputFile.exists() && !outputFile.canWrite()) {
Log.e(TAG, "No permissions to write to " + outputFile);
removeCallbackAndErr(utteranceId.toUniqueString(), Status.ERROR_OUTPUT);
- return;
+ return null;
}
fileDescriptor = ParcelFileDescriptor.open(outputFile,
ParcelFileDescriptor.MODE_WRITE_ONLY |
@@ -1023,6 +1037,7 @@ public class TextToSpeechClient {
Log.e(TAG, "Closing file " + outputFile + " failed", e);
removeCallbackAndErr(utteranceId.toUniqueString(), Status.ERROR_OUTPUT);
}
+ return null;
}
});
}
@@ -1050,9 +1065,9 @@ public class TextToSpeechClient {
*/
public void queueSilence(final long durationInMs, final UtteranceId utteranceId,
final RequestCallbacks callbacks) {
- runAction(new Action(ACTION_QUEUE_SILENCE_NAME) {
+ runAction(new Action<Void>(ACTION_QUEUE_SILENCE_NAME) {
@Override
- public void run(ITextToSpeechService service) throws RemoteException {
+ public Void run(ITextToSpeechService service) throws RemoteException {
RequestCallbacks c = mDefaultRequestCallbacks;
if (callbacks != null) {
c = callbacks;
@@ -1068,6 +1083,7 @@ public class TextToSpeechClient {
if (queueResult != Status.SUCCESS) {
removeCallbackAndErr(utteranceId.toUniqueString(), queueResult);
}
+ return null;
}
});
}
@@ -1091,9 +1107,9 @@ public class TextToSpeechClient {
*/
public void queueAudio(final Uri audioUrl, final UtteranceId utteranceId,
final RequestConfig config, final RequestCallbacks callbacks) {
- runAction(new Action(ACTION_QUEUE_AUDIO_NAME) {
+ runAction(new Action<Void>(ACTION_QUEUE_AUDIO_NAME) {
@Override
- public void run(ITextToSpeechService service) throws RemoteException {
+ public Void run(ITextToSpeechService service) throws RemoteException {
RequestCallbacks c = mDefaultRequestCallbacks;
if (callbacks != null) {
c = callbacks;
@@ -1109,10 +1125,35 @@ public class TextToSpeechClient {
if (queueResult != Status.SUCCESS) {
removeCallbackAndErr(utteranceId.toUniqueString(), queueResult);
}
+ return null;
+ }
+ });
+ }
+
+ private static final String ACTION_IS_SPEAKING_NAME = "isSpeaking";
+
+ /**
+ * Checks whether the TTS engine is busy speaking. Note that a speech item is
+ * considered complete once it's audio data has been sent to the audio mixer, or
+ * written to a file. There might be a finite lag between this point, and when
+ * the audio hardware completes playback.
+ *
+ * @return {@code true} if the TTS engine is speaking.
+ */
+ public boolean isSpeaking() {
+ ActionResult<Boolean> result = runAction(new Action<Boolean>(ACTION_IS_SPEAKING_NAME) {
+ @Override
+ public Boolean run(ITextToSpeechService service) throws RemoteException {
+ return service.isSpeaking();
}
});
+ if (!result.mSuccess) {
+ return false; // We can't really say, return false
+ }
+ return result.mResult;
}
+
class InternalHandler extends Handler {
final static int WHAT_ENGINE_STATUS_CHANGED = 1;
final static int WHAT_SERVICE_DISCONNECTED = 2;
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 424d860..5056097 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -75,22 +75,10 @@ class GLES20Canvas extends HardwareCanvas {
// Constructors
///////////////////////////////////////////////////////////////////////////
- /**
- * Creates a canvas to render directly on screen.
- */
- GLES20Canvas(boolean translucent) {
- this(false, translucent);
- }
-
- protected GLES20Canvas(boolean record, boolean translucent) {
- mOpaque = !translucent;
-
- if (record) {
- mRenderer = nCreateDisplayListRenderer();
- } else {
- mRenderer = nCreateRenderer();
- }
-
+ // TODO: Merge with GLES20RecordingCanvas
+ protected GLES20Canvas() {
+ mOpaque = false;
+ mRenderer = nCreateDisplayListRenderer();
setupFinalizer();
}
@@ -102,7 +90,6 @@ class GLES20Canvas extends HardwareCanvas {
}
}
- private static native long nCreateRenderer();
private static native long nCreateDisplayListRenderer();
private static native void nResetDisplayListRenderer(long renderer);
private static native void nDestroyRenderer(long renderer);
@@ -131,36 +118,6 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nSetProperty(String name, String value);
///////////////////////////////////////////////////////////////////////////
- // Hardware layers
- ///////////////////////////////////////////////////////////////////////////
-
- @Override
- void pushLayerUpdate(HardwareLayer layer) {
- nPushLayerUpdate(mRenderer, layer.getLayer());
- }
-
- @Override
- void cancelLayerUpdate(HardwareLayer layer) {
- nCancelLayerUpdate(mRenderer, layer.getLayer());
- }
-
- @Override
- void flushLayerUpdates() {
- nFlushLayerUpdates(mRenderer);
- }
-
- @Override
- void clearLayerUpdates() {
- nClearLayerUpdates(mRenderer);
- }
-
- static native boolean nCopyLayer(long layerId, long bitmap);
- private static native void nClearLayerUpdates(long renderer);
- private static native void nFlushLayerUpdates(long renderer);
- private static native void nPushLayerUpdate(long renderer, long layer);
- private static native void nCancelLayerUpdate(long renderer, long layer);
-
- ///////////////////////////////////////////////////////////////////////////
// Canvas management
///////////////////////////////////////////////////////////////////////////
@@ -234,20 +191,6 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nFinish(long renderer);
- /**
- * Returns the size of the stencil buffer required by the underlying
- * implementation.
- *
- * @return The minimum number of bits the stencil buffer must. Always >= 0.
- *
- * @hide
- */
- public static int getStencilSize() {
- return nGetStencilSize();
- }
-
- private static native int nGetStencilSize();
-
///////////////////////////////////////////////////////////////////////////
// Functor
///////////////////////////////////////////////////////////////////////////
@@ -284,49 +227,6 @@ class GLES20Canvas extends HardwareCanvas {
*/
static final int FLUSH_CACHES_FULL = 2;
- /**
- * Flush caches to reclaim as much memory as possible. The amount of memory
- * to reclaim is indicate by the level parameter.
- *
- * The level can be one of {@link #FLUSH_CACHES_MODERATE} or
- * {@link #FLUSH_CACHES_FULL}.
- *
- * @param level Hint about the amount of memory to reclaim
- */
- static void flushCaches(int level) {
- nFlushCaches(level);
- }
-
- private static native void nFlushCaches(int level);
-
- /**
- * Release all resources associated with the underlying caches. This should
- * only be called after a full flushCaches().
- *
- * @hide
- */
- static void terminateCaches() {
- nTerminateCaches();
- }
-
- private static native void nTerminateCaches();
-
- static boolean initCaches() {
- return nInitCaches();
- }
-
- private static native boolean nInitCaches();
-
- ///////////////////////////////////////////////////////////////////////////
- // Atlas
- ///////////////////////////////////////////////////////////////////////////
-
- static void initAtlas(GraphicBuffer buffer, long[] map) {
- nInitAtlas(buffer, map, map.length);
- }
-
- private static native void nInitAtlas(GraphicBuffer buffer, long[] map, int count);
-
///////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////
@@ -899,12 +799,6 @@ class GLES20Canvas extends HardwareCanvas {
private static native void nDrawPath(long renderer, long path, long paint);
private static native void nDrawRects(long renderer, long region, long paint);
- void drawRects(float[] rects, int count, Paint paint) {
- nDrawRects(mRenderer, rects, count, paint.mNativePaint);
- }
-
- private static native void nDrawRects(long renderer, float[] rects, int count, long paint);
-
@Override
public void drawPicture(Picture picture) {
if (picture.createdFromStream) {
diff --git a/core/java/android/view/GLES20RecordingCanvas.java b/core/java/android/view/GLES20RecordingCanvas.java
index a94ec3a..b2961e5 100644
--- a/core/java/android/view/GLES20RecordingCanvas.java
+++ b/core/java/android/view/GLES20RecordingCanvas.java
@@ -36,7 +36,7 @@ class GLES20RecordingCanvas extends GLES20Canvas {
RenderNode mNode;
private GLES20RecordingCanvas() {
- super(true, true);
+ super();
}
static GLES20RecordingCanvas obtain(@NonNull RenderNode node) {
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
deleted file mode 100644
index f1163e2..0000000
--- a/core/java/android/view/GLRenderer.java
+++ /dev/null
@@ -1,1521 +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.view;
-
-import static javax.microedition.khronos.egl.EGL10.EGL_ALPHA_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_BAD_NATIVE_WINDOW;
-import static javax.microedition.khronos.egl.EGL10.EGL_BLUE_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_CONFIG_CAVEAT;
-import static javax.microedition.khronos.egl.EGL10.EGL_DEFAULT_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_DEPTH_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_DRAW;
-import static javax.microedition.khronos.egl.EGL10.EGL_GREEN_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_HEIGHT;
-import static javax.microedition.khronos.egl.EGL10.EGL_NONE;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_CONTEXT;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_DISPLAY;
-import static javax.microedition.khronos.egl.EGL10.EGL_NO_SURFACE;
-import static javax.microedition.khronos.egl.EGL10.EGL_RED_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_RENDERABLE_TYPE;
-import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLES;
-import static javax.microedition.khronos.egl.EGL10.EGL_SAMPLE_BUFFERS;
-import static javax.microedition.khronos.egl.EGL10.EGL_STENCIL_SIZE;
-import static javax.microedition.khronos.egl.EGL10.EGL_SUCCESS;
-import static javax.microedition.khronos.egl.EGL10.EGL_SURFACE_TYPE;
-import static javax.microedition.khronos.egl.EGL10.EGL_WIDTH;
-import static javax.microedition.khronos.egl.EGL10.EGL_WINDOW_BIT;
-
-import android.content.ComponentCallbacks2;
-import android.graphics.Bitmap;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.SurfaceTexture;
-import android.opengl.EGL14;
-import android.opengl.GLUtils;
-import android.opengl.ManagedEGLContext;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Looper;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-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 java.io.FileDescriptor;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.locks.ReentrantLock;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGL11;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-import javax.microedition.khronos.opengles.GL;
-
-/**
- * Hardware renderer using OpenGL
- *
- * @hide
- */
-public class GLRenderer extends HardwareRenderer {
- static final int SURFACE_STATE_ERROR = 0;
- static final int SURFACE_STATE_SUCCESS = 1;
- static final int SURFACE_STATE_UPDATED = 2;
-
- static final int FUNCTOR_PROCESS_DELAY = 4;
-
- /**
- * Number of frames to profile.
- */
- private static final int PROFILE_MAX_FRAMES = 128;
-
- /**
- * Number of floats per profiled frame.
- */
- private static final int PROFILE_FRAME_DATA_COUNT = 3;
-
- private static final int PROFILE_DRAW_MARGIN = 0;
- private static final int PROFILE_DRAW_WIDTH = 3;
- private static final int[] PROFILE_DRAW_COLORS = { 0xcf3e66cc, 0xcfdc3912, 0xcfe69800 };
- private static final int PROFILE_DRAW_CURRENT_FRAME_COLOR = 0xcf5faa4d;
- private static final int PROFILE_DRAW_THRESHOLD_COLOR = 0xff5faa4d;
- private static final int PROFILE_DRAW_THRESHOLD_STROKE_WIDTH = 2;
- private static final int PROFILE_DRAW_DP_PER_MS = 7;
-
- private static final String[] VISUALIZERS = {
- PROFILE_PROPERTY_VISUALIZE_BARS,
- };
-
- private static final String[] OVERDRAW = {
- OVERDRAW_PROPERTY_SHOW,
- };
- private static final int GL_VERSION = 2;
-
- static EGL10 sEgl;
- static EGLDisplay sEglDisplay;
- static EGLConfig sEglConfig;
- static final Object[] sEglLock = new Object[0];
- int mWidth = -1, mHeight = -1;
-
- static final ThreadLocal<ManagedEGLContext> sEglContextStorage
- = new ThreadLocal<ManagedEGLContext>();
-
- EGLContext mEglContext;
- Thread mEglThread;
-
- EGLSurface mEglSurface;
-
- GL mGl;
- HardwareCanvas mCanvas;
-
- String mName;
-
- long mFrameCount;
- Paint mDebugPaint;
-
- static boolean sDirtyRegions;
- static final boolean sDirtyRegionsRequested;
- static {
- String dirtyProperty = SystemProperties.get(RENDER_DIRTY_REGIONS_PROPERTY, "true");
- //noinspection PointlessBooleanExpression,ConstantConditions
- sDirtyRegions = "true".equalsIgnoreCase(dirtyProperty);
- sDirtyRegionsRequested = sDirtyRegions;
- }
-
- boolean mDirtyRegionsEnabled;
- boolean mUpdateDirtyRegions;
-
- boolean mProfileEnabled;
- int mProfileVisualizerType = -1;
- float[] mProfileData;
- ReentrantLock mProfileLock;
- int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
-
- GraphDataProvider mDebugDataProvider;
- float[][] mProfileShapes;
- Paint mProfilePaint;
-
- boolean mDebugDirtyRegions;
- int mDebugOverdraw = -1;
-
- final boolean mTranslucent;
-
- private boolean mDestroyed;
-
- private final Rect mRedrawClip = new Rect();
-
- private final int[] mSurfaceSize = new int[2];
-
- private long mDrawDelta = Long.MAX_VALUE;
-
- private GLES20Canvas mGlCanvas;
-
- private DisplayMetrics mDisplayMetrics;
-
- private static EGLSurface sPbuffer;
- private static final Object[] sPbufferLock = new Object[0];
-
- private List<HardwareLayer> mLayerUpdates = new ArrayList<HardwareLayer>();
-
- private static class GLRendererEglContext extends ManagedEGLContext {
- final Handler mHandler = new Handler();
-
- public GLRendererEglContext(EGLContext context) {
- super(context);
- }
-
- @Override
- public void onTerminate(final EGLContext eglContext) {
- // Make sure we do this on the correct thread.
- if (mHandler.getLooper() != Looper.myLooper()) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- onTerminate(eglContext);
- }
- });
- return;
- }
-
- synchronized (sEglLock) {
- if (sEgl == null) return;
-
- if (EGLImpl.getInitCount(sEglDisplay) == 1) {
- usePbufferSurface(eglContext);
- GLES20Canvas.terminateCaches();
-
- sEgl.eglDestroyContext(sEglDisplay, eglContext);
- sEglContextStorage.set(null);
- sEglContextStorage.remove();
-
- sEgl.eglDestroySurface(sEglDisplay, sPbuffer);
- sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
- EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
- sEgl.eglReleaseThread();
- sEgl.eglTerminate(sEglDisplay);
-
- sEgl = null;
- sEglDisplay = null;
- sEglConfig = null;
- sPbuffer = null;
- }
- }
- }
- }
-
- HardwareCanvas createCanvas() {
- return mGlCanvas = new GLES20Canvas(mTranslucent);
- }
-
- ManagedEGLContext createManagedContext(EGLContext eglContext) {
- return new GLRendererEglContext(mEglContext);
- }
-
- int[] getConfig(boolean dirtyRegions) {
- //noinspection PointlessBooleanExpression,ConstantConditions
- final int stencilSize = GLES20Canvas.getStencilSize();
- final int swapBehavior = dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
-
- return new int[] {
- EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
- EGL_RED_SIZE, 8,
- EGL_GREEN_SIZE, 8,
- EGL_BLUE_SIZE, 8,
- EGL_ALPHA_SIZE, 8,
- EGL_DEPTH_SIZE, 0,
- EGL_CONFIG_CAVEAT, EGL_NONE,
- EGL_STENCIL_SIZE, stencilSize,
- EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
- EGL_NONE
- };
- }
-
- void initCaches() {
- if (GLES20Canvas.initCaches()) {
- // Caches were (re)initialized, rebind atlas
- initAtlas();
- }
- }
-
- void initAtlas() {
- IBinder binder = ServiceManager.getService("assetatlas");
- if (binder == null) return;
-
- IAssetAtlas atlas = IAssetAtlas.Stub.asInterface(binder);
- try {
- if (atlas.isCompatible(android.os.Process.myPpid())) {
- GraphicBuffer buffer = atlas.getBuffer();
- if (buffer != null) {
- long[] map = atlas.getMap();
- if (map != null) {
- GLES20Canvas.initAtlas(buffer, map);
- }
- // If IAssetAtlas is not the same class as the IBinder
- // we are using a remote service and we can safely
- // destroy the graphic buffer
- if (atlas.getClass() != binder.getClass()) {
- buffer.destroy();
- }
- }
- }
- } catch (RemoteException e) {
- Log.w(LOG_TAG, "Could not acquire atlas", e);
- }
- }
-
- boolean canDraw() {
- return mGl != null && mCanvas != null && mGlCanvas != null;
- }
-
- int onPreDraw(Rect dirty) {
- return mGlCanvas.onPreDraw(dirty);
- }
-
- void onPostDraw() {
- mGlCanvas.onPostDraw();
- }
-
- void drawProfileData(View.AttachInfo attachInfo) {
- if (mDebugDataProvider != null) {
- final GraphDataProvider provider = mDebugDataProvider;
- initProfileDrawData(attachInfo, provider);
-
- final int height = provider.getVerticalUnitSize();
- final int margin = provider.getHorizontaUnitMargin();
- final int width = provider.getHorizontalUnitSize();
-
- int x = 0;
- int count = 0;
- int current = 0;
-
- final float[] data = provider.getData();
- final int elementCount = provider.getElementCount();
- final int graphType = provider.getGraphType();
-
- int totalCount = provider.getFrameCount() * elementCount;
- if (graphType == GraphDataProvider.GRAPH_TYPE_LINES) {
- totalCount -= elementCount;
- }
-
- for (int i = 0; i < totalCount; i += elementCount) {
- if (data[i] < 0.0f) break;
-
- int index = count * 4;
- if (i == provider.getCurrentFrame() * elementCount) current = index;
-
- x += margin;
- int x2 = x + width;
-
- int y2 = mHeight;
- int y1 = (int) (y2 - data[i] * height);
-
- switch (graphType) {
- case GraphDataProvider.GRAPH_TYPE_BARS: {
- for (int j = 0; j < elementCount; j++) {
- //noinspection MismatchedReadAndWriteOfArray
- final float[] r = mProfileShapes[j];
- r[index] = x;
- r[index + 1] = y1;
- r[index + 2] = x2;
- r[index + 3] = y2;
-
- y2 = y1;
- if (j < elementCount - 1) {
- y1 = (int) (y2 - data[i + j + 1] * height);
- }
- }
- } break;
- case GraphDataProvider.GRAPH_TYPE_LINES: {
- for (int j = 0; j < elementCount; j++) {
- //noinspection MismatchedReadAndWriteOfArray
- final float[] r = mProfileShapes[j];
- r[index] = (x + x2) * 0.5f;
- r[index + 1] = index == 0 ? y1 : r[index - 1];
- r[index + 2] = r[index] + width;
- r[index + 3] = y1;
-
- y2 = y1;
- if (j < elementCount - 1) {
- y1 = (int) (y2 - data[i + j + 1] * height);
- }
- }
- } break;
- }
-
-
- x += width;
- count++;
- }
-
- x += margin;
-
- drawGraph(graphType, count);
- drawCurrentFrame(graphType, current);
- drawThreshold(x, height);
- }
- }
-
- private void drawGraph(int graphType, int count) {
- for (int i = 0; i < mProfileShapes.length; i++) {
- mDebugDataProvider.setupGraphPaint(mProfilePaint, i);
- switch (graphType) {
- case GraphDataProvider.GRAPH_TYPE_BARS:
- mGlCanvas.drawRects(mProfileShapes[i], count * 4, mProfilePaint);
- break;
- case GraphDataProvider.GRAPH_TYPE_LINES:
- mGlCanvas.drawLines(mProfileShapes[i], 0, count * 4, mProfilePaint);
- break;
- }
- }
- }
-
- private void drawCurrentFrame(int graphType, int index) {
- if (index >= 0) {
- mDebugDataProvider.setupCurrentFramePaint(mProfilePaint);
- switch (graphType) {
- case GraphDataProvider.GRAPH_TYPE_BARS:
- mGlCanvas.drawRect(mProfileShapes[2][index], mProfileShapes[2][index + 1],
- mProfileShapes[2][index + 2], mProfileShapes[0][index + 3],
- mProfilePaint);
- break;
- case GraphDataProvider.GRAPH_TYPE_LINES:
- mGlCanvas.drawLine(mProfileShapes[2][index], mProfileShapes[2][index + 1],
- mProfileShapes[2][index], mHeight, mProfilePaint);
- break;
- }
- }
- }
-
- private void drawThreshold(int x, int height) {
- float threshold = mDebugDataProvider.getThreshold();
- if (threshold > 0.0f) {
- mDebugDataProvider.setupThresholdPaint(mProfilePaint);
- int y = (int) (mHeight - threshold * height);
- mGlCanvas.drawLine(0.0f, y, x, y, mProfilePaint);
- }
- }
-
- private void initProfileDrawData(View.AttachInfo attachInfo, GraphDataProvider provider) {
- if (mProfileShapes == null) {
- final int elementCount = provider.getElementCount();
- final int frameCount = provider.getFrameCount();
-
- mProfileShapes = new float[elementCount][];
- for (int i = 0; i < elementCount; i++) {
- mProfileShapes[i] = new float[frameCount * 4];
- }
-
- mProfilePaint = new Paint();
- }
-
- mProfilePaint.reset();
- if (provider.getGraphType() == GraphDataProvider.GRAPH_TYPE_LINES) {
- mProfilePaint.setAntiAlias(true);
- }
-
- if (mDisplayMetrics == null) {
- mDisplayMetrics = new DisplayMetrics();
- }
-
- attachInfo.mDisplay.getMetrics(mDisplayMetrics);
- provider.prepare(mDisplayMetrics);
- }
-
- @Override
- void destroy(boolean full) {
- try {
- if (full && mCanvas != null) {
- mCanvas = null;
- }
-
- if (!isEnabled() || mDestroyed) {
- setEnabled(false);
- return;
- }
-
- destroySurface();
- setEnabled(false);
-
- mDestroyed = true;
- mGl = null;
- } finally {
- if (full && mGlCanvas != null) {
- mGlCanvas = null;
- }
- }
- }
-
- @Override
- void pushLayerUpdate(HardwareLayer layer) {
- mLayerUpdates.add(layer);
- }
-
- @Override
- void flushLayerUpdates() {
- if (validate()) {
- flushLayerChanges();
- mGlCanvas.flushLayerUpdates();
- }
- }
-
- @Override
- HardwareLayer createTextureLayer() {
- validate();
- return HardwareLayer.createTextureLayer(this);
- }
-
- @Override
- public HardwareLayer createDisplayListLayer(int width, int height) {
- validate();
- return HardwareLayer.createDisplayListLayer(this, width, height);
- }
-
- boolean hasContext() {
- return sEgl != null && mEglContext != null
- && mEglContext.equals(sEgl.eglGetCurrentContext());
- }
-
- @Override
- void onLayerDestroyed(HardwareLayer layer) {
- if (mGlCanvas != null) {
- mGlCanvas.cancelLayerUpdate(layer);
- }
- mLayerUpdates.remove(layer);
- }
-
- @Override
- public SurfaceTexture createSurfaceTexture(HardwareLayer layer) {
- return layer.createSurfaceTexture();
- }
-
- @Override
- boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) {
- if (!validate()) {
- throw new IllegalStateException("Could not acquire hardware rendering context");
- }
- layer.flushChanges();
- return GLES20Canvas.nCopyLayer(layer.getLayer(), bitmap.mNativeBitmap);
- }
-
- @Override
- boolean safelyRun(Runnable action) {
- boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
-
- if (needsContext) {
- GLRendererEglContext managedContext =
- (GLRendererEglContext) sEglContextStorage.get();
- if (managedContext == null) return false;
- usePbufferSurface(managedContext.getContext());
- }
-
- try {
- action.run();
- } finally {
- if (needsContext) {
- sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
- EGL_NO_SURFACE, EGL_NO_CONTEXT);
- }
- }
-
- return true;
- }
-
- @Override
- void invokeFunctor(long functor, boolean waitForCompletion) {
- boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
- boolean hasContext = !needsContext;
-
- if (needsContext) {
- GLRendererEglContext managedContext =
- (GLRendererEglContext) sEglContextStorage.get();
- if (managedContext != null) {
- usePbufferSurface(managedContext.getContext());
- hasContext = true;
- }
- }
-
- try {
- nInvokeFunctor(functor, hasContext);
- } finally {
- if (needsContext) {
- sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE,
- EGL_NO_SURFACE, EGL_NO_CONTEXT);
- }
- }
- }
-
- private static native void nInvokeFunctor(long functor, boolean hasContext);
-
- @Override
- void destroyHardwareResources(final View view) {
- if (view != null) {
- safelyRun(new Runnable() {
- @Override
- public void run() {
- if (mCanvas != null) {
- mCanvas.clearLayerUpdates();
- }
- destroyResources(view);
- GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS);
- }
- });
- }
- }
-
- private static void destroyResources(View view) {
- view.destroyHardwareResources();
-
- if (view instanceof ViewGroup) {
- ViewGroup group = (ViewGroup) view;
-
- int count = group.getChildCount();
- for (int i = 0; i < count; i++) {
- destroyResources(group.getChildAt(i));
- }
- }
- }
-
- static void startTrimMemory(int level) {
- if (sEgl == null || sEglConfig == null) return;
-
- GLRendererEglContext managedContext =
- (GLRendererEglContext) sEglContextStorage.get();
- // We do not have OpenGL objects
- if (managedContext == null) {
- return;
- } else {
- usePbufferSurface(managedContext.getContext());
- }
-
- if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
- GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_FULL);
- } else if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
- GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_MODERATE);
- }
- }
-
- static void endTrimMemory() {
- if (sEgl != null && sEglDisplay != null) {
- sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- }
- }
-
- private static void usePbufferSurface(EGLContext eglContext) {
- synchronized (sPbufferLock) {
- // Create a temporary 1x1 pbuffer so we have a context
- // to clear our OpenGL objects
- if (sPbuffer == null) {
- sPbuffer = sEgl.eglCreatePbufferSurface(sEglDisplay, sEglConfig, new int[] {
- EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE
- });
- }
- }
- sEgl.eglMakeCurrent(sEglDisplay, sPbuffer, sPbuffer, eglContext);
- }
-
- GLRenderer(boolean translucent) {
- mTranslucent = translucent;
-
- loadSystemProperties();
- }
-
- @Override
- void setOpaque(boolean opaque) {
- // Not supported
- }
-
- @Override
- boolean loadSystemProperties() {
- boolean value;
- boolean changed = false;
-
- String profiling = SystemProperties.get(PROFILE_PROPERTY);
- int graphType = search(VISUALIZERS, profiling);
- value = graphType >= 0;
-
- if (graphType != mProfileVisualizerType) {
- changed = true;
- mProfileVisualizerType = graphType;
-
- mProfileShapes = null;
- mProfilePaint = null;
-
- if (value) {
- mDebugDataProvider = new GraphDataProvider(graphType);
- } else {
- mDebugDataProvider = null;
- }
- }
-
- // If on-screen profiling is not enabled, we need to check whether
- // console profiling only is enabled
- if (!value) {
- value = Boolean.parseBoolean(profiling);
- }
-
- if (value != mProfileEnabled) {
- changed = true;
- mProfileEnabled = value;
-
- if (mProfileEnabled) {
- Log.d(LOG_TAG, "Profiling hardware renderer");
-
- int maxProfileFrames = SystemProperties.getInt(PROFILE_MAXFRAMES_PROPERTY,
- PROFILE_MAX_FRAMES);
- mProfileData = new float[maxProfileFrames * PROFILE_FRAME_DATA_COUNT];
- for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
- mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
- }
-
- mProfileLock = new ReentrantLock();
- } else {
- mProfileData = null;
- mProfileLock = null;
- mProfileVisualizerType = -1;
- }
-
- mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT;
- }
-
- value = SystemProperties.getBoolean(DEBUG_DIRTY_REGIONS_PROPERTY, false);
- if (value != mDebugDirtyRegions) {
- changed = true;
- mDebugDirtyRegions = value;
-
- if (mDebugDirtyRegions) {
- Log.d(LOG_TAG, "Debugging dirty regions");
- }
- }
-
- String overdraw = SystemProperties.get(HardwareRenderer.DEBUG_OVERDRAW_PROPERTY);
- int debugOverdraw = search(OVERDRAW, overdraw);
- if (debugOverdraw != mDebugOverdraw) {
- changed = true;
- mDebugOverdraw = debugOverdraw;
- }
-
- if (loadProperties()) {
- changed = true;
- }
-
- return changed;
- }
-
- private static int search(String[] values, String value) {
- for (int i = 0; i < values.length; i++) {
- if (values[i].equals(value)) return i;
- }
- return -1;
- }
-
- @Override
- void dumpGfxInfo(PrintWriter pw, FileDescriptor fd) {
- if (mProfileEnabled) {
- pw.printf("\n\tDraw\tProcess\tExecute\n");
-
- mProfileLock.lock();
- try {
- for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) {
- if (mProfileData[i] < 0) {
- break;
- }
- pw.printf("\t%3.2f\t%3.2f\t%3.2f\n", mProfileData[i], mProfileData[i + 1],
- mProfileData[i + 2]);
- mProfileData[i] = mProfileData[i + 1] = mProfileData[i + 2] = -1;
- }
- mProfileCurrentFrame = mProfileData.length;
- } finally {
- mProfileLock.unlock();
- }
- }
- }
-
- /**
- * Indicates whether this renderer instance can track and update dirty regions.
- */
- boolean hasDirtyRegions() {
- return mDirtyRegionsEnabled;
- }
-
- /**
- * Checks for OpenGL errors. If an error has occured, {@link #destroy(boolean)}
- * is invoked and the requested flag is turned off. The error code is
- * also logged as a warning.
- */
- void checkEglErrors() {
- if (isEnabled()) {
- checkEglErrorsForced();
- }
- }
-
- private void checkEglErrorsForced() {
- int error = sEgl.eglGetError();
- if (error != EGL_SUCCESS) {
- // something bad has happened revert to
- // normal rendering.
- Log.w(LOG_TAG, "EGL error: " + GLUtils.getEGLErrorString(error));
- fallback(error != EGL11.EGL_CONTEXT_LOST);
- }
- }
-
- private void fallback(boolean fallback) {
- destroy(true);
- if (fallback) {
- // we'll try again if it was context lost
- setRequested(false);
- Log.w(LOG_TAG, "Mountain View, we've had a problem here. "
- + "Switching back to software rendering.");
- }
- }
-
- @Override
- boolean initialize(Surface surface) throws OutOfResourcesException {
- if (isRequested() && !isEnabled()) {
- boolean contextCreated = initializeEgl();
- mGl = createEglSurface(surface);
- mDestroyed = false;
-
- if (mGl != null) {
- int err = sEgl.eglGetError();
- if (err != EGL_SUCCESS) {
- destroy(true);
- setRequested(false);
- } else {
- if (mCanvas == null) {
- mCanvas = createCanvas();
- }
- setEnabled(true);
-
- if (contextCreated) {
- initAtlas();
- }
- }
-
- return mCanvas != null;
- }
- }
- return false;
- }
-
- @Override
- void updateSurface(Surface surface) throws OutOfResourcesException {
- if (isRequested() && isEnabled()) {
- createEglSurface(surface);
- }
- }
-
- @Override
- void pauseSurface(Surface surface) {
- // No-op
- }
-
- boolean initializeEgl() {
- 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)) {
- throw new RuntimeException("eglInitialize failed " +
- GLUtils.getEGLErrorString(sEgl.eglGetError()));
- }
-
- checkEglErrorsForced();
-
- sEglConfig = loadEglConfig();
- }
- }
-
- ManagedEGLContext managedContext = sEglContextStorage.get();
- mEglContext = managedContext != null ? managedContext.getContext() : null;
- mEglThread = Thread.currentThread();
-
- if (mEglContext == null) {
- mEglContext = createContext(sEgl, sEglDisplay, sEglConfig);
- sEglContextStorage.set(createManagedContext(mEglContext));
- return true;
- }
-
- return false;
- }
-
- private EGLConfig loadEglConfig() {
- EGLConfig eglConfig = chooseEglConfig();
- if (eglConfig == null) {
- // We tried to use EGL_SWAP_BEHAVIOR_PRESERVED_BIT, try again without
- if (sDirtyRegions) {
- sDirtyRegions = false;
- eglConfig = chooseEglConfig();
- if (eglConfig == null) {
- throw new RuntimeException("eglConfig not initialized");
- }
- } else {
- throw new RuntimeException("eglConfig not initialized");
- }
- }
- return eglConfig;
- }
-
- private EGLConfig chooseEglConfig() {
- EGLConfig[] configs = new EGLConfig[1];
- int[] configsCount = new int[1];
- int[] configSpec = getConfig(sDirtyRegions);
-
- // Debug
- final String debug = SystemProperties.get(PRINT_CONFIG_PROPERTY, "");
- if ("all".equalsIgnoreCase(debug)) {
- sEgl.eglChooseConfig(sEglDisplay, configSpec, null, 0, configsCount);
-
- EGLConfig[] debugConfigs = new EGLConfig[configsCount[0]];
- sEgl.eglChooseConfig(sEglDisplay, configSpec, debugConfigs,
- configsCount[0], configsCount);
-
- for (EGLConfig config : debugConfigs) {
- printConfig(config);
- }
- }
-
- if (!sEgl.eglChooseConfig(sEglDisplay, configSpec, configs, 1, configsCount)) {
- throw new IllegalArgumentException("eglChooseConfig failed " +
- GLUtils.getEGLErrorString(sEgl.eglGetError()));
- } else if (configsCount[0] > 0) {
- if ("choice".equalsIgnoreCase(debug)) {
- printConfig(configs[0]);
- }
- return configs[0];
- }
-
- return null;
- }
-
- private static void printConfig(EGLConfig config) {
- int[] value = new int[1];
-
- Log.d(LOG_TAG, "EGL configuration " + config + ":");
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_RED_SIZE, value);
- Log.d(LOG_TAG, " RED_SIZE = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_GREEN_SIZE, value);
- Log.d(LOG_TAG, " GREEN_SIZE = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_BLUE_SIZE, value);
- Log.d(LOG_TAG, " BLUE_SIZE = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_ALPHA_SIZE, value);
- Log.d(LOG_TAG, " ALPHA_SIZE = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_DEPTH_SIZE, value);
- Log.d(LOG_TAG, " DEPTH_SIZE = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_STENCIL_SIZE, value);
- Log.d(LOG_TAG, " STENCIL_SIZE = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLE_BUFFERS, value);
- Log.d(LOG_TAG, " SAMPLE_BUFFERS = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SAMPLES, value);
- Log.d(LOG_TAG, " SAMPLES = " + value[0]);
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_SURFACE_TYPE, value);
- Log.d(LOG_TAG, " SURFACE_TYPE = 0x" + Integer.toHexString(value[0]));
-
- sEgl.eglGetConfigAttrib(sEglDisplay, config, EGL_CONFIG_CAVEAT, value);
- Log.d(LOG_TAG, " CONFIG_CAVEAT = 0x" + Integer.toHexString(value[0]));
- }
-
- GL createEglSurface(Surface surface) throws OutOfResourcesException {
- // Check preconditions.
- if (sEgl == null) {
- throw new RuntimeException("egl not initialized");
- }
- if (sEglDisplay == null) {
- throw new RuntimeException("eglDisplay not initialized");
- }
- if (sEglConfig == null) {
- throw new RuntimeException("eglConfig not initialized");
- }
- if (Thread.currentThread() != mEglThread) {
- throw new IllegalStateException("HardwareRenderer cannot be used "
- + "from multiple threads");
- }
-
- // In case we need to destroy an existing surface
- destroySurface();
-
- // Create an EGL surface we can render into.
- if (!createSurface(surface)) {
- return null;
- }
-
- initCaches();
-
- return mEglContext.getGL();
- }
-
- private void enableDirtyRegions() {
- // If mDirtyRegions is set, this means we have an EGL configuration
- // with EGL_SWAP_BEHAVIOR_PRESERVED_BIT set
- if (sDirtyRegions) {
- if (!(mDirtyRegionsEnabled = preserveBackBuffer())) {
- Log.w(LOG_TAG, "Backbuffer cannot be preserved");
- }
- } else if (sDirtyRegionsRequested) {
- // If mDirtyRegions is not set, our EGL configuration does not
- // have EGL_SWAP_BEHAVIOR_PRESERVED_BIT; however, the default
- // swap behavior might be EGL_BUFFER_PRESERVED, which means we
- // want to set mDirtyRegions. We try to do this only if dirty
- // regions were initially requested as part of the device
- // configuration (see RENDER_DIRTY_REGIONS)
- mDirtyRegionsEnabled = isBackBufferPreserved();
- }
- }
-
- EGLContext createContext(EGL10 egl, EGLDisplay eglDisplay, EGLConfig eglConfig) {
- final int[] attribs = { EGL14.EGL_CONTEXT_CLIENT_VERSION, GL_VERSION, EGL_NONE };
-
- EGLContext context = egl.eglCreateContext(eglDisplay, eglConfig, EGL_NO_CONTEXT,
- attribs);
- if (context == null || context == EGL_NO_CONTEXT) {
- //noinspection ConstantConditions
- throw new IllegalStateException(
- "Could not create an EGL context. eglCreateContext failed with error: " +
- GLUtils.getEGLErrorString(sEgl.eglGetError()));
- }
-
- return context;
- }
-
- void destroySurface() {
- if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
- if (mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW))) {
- sEgl.eglMakeCurrent(sEglDisplay,
- EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- }
- sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
- mEglSurface = null;
- }
- }
-
- @Override
- void invalidate(Surface surface) {
- // Cancels any existing buffer to ensure we'll get a buffer
- // of the right size before we call eglSwapBuffers
- sEgl.eglMakeCurrent(sEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
- if (mEglSurface != null && mEglSurface != EGL_NO_SURFACE) {
- sEgl.eglDestroySurface(sEglDisplay, mEglSurface);
- mEglSurface = null;
- setEnabled(false);
- }
-
- if (surface.isValid()) {
- if (!createSurface(surface)) {
- return;
- }
-
- mUpdateDirtyRegions = true;
-
- if (mCanvas != null) {
- setEnabled(true);
- }
- }
- }
-
- private boolean createSurface(Surface surface) {
- mEglSurface = sEgl.eglCreateWindowSurface(sEglDisplay, sEglConfig, surface, null);
-
- if (mEglSurface == null || mEglSurface == EGL_NO_SURFACE) {
- int error = sEgl.eglGetError();
- if (error == EGL_BAD_NATIVE_WINDOW) {
- Log.e(LOG_TAG, "createWindowSurface returned EGL_BAD_NATIVE_WINDOW.");
- return false;
- }
- throw new RuntimeException("createWindowSurface failed "
- + GLUtils.getEGLErrorString(error));
- }
-
- if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- throw new IllegalStateException("eglMakeCurrent failed " +
- GLUtils.getEGLErrorString(sEgl.eglGetError()));
- }
-
- enableDirtyRegions();
-
- return true;
- }
-
- boolean validate() {
- return checkRenderContext() != SURFACE_STATE_ERROR;
- }
-
- @Override
- void setup(int width, int height, float lightX, float lightY, float lightZ, float lightRadius) {
- if (validate()) {
- mCanvas.setViewport(width, height);
- mCanvas.initializeLight(lightX, lightY, lightZ, lightRadius);
- mWidth = width;
- mHeight = height;
- }
- }
-
- @Override
- int getWidth() {
- return mWidth;
- }
-
- @Override
- int getHeight() {
- return mHeight;
- }
-
- @Override
- void setName(String name) {
- mName = name;
- }
-
- @Override
- void draw(View view, View.AttachInfo attachInfo, HardwareDrawCallbacks callbacks,
- Rect dirty) {
- if (canDraw()) {
- if (!hasDirtyRegions()) {
- dirty = null;
- }
- attachInfo.mIgnoreDirtyState = true;
- attachInfo.mDrawingTime = SystemClock.uptimeMillis();
-
- view.mPrivateFlags |= View.PFLAG_DRAWN;
-
- // We are already on the correct thread
- final int surfaceState = checkRenderContextUnsafe();
- if (surfaceState != SURFACE_STATE_ERROR) {
- HardwareCanvas canvas = mCanvas;
-
- if (mProfileEnabled) {
- mProfileLock.lock();
- }
-
- dirty = beginFrame(canvas, dirty, surfaceState);
-
- RenderNode displayList = buildDisplayList(view, canvas);
-
- flushLayerChanges();
-
- // buildDisplayList() calls into user code which can cause
- // an eglMakeCurrent to happen with a different surface/context.
- // We must therefore check again here.
- if (checkRenderContextUnsafe() == SURFACE_STATE_ERROR) {
- return;
- }
-
- int saveCount = 0;
- int status = RenderNode.STATUS_DONE;
-
- long start = getSystemTime();
- try {
- status = prepareFrame(dirty);
-
- saveCount = canvas.save();
- callbacks.onHardwarePreDraw(canvas);
-
- if (displayList != null) {
- status |= drawDisplayList(canvas, displayList, status);
- } else {
- // Shouldn't reach here
- view.draw(canvas);
- }
- } catch (Exception e) {
- Log.e(LOG_TAG, "An error has occurred while drawing:", e);
- } finally {
- callbacks.onHardwarePostDraw(canvas);
- canvas.restoreToCount(saveCount);
- view.mRecreateDisplayList = false;
-
- mDrawDelta = getSystemTime() - start;
-
- if (mDrawDelta > 0) {
- mFrameCount++;
-
- debugDirtyRegions(dirty, canvas);
- drawProfileData(attachInfo);
- }
- }
-
- onPostDraw();
-
- swapBuffers(status);
-
- if (mProfileEnabled) {
- mProfileLock.unlock();
- }
-
- attachInfo.mIgnoreDirtyState = false;
- }
- }
- }
-
- private void flushLayerChanges() {
- // Loop through and apply any pending layer changes
- for (int i = 0; i < mLayerUpdates.size(); i++) {
- HardwareLayer layer = mLayerUpdates.get(i);
- layer.flushChanges();
- if (!layer.isValid()) {
- // The layer was removed from mAttachedLayers, rewind i by 1
- // Note that this shouldn't actually happen as View.getHardwareLayer()
- // is already flushing for error checking reasons
- i--;
- } else if (layer.hasDisplayList()) {
- mCanvas.pushLayerUpdate(layer);
- }
- }
- mLayerUpdates.clear();
- }
-
- @Override
- void fence() {
- // Everything is immediate, so this is a no-op
- }
-
- private RenderNode buildDisplayList(View view, HardwareCanvas canvas) {
- view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
- == View.PFLAG_INVALIDATED;
- view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
-
- long buildDisplayListStartTime = startBuildDisplayListProfiling();
- canvas.clearLayerUpdates();
-
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
- RenderNode renderNode = view.getDisplayList();
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
-
- endBuildDisplayListProfiling(buildDisplayListStartTime);
-
- return renderNode;
- }
-
- private Rect beginFrame(HardwareCanvas canvas, Rect dirty, int surfaceState) {
- // We had to change the current surface and/or context, redraw everything
- if (surfaceState == SURFACE_STATE_UPDATED) {
- dirty = null;
- beginFrame(null);
- } else {
- int[] size = mSurfaceSize;
- beginFrame(size);
-
- if (size[1] != mHeight || size[0] != mWidth) {
- mWidth = size[0];
- mHeight = size[1];
-
- canvas.setViewport(mWidth, mHeight);
-
- dirty = null;
- }
- }
-
- if (mDebugDataProvider != null) dirty = null;
-
- return dirty;
- }
-
- private long startBuildDisplayListProfiling() {
- if (mProfileEnabled) {
- mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT;
- if (mProfileCurrentFrame >= mProfileData.length) {
- mProfileCurrentFrame = 0;
- }
-
- return System.nanoTime();
- }
- return 0;
- }
-
- private void endBuildDisplayListProfiling(long getDisplayListStartTime) {
- if (mProfileEnabled) {
- long now = System.nanoTime();
- float total = (now - getDisplayListStartTime) * 0.000001f;
- //noinspection PointlessArithmeticExpression
- mProfileData[mProfileCurrentFrame] = total;
- }
- }
-
- private int prepareFrame(Rect dirty) {
- int status;
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
- try {
- status = onPreDraw(dirty);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
- return status;
- }
-
- private int drawDisplayList(HardwareCanvas canvas, RenderNode displayList,
- int status) {
-
- long drawDisplayListStartTime = 0;
- if (mProfileEnabled) {
- drawDisplayListStartTime = System.nanoTime();
- }
-
- Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList");
- nPrepareTree(displayList.getNativeDisplayList());
- try {
- status |= canvas.drawDisplayList(displayList, mRedrawClip,
- RenderNode.FLAG_CLIP_CHILDREN);
- } finally {
- Trace.traceEnd(Trace.TRACE_TAG_VIEW);
- }
-
- if (mProfileEnabled) {
- long now = System.nanoTime();
- float total = (now - drawDisplayListStartTime) * 0.000001f;
- mProfileData[mProfileCurrentFrame + 1] = total;
- }
-
- return status;
- }
-
- private void swapBuffers(int status) {
- if ((status & RenderNode.STATUS_DREW) == RenderNode.STATUS_DREW) {
- long eglSwapBuffersStartTime = 0;
- if (mProfileEnabled) {
- eglSwapBuffersStartTime = System.nanoTime();
- }
-
- sEgl.eglSwapBuffers(sEglDisplay, mEglSurface);
-
- if (mProfileEnabled) {
- long now = System.nanoTime();
- float total = (now - eglSwapBuffersStartTime) * 0.000001f;
- mProfileData[mProfileCurrentFrame + 2] = total;
- }
-
- checkEglErrors();
- }
- }
-
- private void debugDirtyRegions(Rect dirty, HardwareCanvas canvas) {
- if (mDebugDirtyRegions) {
- if (mDebugPaint == null) {
- mDebugPaint = new Paint();
- mDebugPaint.setColor(0x7fff0000);
- }
-
- if (dirty != null && (mFrameCount & 1) == 0) {
- canvas.drawRect(dirty, mDebugPaint);
- }
- }
- }
-
- /**
- * 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
- *
- * @see #checkRenderContextUnsafe()
- */
- int checkRenderContext() {
- if (mEglThread != Thread.currentThread()) {
- throw new IllegalStateException("Hardware acceleration can only be used with a " +
- "single UI thread.\nOriginal thread: " + mEglThread + "\n" +
- "Current thread: " + Thread.currentThread());
- }
-
- return checkRenderContextUnsafe();
- }
-
- /**
- * Ensures the current EGL context and surface are the ones we expect.
- * This method does not check the current thread.
- *
- * @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
- *
- * @see #checkRenderContext()
- */
- private int checkRenderContextUnsafe() {
- if (!mEglSurface.equals(sEgl.eglGetCurrentSurface(EGL_DRAW)) ||
- !mEglContext.equals(sEgl.eglGetCurrentContext())) {
- if (!sEgl.eglMakeCurrent(sEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- Log.e(LOG_TAG, "eglMakeCurrent failed " +
- GLUtils.getEGLErrorString(sEgl.eglGetError()));
- fallback(true);
- return SURFACE_STATE_ERROR;
- } else {
- if (mUpdateDirtyRegions) {
- enableDirtyRegions();
- mUpdateDirtyRegions = false;
- }
- return SURFACE_STATE_UPDATED;
- }
- }
- return SURFACE_STATE_SUCCESS;
- }
-
- private static int dpToPx(int dp, float density) {
- return (int) (dp * density + 0.5f);
- }
-
- static native boolean loadProperties();
-
- static native void setupShadersDiskCache(String cacheFile);
-
- /**
- * Notifies EGL that the frame is about to be rendered.
- * @param size
- */
- static native void beginFrame(int[] size);
-
- /**
- * Returns the current system time according to the renderer.
- * This method is used for debugging only and should not be used
- * as a clock.
- */
- static native long getSystemTime();
-
- /**
- * Preserves the back buffer of the current surface after a buffer swap.
- * Calling this method sets the EGL_SWAP_BEHAVIOR attribute of the current
- * surface to EGL_BUFFER_PRESERVED. Calling this method requires an EGL
- * config that supports EGL_SWAP_BEHAVIOR_PRESERVED_BIT.
- *
- * @return True if the swap behavior was successfully changed,
- * false otherwise.
- */
- static native boolean preserveBackBuffer();
-
- /**
- * Indicates whether the current surface preserves its back buffer
- * after a buffer swap.
- *
- * @return True, if the surface's EGL_SWAP_BEHAVIOR is EGL_BUFFER_PRESERVED,
- * false otherwise
- */
- static native boolean isBackBufferPreserved();
-
- static native void nDestroyLayer(long layerPtr);
-
- private static native void nPrepareTree(long displayListPtr);
-
- class GraphDataProvider {
- /**
- * Draws the graph as bars. Frame elements are stacked on top of
- * each other.
- */
- public static final int GRAPH_TYPE_BARS = 0;
- /**
- * Draws the graph as lines. The number of series drawn corresponds
- * to the number of elements.
- */
- public static final int GRAPH_TYPE_LINES = 1;
-
- private final int mGraphType;
-
- private int mVerticalUnit;
- private int mHorizontalUnit;
- private int mHorizontalMargin;
- private int mThresholdStroke;
-
- public GraphDataProvider(int graphType) {
- mGraphType = graphType;
- }
-
- void prepare(DisplayMetrics metrics) {
- final float density = metrics.density;
-
- mVerticalUnit = dpToPx(PROFILE_DRAW_DP_PER_MS, density);
- mHorizontalUnit = dpToPx(PROFILE_DRAW_WIDTH, density);
- mHorizontalMargin = dpToPx(PROFILE_DRAW_MARGIN, density);
- mThresholdStroke = dpToPx(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH, density);
- }
-
- int getGraphType() {
- return mGraphType;
- }
-
- int getVerticalUnitSize() {
- return mVerticalUnit;
- }
-
- int getHorizontalUnitSize() {
- return mHorizontalUnit;
- }
-
- int getHorizontaUnitMargin() {
- return mHorizontalMargin;
- }
-
- float[] getData() {
- return mProfileData;
- }
-
- float getThreshold() {
- return 16;
- }
-
- int getFrameCount() {
- return mProfileData.length / PROFILE_FRAME_DATA_COUNT;
- }
-
- int getElementCount() {
- return PROFILE_FRAME_DATA_COUNT;
- }
-
- int getCurrentFrame() {
- return mProfileCurrentFrame / PROFILE_FRAME_DATA_COUNT;
- }
-
- void setupGraphPaint(Paint paint, int elementIndex) {
- paint.setColor(PROFILE_DRAW_COLORS[elementIndex]);
- if (mGraphType == GRAPH_TYPE_LINES) paint.setStrokeWidth(mThresholdStroke);
- }
-
- void setupThresholdPaint(Paint paint) {
- paint.setColor(PROFILE_DRAW_THRESHOLD_COLOR);
- paint.setStrokeWidth(mThresholdStroke);
- }
-
- void setupCurrentFramePaint(Paint paint) {
- paint.setColor(PROFILE_DRAW_CURRENT_FRAME_COLOR);
- if (mGraphType == GRAPH_TYPE_LINES) paint.setStrokeWidth(mThresholdStroke);
- }
- }
-}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
index 9568760..b8e7d8c 100644
--- a/core/java/android/view/HardwareCanvas.java
+++ b/core/java/android/view/HardwareCanvas.java
@@ -110,48 +110,6 @@ public abstract class HardwareCanvas extends Canvas {
return RenderNode.STATUS_DONE;
}
- /**
- * Indicates that the specified layer must be updated as soon as possible.
- *
- * @param layer The layer to update
- *
- * @see #clearLayerUpdates()
- *
- * @hide
- */
- abstract void pushLayerUpdate(HardwareLayer layer);
-
- /**
- * Cancels a queued layer update. If the specified layer was not
- * queued for update, this method has no effect.
- *
- * @param layer The layer whose update to cancel
- *
- * @see #pushLayerUpdate(HardwareLayer)
- * @see #clearLayerUpdates()
- *
- * @hide
- */
- abstract void cancelLayerUpdate(HardwareLayer layer);
-
- /**
- * Immediately executes all enqueued layer updates.
- *
- * @see #pushLayerUpdate(HardwareLayer)
- *
- * @hide
- */
- abstract void flushLayerUpdates();
-
- /**
- * Removes all enqueued layer updates.
- *
- * @see #pushLayerUpdate(HardwareLayer)
- *
- * @hide
- */
- abstract void clearLayerUpdates();
-
public abstract void drawCircle(CanvasProperty<Float> cx, CanvasProperty<Float> cy,
CanvasProperty<Float> radius, CanvasProperty<Paint> paint);
}
diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java
index 652bcd2..6acb134 100644
--- a/core/java/android/view/HardwareLayer.java
+++ b/core/java/android/view/HardwareLayer.java
@@ -172,24 +172,6 @@ final class HardwareLayer {
});
}
- /**
- * This exists to minimize impact into the current HardwareLayer paths as
- * some of the specifics of how to handle error cases in the fully
- * deferred model will work
- */
- @Deprecated
- public void flushChanges() {
- if (HardwareRenderer.sUseRenderThread) {
- // Not supported, don't try.
- return;
- }
-
- boolean success = nFlushChanges(mFinalizer.get());
- if (!success) {
- destroy();
- }
- }
-
public long getLayer() {
return nGetLayer(mFinalizer.get());
}
@@ -216,33 +198,14 @@ final class HardwareLayer {
return st;
}
- /**
- * This should only be used by HardwareRenderer! Do not call directly
- */
- static HardwareLayer createTextureLayer(HardwareRenderer renderer) {
- return new HardwareLayer(renderer, nCreateTextureLayer(), LAYER_TYPE_TEXTURE);
- }
-
static HardwareLayer adoptTextureLayer(HardwareRenderer renderer, long layer) {
return new HardwareLayer(renderer, layer, LAYER_TYPE_TEXTURE);
}
- /**
- * This should only be used by HardwareRenderer! Do not call directly
- */
- static HardwareLayer createDisplayListLayer(HardwareRenderer renderer,
- int width, int height) {
- return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_DISPLAY_LIST);
- }
-
static HardwareLayer adoptDisplayListLayer(HardwareRenderer renderer, long layer) {
return new HardwareLayer(renderer, layer, LAYER_TYPE_DISPLAY_LIST);
}
- /** This also creates the underlying layer */
- private static native long nCreateTextureLayer();
- private static native long nCreateRenderLayer(int width, int height);
-
private static native void nOnTextureDestroyed(long layerUpdater);
private static native boolean nPrepare(long layerUpdater, int width, int height, boolean isOpaque);
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index d71de9f..d67c974 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -171,9 +171,6 @@ public abstract class HardwareRenderer {
*/
public static boolean sSystemRendererDisabled = false;
- /** @hide */
- public static boolean sUseRenderThread = true;
-
private boolean mEnabled;
private boolean mRequested = true;
@@ -309,7 +306,7 @@ public abstract class HardwareRenderer {
* @hide
*/
public static void setupDiskCache(File cacheDir) {
- GLRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
+ ThreadedRenderer.setupShadersDiskCache(new File(cacheDir, CACHE_PATH_SHADERS).getAbsolutePath());
}
/**
@@ -469,11 +466,7 @@ public abstract class HardwareRenderer {
static HardwareRenderer create(boolean translucent) {
HardwareRenderer renderer = null;
if (GLES20Canvas.isAvailable()) {
- if (sUseRenderThread) {
- renderer = new ThreadedRenderer(translucent);
- } else {
- renderer = new GLRenderer(translucent);
- }
+ renderer = new ThreadedRenderer(translucent);
}
return renderer;
}
@@ -500,7 +493,7 @@ public abstract class HardwareRenderer {
* see {@link android.content.ComponentCallbacks}
*/
static void startTrimMemory(int level) {
- GLRenderer.startTrimMemory(level);
+ ThreadedRenderer.startTrimMemory(level);
}
/**
@@ -508,7 +501,7 @@ public abstract class HardwareRenderer {
* cleanup special resources used by the memory trimming process.
*/
static void endTrimMemory() {
- GLRenderer.endTrimMemory();
+ ThreadedRenderer.endTrimMemory();
}
/**
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index af16185..a52ccdf 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -216,12 +216,6 @@ interface IWindowManager
oneway void statusBarVisibilityChanged(int visibility);
/**
- * Block until the given window has been drawn to the screen.
- * Returns true if really waiting, false if the window does not exist.
- */
- boolean waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
-
- /**
* Device has a software navigation bar (separate from the status bar).
*/
boolean hasNavigationBar();
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 8a996d2..8b2ec7a 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -1716,6 +1716,7 @@ public class KeyEvent extends InputEvent implements Parcelable {
case KeyEvent.KEYCODE_MENU:
case KeyEvent.KEYCODE_SLEEP:
case KeyEvent.KEYCODE_WAKEUP:
+ case KeyEvent.KEYCODE_PAIRING:
return true;
}
return false;
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 11db996..9b3ef7f 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -331,6 +331,14 @@ public class ThreadedRenderer extends HardwareRenderer {
}
}
+ static void startTrimMemory(int level) {
+ // TODO
+ }
+
+ static void endTrimMemory() {
+ // TODO
+ }
+
private static class AtlasInitializer {
static AtlasInitializer sInstance = new AtlasInitializer();
@@ -367,6 +375,8 @@ public class ThreadedRenderer extends HardwareRenderer {
}
}
+ static native void setupShadersDiskCache(String cacheFile);
+
private static native void nSetAtlas(GraphicBuffer buffer, long[] map);
private static native long nCreateRootRenderNode();
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ce266d7..622fa8c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -13593,12 +13593,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
}
- // The layer is not valid if the underlying GPU resources cannot be allocated
- mHardwareLayer.flushChanges();
- if (!mHardwareLayer.isValid()) {
- return null;
- }
-
mHardwareLayer.setLayerPaint(mLayerPaint);
RenderNode displayList = mHardwareLayer.startRecording();
updateDisplayListIfDirty(displayList, true);
@@ -16197,6 +16191,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Set this view's optical insets.
+ *
+ * <p>This method should be treated similarly to setMeasuredDimension and not as a general
+ * property. Views that compute their own optical insets should call it as part of measurement.
+ * This method does not request layout. If you are setting optical insets outside of
+ * measure/layout itself you will want to call requestLayout() yourself.
+ * </p>
+ * @hide
+ */
+ public void setOpticalInsets(Insets insets) {
+ mLayoutInsets = insets;
+ }
+
+ /**
* Changes the selection state of this view. A view can be selected or not.
* Note that selection is not the same as focus. Views are typically
* selected in the context of an AdapterView like ListView or GridView;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index ac25b57..f3d1e3c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -716,17 +716,6 @@ public final class ViewRootImpl implements ViewParent,
if (!HardwareRenderer.sRendererDisabled || (HardwareRenderer.sSystemRendererDisabled
&& forceHwAccelerated)) {
- if (!HardwareRenderer.sUseRenderThread) {
- // TODO: Delete
- // 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 "
- + "acceleration outside of the main thread, aborting");
- return;
- }
- }
-
if (mAttachInfo.mHardwareRenderer != null) {
mAttachInfo.mHardwareRenderer.destroy(true);
}
diff --git a/core/java/android/view/WindowManagerInternal.java b/core/java/android/view/WindowManagerInternal.java
index 14dc356..a92bf59 100644
--- a/core/java/android/view/WindowManagerInternal.java
+++ b/core/java/android/view/WindowManagerInternal.java
@@ -20,6 +20,7 @@ import android.graphics.Rect;
import android.graphics.Region;
import android.hardware.display.DisplayManagerInternal;
import android.os.IBinder;
+import android.os.IRemoteCallback;
import java.util.List;
@@ -105,7 +106,7 @@ public abstract class WindowManagerInternal {
* Set by the accessibility layer to specify the magnification and panning to
* be applied to all windows that should be magnified.
*
- * @param callbacks The callbacks to invoke.
+ * @param spec The MagnficationSpec to set.
*
* @see #setMagnificationCallbacks(MagnificationCallbacks)
*/
@@ -161,4 +162,10 @@ public abstract class WindowManagerInternal {
* @param outBounds The frame to populate.
*/
public abstract void getWindowFrame(IBinder token, Rect outBounds);
+
+ /**
+ * Invalidate all visible windows. Then report back on the callback once all windows have
+ * redrawn.
+ */
+ public abstract void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout);
}
diff --git a/core/java/android/webkit/CookieManager.java b/core/java/android/webkit/CookieManager.java
index 2b75d83..abed082 100644
--- a/core/java/android/webkit/CookieManager.java
+++ b/core/java/android/webkit/CookieManager.java
@@ -70,8 +70,7 @@ public class CookieManager {
/**
* Sets a cookie for the given URL. Any existing cookie with the same host,
* path and name will be replaced with the new cookie. The cookie being set
- * must not have expired and must not be a session cookie, otherwise it
- * will be ignored.
+ * will be ignored if it is expired.
*
* @param url the URL for which the cookie is set
* @param value the cookie as a string, using the format of the 'Set-Cookie'
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 7c32c5b..d14c19b 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -1460,4 +1460,36 @@ public abstract class WebSettings {
* {@link #MIXED_CONTENT_NEVER_ALLOW} or {@link #MIXED_CONTENT_COMPATIBILITY_MODE}.
*/
public abstract int getMixedContentMode();
+
+ /**
+ * Sets whether to use a video overlay for embedded encrypted video.
+ * In API levels prior to {@link android.os.Build.VERSION_CODES#L}, encrypted video can
+ * only be rendered directly on a secure video surface, so it had been a hard problem to play
+ * encrypted video in HTML. When this flag is on, WebView can play encrypted video (MSE/EME)
+ * by using a video overlay (aka hole-punching) for videos embedded using HTML &lt;video&gt;
+ * tag.<br>
+ * Caution: This setting is intended for use only in a narrow set of circumstances and apps
+ * should only enable it if they require playback of encrypted video content. It will impose
+ * the following limitations on the WebView:
+ * <ul>
+ * <li> Only one video overlay can be played at a time.
+ * <li> Changes made to position or dimensions of a video element may be propagated to the
+ * corresponding video overlay with a noticeable delay.
+ * <li> The video overlay is not visible to web APIs and as such may not interact with
+ * script or styling. For example, CSS styles applied to the &lt;video&gt; tag may be ignored.
+ * </ul>
+ * This is not an exhaustive set of constraints and it may vary with new versions of the
+ * WebView.
+ * @hide
+ */
+ public abstract void setVideoOverlayForEmbeddedEncryptedVideoEnabled(boolean flag);
+
+ /**
+ * Gets whether a video overlay will be used for embedded encrypted video.
+ *
+ * @return true if WebView uses a video overlay for embedded encrypted video.
+ * @see #setVideoOverlayForEmbeddedEncryptedVideoEnabled
+ * @hide
+ */
+ public abstract boolean getVideoOverlayForEmbeddedEncryptedVideoEnabled();
}
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 9a46052..372228c 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4028,12 +4028,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
final int scrollY = mScrollY;
if (!mEdgeGlowTop.isFinished()) {
final int restoreCount = canvas.save();
- final int leftPadding = mListPadding.left + mGlowPaddingLeft;
- final int rightPadding = mListPadding.right + mGlowPaddingRight;
- final int width = getWidth() - leftPadding - rightPadding;
+ final int width = getWidth();
int edgeY = Math.min(0, scrollY + mFirstPositionDistanceGuess);
- canvas.translate(leftPadding, edgeY);
+ canvas.translate(0, edgeY);
mEdgeGlowTop.setSize(width, getHeight());
if (mEdgeGlowTop.draw(canvas)) {
invalidate(0, 0, getWidth(),
@@ -4043,12 +4041,10 @@ public abstract class AbsListView extends AdapterView<ListAdapter> implements Te
}
if (!mEdgeGlowBottom.isFinished()) {
final int restoreCount = canvas.save();
- final int leftPadding = mListPadding.left + mGlowPaddingLeft;
- final int rightPadding = mListPadding.right + mGlowPaddingRight;
- final int width = getWidth() - leftPadding - rightPadding;
+ final int width = getWidth();
final int height = getHeight();
- int edgeX = -width + leftPadding;
+ int edgeX = -width;
int edgeY = Math.max(height, scrollY + mLastPositionDistanceGuess);
canvas.translate(edgeX, edgeY);
canvas.rotate(180, width, 0);
diff --git a/core/java/android/widget/EdgeEffect.java b/core/java/android/widget/EdgeEffect.java
index c4a40b4..2502954 100644
--- a/core/java/android/widget/EdgeEffect.java
+++ b/core/java/android/widget/EdgeEffect.java
@@ -122,7 +122,7 @@ public class EdgeEffect {
final TypedArray a = context.obtainStyledAttributes(
com.android.internal.R.styleable.EdgeEffect);
final int themeColor = a.getColor(
- com.android.internal.R.styleable.EdgeEffect_colorPrimaryLight, 0xff666666);
+ com.android.internal.R.styleable.EdgeEffect_colorPrimary, 0xff666666);
a.recycle();
mPaint.setColor((themeColor & 0xffffff) | 0x33000000);
mPaint.setStyle(Paint.Style.FILL);
@@ -312,8 +312,7 @@ public class EdgeEffect {
final float displacement = Math.max(0, Math.min(mDisplacement, 1.f)) - 0.5f;
float translateX = mBounds.width() * displacement / 2;
- canvas.clipRect(Float.MIN_VALUE, mBounds.top,
- Float.MAX_VALUE, Float.MAX_VALUE);
+ canvas.clipRect(mBounds);
canvas.translate(translateX, 0);
canvas.drawArc(mArcRect, 45, 90, true, mPaint);
canvas.restoreToCount(count);
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index eedacb5..572302a 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -664,7 +664,7 @@ public class ImageView extends View {
InputStream stream = null;
try {
stream = mContext.getContentResolver().openInputStream(mUri);
- d = Drawable.createFromStreamThemed(stream, null, mContext.getTheme());
+ d = Drawable.createFromStream(stream, null);
} catch (Exception e) {
Log.w("ImageView", "Unable to open content: " + mUri, e);
} finally {
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 0c3715d..b49938c 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -357,9 +357,8 @@ public class ProgressBar extends View {
Shader.TileMode.REPEAT, Shader.TileMode.CLAMP);
shapeDrawable.getPaint().setShader(bitmapShader);
- // Ensure the color filter and tint are propagated.
- shapeDrawable.setTint(bitmap.getTint());
- shapeDrawable.setTintMode(bitmap.getTintMode());
+ // Ensure the tint and filter are propagated in the correct order.
+ shapeDrawable.setTint(bitmap.getTint(), bitmap.getTintMode());
shapeDrawable.setColorFilter(bitmap.getColorFilter());
return clip ? new ClipDrawable(
diff --git a/core/java/android/widget/RadialTimePickerView.java b/core/java/android/widget/RadialTimePickerView.java
index 1c9ab61..bb74c44 100644
--- a/core/java/android/widget/RadialTimePickerView.java
+++ b/core/java/android/widget/RadialTimePickerView.java
@@ -42,6 +42,7 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
+
import com.android.internal.R;
import java.text.DateFormatSymbols;
@@ -82,13 +83,13 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
private static final int ALPHA_TRANSPARENT = 0;
// Alpha level of color for selector.
- private static final int ALPHA_SELECTOR = 51;
+ private static final int ALPHA_SELECTOR = 255; // was 51
// Alpha level of color for selected circle.
private static final int ALPHA_AMPM_SELECTED = ALPHA_SELECTOR;
// Alpha level of color for pressed circle.
- private static final int ALPHA_AMPM_PRESSED = 175;
+ private static final int ALPHA_AMPM_PRESSED = 255; // was 175
private static final float COSINE_30_DEGREES = ((float) Math.sqrt(3)) * 0.5f;
private static final float SINE_30_DEGREES = 0.5f;
@@ -112,8 +113,15 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
private final String[] mAmPmText = new String[2];
private final Paint[] mPaint = new Paint[2];
+ private final int[] mColor = new int[2];
+ private final IntHolder[] mAlpha = new IntHolder[2];
+
private final Paint mPaintCenter = new Paint();
+
private final Paint[][] mPaintSelector = new Paint[2][3];
+ private final int[][] mColorSelector = new int[2][3];
+ private final IntHolder[][] mAlphaSelector = new IntHolder[2][3];
+
private final Paint mPaintAmPmText = new Paint();
private final Paint[] mPaintAmPmCircle = new Paint[2];
@@ -309,65 +317,80 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
final Resources res = getResources();
mAmPmUnselectedColor = a.getColor(R.styleable.TimePicker_amPmUnselectedBackgroundColor,
- res.getColor(
- R.color.timepicker_default_ampm_unselected_background_color_holo_light));
+ res.getColor(R.color.timepicker_default_ampm_unselected_background_color_quantum));
mAmPmSelectedColor = a.getColor(R.styleable.TimePicker_amPmSelectedBackgroundColor,
- res.getColor(R.color.timepicker_default_ampm_selected_background_color_holo_light));
+ res.getColor(R.color.timepicker_default_ampm_selected_background_color_quantum));
mAmPmTextColor = a.getColor(R.styleable.TimePicker_amPmTextColor,
- res.getColor(R.color.timepicker_default_text_color_holo_light));
-
- final int numbersTextColor = a.getColor(R.styleable.TimePicker_numbersTextColor,
- res.getColor(R.color.timepicker_default_text_color_holo_light));
+ res.getColor(R.color.timepicker_default_text_color_quantum));
mTypeface = Typeface.create("sans-serif", Typeface.NORMAL);
+ // Initialize all alpha values to opaque.
+ for (int i = 0; i < mAlpha.length; i++) {
+ mAlpha[i] = new IntHolder(ALPHA_OPAQUE);
+ }
+ for (int i = 0; i < mAlphaSelector.length; i++) {
+ for (int j = 0; j < mAlphaSelector[i].length; j++) {
+ mAlphaSelector[i][j] = new IntHolder(ALPHA_OPAQUE);
+ }
+ }
+
+ final int numbersTextColor = a.getColor(R.styleable.TimePicker_numbersTextColor,
+ res.getColor(R.color.timepicker_default_text_color_quantum));
+
mPaint[HOURS] = new Paint();
- mPaint[HOURS].setColor(numbersTextColor);
mPaint[HOURS].setAntiAlias(true);
mPaint[HOURS].setTextAlign(Paint.Align.CENTER);
+ mColor[HOURS] = numbersTextColor;
mPaint[MINUTES] = new Paint();
- mPaint[MINUTES].setColor(numbersTextColor);
mPaint[MINUTES].setAntiAlias(true);
mPaint[MINUTES].setTextAlign(Paint.Align.CENTER);
+ mColor[MINUTES] = numbersTextColor;
mPaintCenter.setColor(numbersTextColor);
mPaintCenter.setAntiAlias(true);
mPaintCenter.setTextAlign(Paint.Align.CENTER);
mPaintSelector[HOURS][SELECTOR_CIRCLE] = new Paint();
- mPaintSelector[HOURS][SELECTOR_CIRCLE].setColor(
- a.getColor(R.styleable.TimePicker_numbersSelectorColor, R.color.holo_blue_light));
mPaintSelector[HOURS][SELECTOR_CIRCLE].setAntiAlias(true);
+ mColorSelector[HOURS][SELECTOR_CIRCLE] = a.getColor(
+ R.styleable.TimePicker_numbersSelectorColor,
+ R.color.timepicker_default_selector_color_quantum);
mPaintSelector[HOURS][SELECTOR_DOT] = new Paint();
- mPaintSelector[HOURS][SELECTOR_DOT].setColor(
- a.getColor(R.styleable.TimePicker_numbersSelectorColor, R.color.holo_blue_light));
mPaintSelector[HOURS][SELECTOR_DOT].setAntiAlias(true);
+ mColorSelector[HOURS][SELECTOR_DOT] = a.getColor(
+ R.styleable.TimePicker_numbersSelectorColor,
+ R.color.timepicker_default_selector_color_quantum);
mPaintSelector[HOURS][SELECTOR_LINE] = new Paint();
- mPaintSelector[HOURS][SELECTOR_LINE].setColor(
- a.getColor(R.styleable.TimePicker_numbersSelectorColor, R.color.holo_blue_light));
mPaintSelector[HOURS][SELECTOR_LINE].setAntiAlias(true);
mPaintSelector[HOURS][SELECTOR_LINE].setStrokeWidth(2);
+ mColorSelector[HOURS][SELECTOR_LINE] = a.getColor(
+ R.styleable.TimePicker_numbersSelectorColor,
+ R.color.timepicker_default_selector_color_quantum);
mPaintSelector[MINUTES][SELECTOR_CIRCLE] = new Paint();
- mPaintSelector[MINUTES][SELECTOR_CIRCLE].setColor(
- a.getColor(R.styleable.TimePicker_numbersSelectorColor, R.color.holo_blue_light));
mPaintSelector[MINUTES][SELECTOR_CIRCLE].setAntiAlias(true);
+ mColorSelector[MINUTES][SELECTOR_CIRCLE] = a.getColor(
+ R.styleable.TimePicker_numbersSelectorColor,
+ R.color.timepicker_default_selector_color_quantum);
mPaintSelector[MINUTES][SELECTOR_DOT] = new Paint();
- mPaintSelector[MINUTES][SELECTOR_DOT].setColor(
- a.getColor(R.styleable.TimePicker_numbersSelectorColor, R.color.holo_blue_light));
mPaintSelector[MINUTES][SELECTOR_DOT].setAntiAlias(true);
+ mColorSelector[MINUTES][SELECTOR_DOT] = a.getColor(
+ R.styleable.TimePicker_numbersSelectorColor,
+ R.color.timepicker_default_selector_color_quantum);
mPaintSelector[MINUTES][SELECTOR_LINE] = new Paint();
- mPaintSelector[MINUTES][SELECTOR_LINE].setColor(
- a.getColor(R.styleable.TimePicker_numbersSelectorColor, R.color.holo_blue_light));
mPaintSelector[MINUTES][SELECTOR_LINE].setAntiAlias(true);
mPaintSelector[MINUTES][SELECTOR_LINE].setStrokeWidth(2);
+ mColorSelector[MINUTES][SELECTOR_LINE] = a.getColor(
+ R.styleable.TimePicker_numbersSelectorColor,
+ R.color.timepicker_default_selector_color_quantum);
mPaintAmPmText.setColor(mAmPmTextColor);
mPaintAmPmText.setTypeface(mTypeface);
@@ -379,13 +402,12 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
mPaintAmPmCircle[PM] = new Paint();
mPaintAmPmCircle[PM].setAntiAlias(true);
- mPaintBackground.setColor(
- a.getColor(R.styleable.TimePicker_numbersBackgroundColor, Color.WHITE));
+ mPaintBackground.setColor(a.getColor(R.styleable.TimePicker_numbersBackgroundColor,
+ res.getColor(R.color.timepicker_default_numbers_background_color_quantum)));
mPaintBackground.setAntiAlias(true);
- final int disabledColor = a.getColor(R.styleable.TimePicker_disabledColor,
- res.getColor(R.color.timepicker_default_disabled_color_holo_light));
- mPaintDisabled.setColor(disabledColor);
+ mPaintDisabled.setColor(a.getColor(R.styleable.TimePicker_disabledColor,
+ res.getColor(R.color.timepicker_default_disabled_color_quantum)));
mPaintDisabled.setAntiAlias(true);
if (DEBUG) {
@@ -415,6 +437,8 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
mSelectionRadiusMultiplier = Float.parseFloat(
res.getString(R.string.timepicker_selection_radius_multiplier));
+ a.recycle();
+
setOnTouchListener(this);
// Initial values
@@ -622,21 +646,21 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
mAmPmCircleRadiusMultiplier = Float.parseFloat(
res.getString(R.string.timepicker_ampm_circle_radius_multiplier));
- mPaint[HOURS].setAlpha(mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT);
- mPaint[MINUTES].setAlpha(mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE);
+ mAlpha[HOURS].setValue(mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT);
+ mAlpha[MINUTES].setValue(mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE);
- mPaintSelector[HOURS][SELECTOR_CIRCLE].setAlpha(
- mShowHours ?ALPHA_SELECTOR : ALPHA_TRANSPARENT);
- mPaintSelector[HOURS][SELECTOR_DOT].setAlpha(
+ mAlphaSelector[HOURS][SELECTOR_CIRCLE].setValue(
+ mShowHours ? ALPHA_SELECTOR : ALPHA_TRANSPARENT);
+ mAlphaSelector[HOURS][SELECTOR_DOT].setValue(
mShowHours ? ALPHA_OPAQUE : ALPHA_TRANSPARENT);
- mPaintSelector[HOURS][SELECTOR_LINE].setAlpha(
+ mAlphaSelector[HOURS][SELECTOR_LINE].setValue(
mShowHours ? ALPHA_SELECTOR : ALPHA_TRANSPARENT);
- mPaintSelector[MINUTES][SELECTOR_CIRCLE].setAlpha(
+ mAlphaSelector[MINUTES][SELECTOR_CIRCLE].setValue(
mShowHours ? ALPHA_TRANSPARENT : ALPHA_SELECTOR);
- mPaintSelector[MINUTES][SELECTOR_DOT].setAlpha(
+ mAlphaSelector[MINUTES][SELECTOR_DOT].setValue(
mShowHours ? ALPHA_TRANSPARENT : ALPHA_OPAQUE);
- mPaintSelector[MINUTES][SELECTOR_LINE].setAlpha(
+ mAlphaSelector[MINUTES][SELECTOR_LINE].setValue(
mShowHours ? ALPHA_TRANSPARENT : ALPHA_SELECTOR);
}
@@ -704,20 +728,23 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
calculateGridSizesMinutes();
drawCircleBackground(canvas);
+ drawSelector(canvas);
drawTextElements(canvas, mTextSize[HOURS], mTypeface, mOuterTextHours,
- mTextGridWidths[HOURS], mTextGridHeights[HOURS], mPaint[HOURS]);
+ mTextGridWidths[HOURS], mTextGridHeights[HOURS], mPaint[HOURS],
+ mColor[HOURS], mAlpha[HOURS].getValue());
if (mIs24HourMode && mInnerTextHours != null) {
drawTextElements(canvas, mInnerTextSize, mTypeface, mInnerTextHours,
- mInnerTextGridWidths, mInnerTextGridHeights, mPaint[HOURS]);
+ mInnerTextGridWidths, mInnerTextGridHeights, mPaint[HOURS],
+ mColor[HOURS], mAlpha[HOURS].getValue());
}
drawTextElements(canvas, mTextSize[MINUTES], mTypeface, mOuterTextMinutes,
- mTextGridWidths[MINUTES], mTextGridHeights[MINUTES], mPaint[MINUTES]);
+ mTextGridWidths[MINUTES], mTextGridHeights[MINUTES], mPaint[MINUTES],
+ mColor[MINUTES], mAlpha[MINUTES].getValue());
drawCenter(canvas);
- drawSelector(canvas);
if (!mIs24HourMode) {
drawAmPm(canvas);
}
@@ -772,12 +799,12 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
// Draw the two circles
mPaintAmPmCircle[AM].setColor(amColor);
- mPaintAmPmCircle[AM].setAlpha(amAlpha);
+ mPaintAmPmCircle[AM].setAlpha(getMultipliedAlpha(amColor, amAlpha));
canvas.drawCircle(isLayoutRtl ? mRightIndicatorXCenter : mLeftIndicatorXCenter,
mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[AM]);
mPaintAmPmCircle[PM].setColor(pmColor);
- mPaintAmPmCircle[PM].setAlpha(pmAlpha);
+ mPaintAmPmCircle[PM].setAlpha(getMultipliedAlpha(pmColor, pmAlpha));
canvas.drawCircle(isLayoutRtl ? mLeftIndicatorXCenter : mRightIndicatorXCenter,
mAmPmYCenter, mAmPmCircleRadius, mPaintAmPmCircle[PM]);
@@ -792,6 +819,10 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
textYCenter, mPaintAmPmText);
}
+ private int getMultipliedAlpha(int argb, int alpha) {
+ return (int) (Color.alpha(argb) * (alpha / 255.0) + 0.5);
+ }
+
private void drawSelector(Canvas canvas, int index) {
// Calculate the current radius at which to place the selection circle.
mLineLength[index] = (int) (mCircleRadius[index]
@@ -802,15 +833,27 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
int pointX = mXCenter + (int) (mLineLength[index] * Math.sin(selectionRadians));
int pointY = mYCenter - (int) (mLineLength[index] * Math.cos(selectionRadians));
+ int color;
+ int alpha;
+ Paint paint;
+
// Draw the selection circle
- canvas.drawCircle(pointX, pointY, mSelectionRadius[index],
- mPaintSelector[index % 2][SELECTOR_CIRCLE]);
+ color = mColorSelector[index % 2][SELECTOR_CIRCLE];
+ alpha = mAlphaSelector[index % 2][SELECTOR_CIRCLE].getValue();
+ paint = mPaintSelector[index % 2][SELECTOR_CIRCLE];
+ paint.setColor(color);
+ paint.setAlpha(getMultipliedAlpha(color, alpha));
+ canvas.drawCircle(pointX, pointY, mSelectionRadius[index], paint);
// Draw the dot if needed
if (mSelectionDegrees[index] % 30 != 0) {
// We're not on a direct tick
- canvas.drawCircle(pointX, pointY, (mSelectionRadius[index] * 2 / 7),
- mPaintSelector[index % 2][SELECTOR_DOT]);
+ color = mColorSelector[index % 2][SELECTOR_DOT];
+ alpha = mAlphaSelector[index % 2][SELECTOR_DOT].getValue();
+ paint = mPaintSelector[index % 2][SELECTOR_DOT];
+ paint.setColor(color);
+ paint.setAlpha(getMultipliedAlpha(color, alpha));
+ canvas.drawCircle(pointX, pointY, (mSelectionRadius[index] * 2 / 7), paint);
} else {
// We're not drawing the dot, so shorten the line to only go as far as the edge of the
// selection circle
@@ -820,8 +863,12 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
}
// Draw the line
- canvas.drawLine(mXCenter, mYCenter, pointX, pointY,
- mPaintSelector[index % 2][SELECTOR_LINE]);
+ color = mColorSelector[index % 2][SELECTOR_LINE];
+ alpha = mAlphaSelector[index % 2][SELECTOR_LINE].getValue();
+ paint = mPaintSelector[index % 2][SELECTOR_LINE];
+ paint.setColor(color);
+ paint.setAlpha(getMultipliedAlpha(color, alpha));
+ canvas.drawLine(mXCenter, mYCenter, pointX, pointY, paint);
}
private void drawDebug(Canvas canvas) {
@@ -948,9 +995,11 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
* Draw the 12 text values at the positions specified by the textGrid parameters.
*/
private void drawTextElements(Canvas canvas, float textSize, Typeface typeface, String[] texts,
- float[] textGridWidths, float[] textGridHeights, Paint paint) {
+ float[] textGridWidths, float[] textGridHeights, Paint paint, int color, int alpha) {
paint.setTextSize(textSize);
paint.setTypeface(typeface);
+ paint.setColor(color);
+ paint.setAlpha(getMultipliedAlpha(color, alpha));
canvas.drawText(texts[0], textGridWidths[3], textGridHeights[0], paint);
canvas.drawText(texts[1], textGridWidths[4], textGridHeights[1], paint);
canvas.drawText(texts[2], textGridWidths[5], textGridHeights[2], paint);
@@ -1023,17 +1072,17 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
return animator;
}
- private static ObjectAnimator getFadeOutAnimator(Object target, int startAlpha, int endAlpha,
+ private static ObjectAnimator getFadeOutAnimator(IntHolder target, int startAlpha, int endAlpha,
InvalidateUpdateListener updateListener) {
int duration = 500;
- ObjectAnimator animator = ObjectAnimator.ofInt(target, "alpha", startAlpha, endAlpha);
+ ObjectAnimator animator = ObjectAnimator.ofInt(target, "value", startAlpha, endAlpha);
animator.setDuration(duration);
animator.addUpdateListener(updateListener);
return animator;
}
- private static ObjectAnimator getFadeInAnimator(Object target, int startAlpha, int endAlpha,
+ private static ObjectAnimator getFadeInAnimator(IntHolder target, int startAlpha, int endAlpha,
InvalidateUpdateListener updateListener) {
Keyframe kf0, kf1, kf2;
int duration = 500;
@@ -1048,7 +1097,7 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
kf0 = Keyframe.ofInt(0f, startAlpha);
kf1 = Keyframe.ofInt(delayPoint, startAlpha);
kf2 = Keyframe.ofInt(1f, endAlpha);
- PropertyValuesHolder fadeIn = PropertyValuesHolder.ofKeyframe("alpha", kf0, kf1, kf2);
+ PropertyValuesHolder fadeIn = PropertyValuesHolder.ofKeyframe("value", kf0, kf1, kf2);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(
target, fadeIn).setDuration(totalDuration);
@@ -1068,25 +1117,25 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
mHoursToMinutesAnims.add(getRadiusDisappearAnimator(this,
"animationRadiusMultiplierHours", mInvalidateUpdateListener,
mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier));
- mHoursToMinutesAnims.add(getFadeOutAnimator(mPaint[HOURS],
+ mHoursToMinutesAnims.add(getFadeOutAnimator(mAlpha[HOURS],
ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mHoursToMinutesAnims.add(getFadeOutAnimator(mPaintSelector[HOURS][SELECTOR_CIRCLE],
+ mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_CIRCLE],
ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mHoursToMinutesAnims.add(getFadeOutAnimator(mPaintSelector[HOURS][SELECTOR_DOT],
+ mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_DOT],
ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mHoursToMinutesAnims.add(getFadeOutAnimator(mPaintSelector[HOURS][SELECTOR_LINE],
+ mHoursToMinutesAnims.add(getFadeOutAnimator(mAlphaSelector[HOURS][SELECTOR_LINE],
ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
mHoursToMinutesAnims.add(getRadiusReappearAnimator(this,
"animationRadiusMultiplierMinutes", mInvalidateUpdateListener,
mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier));
- mHoursToMinutesAnims.add(getFadeInAnimator(mPaint[MINUTES],
+ mHoursToMinutesAnims.add(getFadeInAnimator(mAlpha[MINUTES],
ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
- mHoursToMinutesAnims.add(getFadeInAnimator(mPaintSelector[MINUTES][SELECTOR_CIRCLE],
+ mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_CIRCLE],
ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener));
- mHoursToMinutesAnims.add(getFadeInAnimator(mPaintSelector[MINUTES][SELECTOR_DOT],
+ mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_DOT],
ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
- mHoursToMinutesAnims.add(getFadeInAnimator(mPaintSelector[MINUTES][SELECTOR_LINE],
+ mHoursToMinutesAnims.add(getFadeInAnimator(mAlphaSelector[MINUTES][SELECTOR_LINE],
ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener));
}
@@ -1103,25 +1152,25 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
mMinuteToHoursAnims.add(getRadiusDisappearAnimator(this,
"animationRadiusMultiplierMinutes", mInvalidateUpdateListener,
mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier));
- mMinuteToHoursAnims.add(getFadeOutAnimator(mPaint[MINUTES],
+ mMinuteToHoursAnims.add(getFadeOutAnimator(mAlpha[MINUTES],
ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mMinuteToHoursAnims.add(getFadeOutAnimator(mPaintSelector[MINUTES][SELECTOR_CIRCLE],
+ mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_CIRCLE],
ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mMinuteToHoursAnims.add(getFadeOutAnimator(mPaintSelector[MINUTES][SELECTOR_DOT],
+ mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_DOT],
ALPHA_OPAQUE, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
- mMinuteToHoursAnims.add(getFadeOutAnimator(mPaintSelector[MINUTES][SELECTOR_LINE],
+ mMinuteToHoursAnims.add(getFadeOutAnimator(mAlphaSelector[MINUTES][SELECTOR_LINE],
ALPHA_SELECTOR, ALPHA_TRANSPARENT, mInvalidateUpdateListener));
mMinuteToHoursAnims.add(getRadiusReappearAnimator(this,
"animationRadiusMultiplierHours", mInvalidateUpdateListener,
mTransitionMidRadiusMultiplier, mTransitionEndRadiusMultiplier));
- mMinuteToHoursAnims.add(getFadeInAnimator(mPaint[HOURS],
+ mMinuteToHoursAnims.add(getFadeInAnimator(mAlpha[HOURS],
ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
- mMinuteToHoursAnims.add(getFadeInAnimator(mPaintSelector[HOURS][SELECTOR_CIRCLE],
+ mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_CIRCLE],
ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener));
- mMinuteToHoursAnims.add(getFadeInAnimator(mPaintSelector[HOURS][SELECTOR_DOT],
+ mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_DOT],
ALPHA_TRANSPARENT, ALPHA_OPAQUE, mInvalidateUpdateListener));
- mMinuteToHoursAnims.add(getFadeInAnimator(mPaintSelector[HOURS][SELECTOR_LINE],
+ mMinuteToHoursAnims.add(getFadeInAnimator(mAlphaSelector[HOURS][SELECTOR_LINE],
ALPHA_TRANSPARENT, ALPHA_SELECTOR, mInvalidateUpdateListener));
}
@@ -1393,4 +1442,20 @@ public class RadialTimePickerView extends View implements View.OnTouchListener {
mInputEnabled = inputEnabled;
invalidate();
}
+
+ private static class IntHolder {
+ private int mValue;
+
+ public IntHolder(int value) {
+ mValue = value;
+ }
+
+ public void setValue(int value) {
+ mValue = value;
+ }
+
+ public int getValue() {
+ return mValue;
+ }
+ }
}
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 99a7886..ac79d05 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -280,6 +280,7 @@ public class ShareActionProvider extends ActionProvider {
final String action = shareIntent.getAction();
if (Intent.ACTION_SEND.equals(action) || Intent.ACTION_SEND_MULTIPLE.equals(action)) {
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ Intent.FLAG_ACTIVITY_MULTIPLE_TASK |
Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
}
}
@@ -303,6 +304,7 @@ public class ShareActionProvider extends ActionProvider {
if (Intent.ACTION_SEND.equals(action) ||
Intent.ACTION_SEND_MULTIPLE.equals(action)) {
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ Intent.FLAG_ACTIVITY_MULTIPLE_TASK |
Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
}
mContext.startActivity(launchIntent);
diff --git a/core/java/android/widget/SuggestionsAdapter.java b/core/java/android/widget/SuggestionsAdapter.java
index 0203301..c8917e0 100644
--- a/core/java/android/widget/SuggestionsAdapter.java
+++ b/core/java/android/widget/SuggestionsAdapter.java
@@ -574,7 +574,7 @@ class SuggestionsAdapter extends ResourceCursorAdapter implements OnClickListene
throw new FileNotFoundException("Failed to open " + uri);
}
try {
- return Drawable.createFromStreamThemed(stream, null, mContext.getTheme());
+ return Drawable.createFromStream(stream, null);
} finally {
try {
stream.close();
diff --git a/core/java/android/widget/TimePickerDelegate.java b/core/java/android/widget/TimePickerDelegate.java
index 79256e5..ba93ee5 100644
--- a/core/java/android/widget/TimePickerDelegate.java
+++ b/core/java/android/widget/TimePickerDelegate.java
@@ -140,13 +140,12 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement
mSelectMinutes = res.getString(R.string.select_minutes);
mHeaderSelectedColor = a.getColor(R.styleable.TimePicker_headerSelectedTextColor,
- android.R.color.holo_blue_light);
+ R.color.timepicker_default_selector_color_quantum);
- mHeaderUnSelectedColor = getUnselectedColor(
- R.color.timepicker_default_text_color_holo_light);
+ mHeaderUnSelectedColor = getUnselectedColor(R.color.timepicker_default_text_color_quantum);
if (mHeaderUnSelectedColor == -1) {
mHeaderUnSelectedColor = a.getColor(R.styleable.TimePicker_headerUnselectedTextColor,
- R.color.timepicker_default_text_color_holo_light);
+ R.color.timepicker_default_text_color_quantum);
}
final int headerBackgroundColor = a.getColor(
@@ -296,7 +295,7 @@ class TimePickerDelegate extends TimePicker.AbstractTimePickerDelegate implement
TypedArray a = mContext.obtainStyledAttributes(TEXT_APPEARANCE_TIME_LABEL_ATTR);
final int textAppearanceResId = a.getResourceId(0, 0);
tempView.setTextAppearance(mContext, (textAppearanceResId != 0) ?
- textAppearanceResId : R.style.TextAppearance_Holo_TimePicker_TimeLabel);
+ textAppearanceResId : R.style.TextAppearance_Quantum_TimePicker_TimeLabel);
a.recycle();
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
diff --git a/core/java/android/widget/Toolbar.java b/core/java/android/widget/Toolbar.java
index 419c582..cbd9a6a 100644
--- a/core/java/android/widget/Toolbar.java
+++ b/core/java/android/widget/Toolbar.java
@@ -1339,7 +1339,8 @@ public class Toolbar extends ViewGroup {
return getPaddingTop();
case Gravity.BOTTOM:
- return getPaddingBottom() - child.getMeasuredHeight() - lp.bottomMargin;
+ return getHeight() - getPaddingBottom() -
+ child.getMeasuredHeight() - lp.bottomMargin;
default:
case Gravity.CENTER_VERTICAL:
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 106ac0b..877938e 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -38,6 +38,7 @@ public class ChooserActivity extends ResolverActivity {
if (Intent.ACTION_SEND.equals(action) ||
Intent.ACTION_SEND_MULTIPLE.equals(action)) {
target.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ Intent.FLAG_ACTIVITY_MULTIPLE_TASK |
Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
}
}
@@ -61,6 +62,7 @@ public class ChooserActivity extends ResolverActivity {
if (Intent.ACTION_SEND.equals(action) ||
Intent.ACTION_SEND_MULTIPLE.equals(action)) {
in.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT |
+ Intent.FLAG_ACTIVITY_MULTIPLE_TASK |
Intent.FLAG_ACTIVITY_AUTO_REMOVE_FROM_RECENTS);
}
initialIntents[i] = in;
diff --git a/core/java/com/android/internal/app/IMediaContainerService.aidl b/core/java/com/android/internal/app/IMediaContainerService.aidl
index 03d3b22..77f0dec 100644
--- a/core/java/com/android/internal/app/IMediaContainerService.aidl
+++ b/core/java/com/android/internal/app/IMediaContainerService.aidl
@@ -25,16 +25,18 @@ import android.content.res.ObbInfo;
interface IMediaContainerService {
String copyResourceToContainer(in Uri packageURI, String containerId, String key,
String resFileName, String publicResFileName, boolean isExternal,
- boolean isForwardLocked);
+ boolean isForwardLocked, in String abiOverride);
int copyResource(in Uri packageURI, in ContainerEncryptionParams encryptionParams,
in ParcelFileDescriptor outStream);
- PackageInfoLite getMinimalPackageInfo(in String packagePath, in int flags, in long threshold);
+ PackageInfoLite getMinimalPackageInfo(in String packagePath, in int flags, in long threshold,
+ in String abiOverride);
boolean checkInternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in long threshold);
- boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked);
+ boolean checkExternalFreeStorage(in Uri fileUri, boolean isForwardLocked, in String abiOverride);
ObbInfo getObbInfo(in String filename);
long calculateDirectorySize(in String directory);
/** Return file system stats: [0] is total bytes, [1] is available bytes */
long[] getFileSystemStats(in String path);
void clearDirectory(in String directory);
- long calculateInstalledSize(in String packagePath, boolean isForwardLocked);
+ long calculateInstalledSize(in String packagePath, boolean isForwardLocked,
+ in String abiOverride);
}
diff --git a/core/java/com/android/internal/app/NavItemSelectedListener.java b/core/java/com/android/internal/app/NavItemSelectedListener.java
new file mode 100644
index 0000000..545f44b
--- /dev/null
+++ b/core/java/com/android/internal/app/NavItemSelectedListener.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.internal.app;
+
+import android.app.ActionBar;
+import android.view.View;
+import android.widget.AdapterView;
+
+/**
+ * Wrapper to adapt the ActionBar.OnNavigationListener in an AdapterView.OnItemSelectedListener
+ * for use in Spinner widgets. Used by action bar implementations.
+ */
+class NavItemSelectedListener implements AdapterView.OnItemSelectedListener {
+ private final ActionBar.OnNavigationListener mListener;
+
+ public NavItemSelectedListener(ActionBar.OnNavigationListener listener) {
+ mListener = listener;
+ }
+
+ @Override
+ public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+ if (mListener != null) {
+ mListener.onNavigationItemSelected(position, id);
+ }
+ }
+
+ @Override
+ public void onNothingSelected(AdapterView<?> parent) {
+ // Do nothing
+ }
+}
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 6056bf2..e8a3f0a 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -173,14 +173,19 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setListNavigationCallbacks(SpinnerAdapter adapter, OnNavigationListener callback) {
- throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ mDecorToolbar.setDropdownParams(adapter, new NavItemSelectedListener(callback));
}
@Override
public void setSelectedNavigationItem(int position) {
- throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ switch (mDecorToolbar.getNavigationMode()) {
+ case NAVIGATION_MODE_LIST:
+ mDecorToolbar.setDropdownSelectedPosition(position);
+ break;
+ default:
+ throw new IllegalStateException(
+ "setSelectedNavigationIndex not valid for current navigation mode");
+ }
}
@Override
@@ -276,8 +281,10 @@ public class ToolbarActionBar extends ActionBar {
@Override
public void setNavigationMode(@NavigationMode int mode) {
- throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ if (mode == ActionBar.NAVIGATION_MODE_TABS) {
+ throw new IllegalArgumentException("Tabs not supported in this configuration");
+ }
+ mDecorToolbar.setNavigationMode(mode);
}
@Override
@@ -288,67 +295,67 @@ public class ToolbarActionBar extends ActionBar {
@Override
public Tab newTab() {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void addTab(Tab tab) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void addTab(Tab tab, boolean setSelected) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void addTab(Tab tab, int position) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void addTab(Tab tab, int position, boolean setSelected) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void removeTab(Tab tab) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void removeTabAt(int position) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void removeAllTabs() {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public void selectTab(Tab tab) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public Tab getSelectedTab() {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
public Tab getTabAt(int index) {
throw new UnsupportedOperationException(
- "Navigation modes are not supported in toolbar action bars");
+ "Tabs are not supported in toolbar action bars");
}
@Override
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index c0b5b97..87a80ac 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -18,9 +18,7 @@ package com.android.internal.app;
import android.animation.ValueAnimator;
import android.content.res.TypedArray;
-import android.view.ViewGroup;
import android.view.ViewParent;
-import android.widget.AdapterView;
import android.widget.Toolbar;
import com.android.internal.R;
import com.android.internal.view.ActionBarPolicy;
@@ -30,7 +28,6 @@ import com.android.internal.view.menu.SubMenuBuilder;
import com.android.internal.widget.ActionBarContainer;
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.ActionBarOverlayLayout;
-import com.android.internal.widget.ActionBarView;
import com.android.internal.widget.DecorToolbar;
import com.android.internal.widget.ScrollingTabContainerView;
@@ -59,7 +56,6 @@ import android.view.Window;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.widget.SpinnerAdapter;
-import com.android.internal.widget.ToolbarWidgetWrapper;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -1313,23 +1309,4 @@ public class WindowDecorActionBar extends ActionBar implements
}
}
- static class NavItemSelectedListener implements AdapterView.OnItemSelectedListener {
- private final OnNavigationListener mListener;
-
- public NavItemSelectedListener(OnNavigationListener listener) {
- mListener = listener;
- }
-
- @Override
- public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
- if (mListener != null) {
- mListener.onNavigationItemSelected(position, id);
- }
- }
-
- @Override
- public void onNothingSelected(AdapterView<?> parent) {
- // Do nothing
- }
- }
}
diff --git a/core/java/com/android/internal/backup/BackupConstants.java b/core/java/com/android/internal/backup/BackupConstants.java
deleted file mode 100644
index 4c276b7..0000000
--- a/core/java/com/android/internal/backup/BackupConstants.java
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2009 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.backup;
-
-/**
- * Constants used internally between the backup manager and its transports
- */
-public class BackupConstants {
- public static final int TRANSPORT_OK = 0;
- public static final int TRANSPORT_ERROR = 1;
- public static final int TRANSPORT_NOT_INITIALIZED = 2;
- public static final int AGENT_ERROR = 3;
- public static final int AGENT_UNKNOWN = 4;
-}
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index f2b29ef..7292116 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -104,7 +104,7 @@ public class LocalTransport extends BackupTransport {
public int initializeDevice() {
if (DEBUG) Log.v(TAG, "wiping all data");
deleteContents(mCurrentSetDir);
- return BackupConstants.TRANSPORT_OK;
+ return BackupTransport.TRANSPORT_OK;
}
public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) {
@@ -166,7 +166,7 @@ public class LocalTransport extends BackupTransport {
entity.write(buf, 0, dataSize);
} catch (IOException e) {
Log.e(TAG, "Unable to update key file " + entityFile.getAbsolutePath());
- return BackupConstants.TRANSPORT_ERROR;
+ return BackupTransport.TRANSPORT_ERROR;
} finally {
entity.close();
}
@@ -174,11 +174,11 @@ public class LocalTransport extends BackupTransport {
entityFile.delete();
}
}
- return BackupConstants.TRANSPORT_OK;
+ return BackupTransport.TRANSPORT_OK;
} catch (IOException e) {
// oops, something went wrong. abort the operation and return error.
Log.v(TAG, "Exception reading backup input:", e);
- return BackupConstants.TRANSPORT_ERROR;
+ return BackupTransport.TRANSPORT_ERROR;
}
}
@@ -208,12 +208,12 @@ public class LocalTransport extends BackupTransport {
}
packageDir.delete();
}
- return BackupConstants.TRANSPORT_OK;
+ return BackupTransport.TRANSPORT_OK;
}
public int finishBackup() {
if (DEBUG) Log.v(TAG, "finishBackup()");
- return BackupConstants.TRANSPORT_OK;
+ return BackupTransport.TRANSPORT_OK;
}
// Restore handling
@@ -249,7 +249,7 @@ public class LocalTransport extends BackupTransport {
mRestorePackage = -1;
mRestoreToken = token;
mRestoreDataDir = new File(mDataDir, Long.toString(token));
- return BackupConstants.TRANSPORT_OK;
+ return BackupTransport.TRANSPORT_OK;
}
public String nextRestorePackage() {
@@ -281,7 +281,7 @@ public class LocalTransport extends BackupTransport {
ArrayList<DecodedFilename> blobs = contentsByKey(packageDir);
if (blobs == null) { // nextRestorePackage() ensures the dir exists, so this is an error
Log.e(TAG, "No keys for package: " + packageDir);
- return BackupConstants.TRANSPORT_ERROR;
+ return BackupTransport.TRANSPORT_ERROR;
}
// We expect at least some data if the directory exists in the first place
@@ -302,10 +302,10 @@ public class LocalTransport extends BackupTransport {
in.close();
}
}
- return BackupConstants.TRANSPORT_OK;
+ return BackupTransport.TRANSPORT_OK;
} catch (IOException e) {
Log.e(TAG, "Unable to read backup records", e);
- return BackupConstants.TRANSPORT_ERROR;
+ return BackupTransport.TRANSPORT_ERROR;
}
}
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index ba419f9..dab3aff 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -20,6 +20,7 @@ import android.content.pm.PackageManager;
import android.util.Slog;
import java.io.File;
+import java.io.IOException;
/**
* Native libraries helper.
@@ -141,4 +142,18 @@ public class NativeLibraryHelper {
return deletedFiles;
}
+
+ // We don't care about the other return values for now.
+ private static final int BITCODE_PRESENT = 1;
+
+ public static boolean hasRenderscriptBitcode(ApkHandle handle) throws IOException {
+ final int returnVal = hasRenderscriptBitcode(handle.apkHandle);
+ if (returnVal < 0) {
+ throw new IOException("Error scanning APK, code: " + returnVal);
+ }
+
+ return (returnVal == BITCODE_PRESENT);
+ }
+
+ private static native int hasRenderscriptBitcode(long apkHandle);
}
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index df96488..7dbde69 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -34,6 +34,7 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
+import java.util.Objects;
import java.util.TreeMap;
/**
@@ -117,6 +118,24 @@ public class InputMethodSubtypeSwitchingController {
+ " mIsSystemLanguage=" + mIsSystemLanguage
+ "}";
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (o == this) {
+ return true;
+ }
+ if (o instanceof ImeSubtypeListItem) {
+ final ImeSubtypeListItem that = (ImeSubtypeListItem)o;
+ if (!Objects.equals(this.mImi, that.mImi)) {
+ return false;
+ }
+ if (this.mSubtypeId != that.mSubtypeId) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
}
private static class InputMethodAndSubtypeList {
@@ -276,7 +295,7 @@ public class InputMethodSubtypeSwitchingController {
private final List<ImeSubtypeListItem> mImeSubtypeList;
private final int[] mUsageHistoryOfSubtypeListItemIndex;
- public DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) {
+ private DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) {
mImeSubtypeList = imeSubtypeListItems;
mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()];
final int N = mImeSubtypeList.size();
@@ -347,15 +366,53 @@ public class InputMethodSubtypeSwitchingController {
@VisibleForTesting
public static class ControllerImpl {
- // TODO: Switch to DynamicRotationList for smarter rotation.
- private final StaticRotationList mSwitchingAwareSubtypeList;
- private final StaticRotationList mSwitchingUnawareSubtypeList;
-
- public ControllerImpl(final List<ImeSubtypeListItem> sortedItems) {
- mSwitchingAwareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems,
- true /* supportsSwitchingToNextInputMethod */));
- mSwitchingUnawareSubtypeList = new StaticRotationList(filterImeSubtypeList(sortedItems,
- false /* supportsSwitchingToNextInputMethod */));
+ private final DynamicRotationList mSwitchingAwareRotationList;
+ private final StaticRotationList mSwitchingUnawareRotationList;
+
+ public static ControllerImpl createFrom(final ControllerImpl currentInstance,
+ final List<ImeSubtypeListItem> sortedEnabledItems) {
+ DynamicRotationList switchingAwareRotationList = null;
+ {
+ final List<ImeSubtypeListItem> switchingAwareImeSubtypes =
+ filterImeSubtypeList(sortedEnabledItems,
+ true /* supportsSwitchingToNextInputMethod */);
+ if (currentInstance != null &&
+ currentInstance.mSwitchingAwareRotationList != null &&
+ Objects.equals(currentInstance.mSwitchingAwareRotationList.mImeSubtypeList,
+ switchingAwareImeSubtypes)) {
+ // Can reuse the current instance.
+ switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList;
+ }
+ if (switchingAwareRotationList == null) {
+ switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes);
+ }
+ }
+
+ StaticRotationList switchingUnawareRotationList = null;
+ {
+ final List<ImeSubtypeListItem> switchingUnawareImeSubtypes = filterImeSubtypeList(
+ sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */);
+ if (currentInstance != null &&
+ currentInstance.mSwitchingUnawareRotationList != null &&
+ Objects.equals(
+ currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList,
+ switchingUnawareImeSubtypes)) {
+ // Can reuse the current instance.
+ switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList;
+ }
+ if (switchingUnawareRotationList == null) {
+ switchingUnawareRotationList =
+ new StaticRotationList(switchingUnawareImeSubtypes);
+ }
+ }
+
+ return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList);
+ }
+
+ private ControllerImpl(final DynamicRotationList switchingAwareRotationList,
+ final StaticRotationList switchingUnawareRotationList) {
+ mSwitchingAwareRotationList = switchingAwareRotationList;
+ mSwitchingUnawareRotationList = switchingUnawareRotationList;
}
public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi,
@@ -364,10 +421,10 @@ public class InputMethodSubtypeSwitchingController {
return null;
}
if (imi.supportsSwitchingToNextInputMethod()) {
- return mSwitchingAwareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi,
+ return mSwitchingAwareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi,
subtype);
} else {
- return mSwitchingUnawareSubtypeList.getNextInputMethodLocked(onlyCurrentIme, imi,
+ return mSwitchingUnawareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi,
subtype);
}
}
@@ -376,10 +433,9 @@ public class InputMethodSubtypeSwitchingController {
if (imi == null) {
return;
}
- // TODO: Enable the following code when DynamicRotationList is enabled.
- // if (imi.supportsSwitchingToNextInputMethod()) {
- // mSwitchingAwareSubtypeList.onUserAction(imi, subtype);
- // }
+ if (imi.supportsSwitchingToNextInputMethod()) {
+ mSwitchingAwareRotationList.onUserAction(imi, subtype);
+ }
}
private static List<ImeSubtypeListItem> filterImeSubtypeList(
@@ -424,7 +480,8 @@ public class InputMethodSubtypeSwitchingController {
public void resetCircularListLocked(Context context) {
mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
- mController = new ControllerImpl(mSubtypeList.getSortedInputMethodAndSubtypeList());
+ mController = ControllerImpl.createFrom(mController,
+ mSubtypeList.getSortedInputMethodAndSubtypeList());
}
public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi,
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index ed9f9bc..240d520 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -2006,6 +2006,11 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ @Override
+ public void commitCurrentHistoryBatchLocked() {
+ mHistoryLastWritten.cmd = HistoryItem.CMD_NULL;
+ }
+
void addHistoryBufferLocked(long elapsedRealtimeMs, long uptimeMs, HistoryItem cur) {
if (!mHaveBatteryLevel || !mRecordingHistory) {
return;
@@ -2342,13 +2347,16 @@ public final class BatteryStatsImpl extends BatteryStats {
// Only care about partial wake locks, since full wake locks
// will be canceled when the user puts the screen to sleep.
aggregateLastWakeupUptimeLocked(uptime);
+ if (historyName == null) {
+ historyName = name;
+ }
if (mRecordAllWakeLocks) {
- if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, name, uid, 0)) {
+ if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_START, historyName,
+ uid, 0)) {
addHistoryEventLocked(elapsedRealtime, uptime,
- HistoryItem.EVENT_WAKE_LOCK_START, name, uid);
+ HistoryItem.EVENT_WAKE_LOCK_START, historyName, uid);
}
}
- historyName = historyName == null ? name : historyName;
if (mWakeLockNesting == 0) {
mHistoryCur.states |= HistoryItem.STATE_WAKE_LOCK_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Start wake lock to: "
@@ -2358,7 +2366,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mHistoryCur.wakelockTag.uid = mInitialAcquireWakeUid = uid;
mWakeLockImportant = !unimportantForLogging;
addHistoryRecordLocked(elapsedRealtime, uptime);
- } else if (!mWakeLockImportant && !unimportantForLogging) {
+ } else if (!mWakeLockImportant && !unimportantForLogging
+ && mHistoryLastWritten.cmd == HistoryItem.CMD_UPDATE) {
if (mHistoryLastWritten.wakelockTag != null) {
// We'll try to update the last tag.
mHistoryLastWritten.wakelockTag = null;
@@ -2386,9 +2395,13 @@ public final class BatteryStatsImpl extends BatteryStats {
if (type == WAKE_TYPE_PARTIAL) {
mWakeLockNesting--;
if (mRecordAllWakeLocks) {
- if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, name, uid, 0)) {
+ if (historyName == null) {
+ historyName = name;
+ }
+ if (mActiveEvents.updateState(HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName,
+ uid, 0)) {
addHistoryEventLocked(elapsedRealtime, uptime,
- HistoryItem.EVENT_WAKE_LOCK_FINISH, name, uid);
+ HistoryItem.EVENT_WAKE_LOCK_FINISH, historyName, uid);
}
}
if (mWakeLockNesting == 0) {
diff --git a/core/java/com/android/internal/util/Protocol.java b/core/java/com/android/internal/util/Protocol.java
index 81e67d8..af966b1 100644
--- a/core/java/com/android/internal/util/Protocol.java
+++ b/core/java/com/android/internal/util/Protocol.java
@@ -57,9 +57,9 @@ public class Protocol {
public static final int BASE_DNS_PINGER = 0x00050000;
public static final int BASE_NSD_MANAGER = 0x00060000;
public static final int BASE_NETWORK_STATE_TRACKER = 0x00070000;
- public static final int BASE_CONNECTIVITY_SERVICE = 0x00080000;
+ public static final int BASE_CONNECTIVITY_MANAGER = 0x00080000;
public static final int BASE_NETWORK_AGENT = 0x00081000;
public static final int BASE_NETWORK_MONITOR = 0x00082000;
- public static final int BASE_CONNECTIVITY_MANAGER = 0x00083000;
+ public static final int BASE_NETWORK_FACTORY = 0x00083000;
//TODO: define all used protocols
}
diff --git a/core/java/com/android/internal/widget/ActionBarView.java b/core/java/com/android/internal/widget/ActionBarView.java
index af82778..77559c0 100644
--- a/core/java/com/android/internal/widget/ActionBarView.java
+++ b/core/java/com/android/internal/widget/ActionBarView.java
@@ -349,10 +349,7 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
return mIncludeTabs;
}
- public void setEmbeddedTabView(View view) {
- setEmbeddedTabView((ScrollingTabContainerView) view);
- }
-
+ @Override
public void setEmbeddedTabView(ScrollingTabContainerView tabs) {
if (mTabScrollView != null) {
removeView(mTabScrollView);
@@ -758,6 +755,7 @@ public class ActionBarView extends AbsActionBarView implements DecorToolbar {
mNavItemSelectedListener = l;
if (mSpinner != null) {
mSpinner.setAdapter(adapter);
+ mSpinner.setOnItemSelectedListener(l);
}
}
diff --git a/core/java/com/android/internal/widget/DecorToolbar.java b/core/java/com/android/internal/widget/DecorToolbar.java
index ee6988e..5281045 100644
--- a/core/java/com/android/internal/widget/DecorToolbar.java
+++ b/core/java/com/android/internal/widget/DecorToolbar.java
@@ -71,7 +71,7 @@ public interface DecorToolbar {
int getDisplayOptions();
void setDisplayOptions(int opts);
- void setEmbeddedTabView(View tabView);
+ void setEmbeddedTabView(ScrollingTabContainerView tabView);
boolean hasEmbeddedTabs();
boolean isTitleTruncated();
void setCollapsible(boolean collapsible);
diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
index 3e15c32..b298d85 100644
--- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
+++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
@@ -27,6 +27,7 @@ import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
+import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.View;
@@ -78,6 +79,8 @@ public class ToolbarWidgetWrapper implements DecorToolbar {
private boolean mMenuPrepared;
private ActionMenuPresenter mActionMenuPresenter;
+ private int mNavigationMode = ActionBar.NAVIGATION_MODE_STANDARD;
+
public ToolbarWidgetWrapper(Toolbar toolbar) {
mToolbar = toolbar;
@@ -394,8 +397,19 @@ public class ToolbarWidgetWrapper implements DecorToolbar {
}
@Override
- public void setEmbeddedTabView(View tabView) {
+ public void setEmbeddedTabView(ScrollingTabContainerView tabView) {
+ if (mTabView != null && mTabView.getParent() == mToolbar) {
+ mToolbar.removeView(mTabView);
+ }
mTabView = tabView;
+ if (tabView != null && mNavigationMode == ActionBar.NAVIGATION_MODE_TABS) {
+ mToolbar.addView(mTabView, 0);
+ Toolbar.LayoutParams lp = (Toolbar.LayoutParams) mTabView.getLayoutParams();
+ lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ lp.gravity = Gravity.START | Gravity.BOTTOM;
+ tabView.setAllowCollapse(true);
+ }
}
@Override
@@ -420,23 +434,63 @@ public class ToolbarWidgetWrapper implements DecorToolbar {
@Override
public int getNavigationMode() {
- return 0;
+ return mNavigationMode;
}
@Override
public void setNavigationMode(int mode) {
- if (mode != ActionBar.NAVIGATION_MODE_STANDARD) {
- throw new IllegalArgumentException(
- "Navigation modes not supported in this configuration");
+ final int oldMode = mNavigationMode;
+ if (mode != oldMode) {
+ switch (oldMode) {
+ case ActionBar.NAVIGATION_MODE_LIST:
+ if (mSpinner != null && mSpinner.getParent() == mToolbar) {
+ mToolbar.removeView(mSpinner);
+ }
+ break;
+ case ActionBar.NAVIGATION_MODE_TABS:
+ if (mTabView != null && mTabView.getParent() == mToolbar) {
+ mToolbar.removeView(mTabView);
+ }
+ break;
+ }
+
+ mNavigationMode = mode;
+
+ switch (mode) {
+ case ActionBar.NAVIGATION_MODE_STANDARD:
+ break;
+ case ActionBar.NAVIGATION_MODE_LIST:
+ ensureSpinner();
+ mToolbar.addView(mSpinner, 0);
+ break;
+ case ActionBar.NAVIGATION_MODE_TABS:
+ if (mTabView != null) {
+ mToolbar.addView(mTabView, 0);
+ Toolbar.LayoutParams lp = (Toolbar.LayoutParams) mTabView.getLayoutParams();
+ lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
+ lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+ lp.gravity = Gravity.START | Gravity.BOTTOM;
+ }
+ break;
+ default:
+ throw new IllegalArgumentException("Invalid navigation mode " + mode);
+ }
}
}
- @Override
- public void setDropdownParams(SpinnerAdapter adapter,
- AdapterView.OnItemSelectedListener listener) {
+ private void ensureSpinner() {
if (mSpinner == null) {
mSpinner = new Spinner(getContext());
+ Toolbar.LayoutParams lp = new Toolbar.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
+ ViewGroup.LayoutParams.WRAP_CONTENT, Gravity.START | Gravity.CENTER_VERTICAL);
+ mSpinner.setLayoutParams(lp);
}
+ }
+
+ @Override
+ public void setDropdownParams(SpinnerAdapter adapter,
+ AdapterView.OnItemSelectedListener listener) {
+ ensureSpinner();
mSpinner.setAdapter(adapter);
mSpinner.setOnItemSelectedListener(listener);
}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f446c3a..a1cd7f7 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -57,7 +57,6 @@ LOCAL_SRC_FILES:= \
android_view_KeyEvent.cpp \
android_view_KeyCharacterMap.cpp \
android_view_GraphicBuffer.cpp \
- android_view_GLRenderer.cpp \
android_view_GLES20Canvas.cpp \
android_view_HardwareLayer.cpp \
android_view_ThreadedRenderer.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index e069876..16727ab2 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -29,7 +29,6 @@
#include <SkGraphics.h>
#include <SkImageDecoder.h>
-#include <SkImageRef_GlobalPool.h>
#include "jni.h"
#include "JNIHelp.h"
@@ -130,7 +129,6 @@ extern int register_android_view_RenderNode(JNIEnv* env);
extern int register_android_view_RenderNodeAnimator(JNIEnv* env);
extern int register_android_view_GraphicBuffer(JNIEnv* env);
extern int register_android_view_GLES20Canvas(JNIEnv* env);
-extern int register_android_view_GLRenderer(JNIEnv* env);
extern int register_android_view_HardwareLayer(JNIEnv* env);
extern int register_android_view_ThreadedRenderer(JNIEnv* env);
extern int register_android_view_Surface(JNIEnv* env);
@@ -248,11 +246,6 @@ AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength)
// this sets our preference for 16bit images during decode
// in case the src is opaque and 24bit
SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
- // This cache is shared between browser native images, and java "purgeable"
- // bitmaps. This globalpool is for images that do not either use the java
- // heap, or are not backed by ashmem. See BitmapFactory.cpp for the key
- // java call site.
- SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);
// There is also a global font cache, but its budget is specified in code
// see SkFontHost_android.cpp
@@ -1214,7 +1207,6 @@ static const RegJNIRec gRegJNI[] = {
REG_JNI(register_android_view_RenderNodeAnimator),
REG_JNI(register_android_view_GraphicBuffer),
REG_JNI(register_android_view_GLES20Canvas),
- REG_JNI(register_android_view_GLRenderer),
REG_JNI(register_android_view_HardwareLayer),
REG_JNI(register_android_view_ThreadedRenderer),
REG_JNI(register_android_view_Surface),
diff --git a/core/jni/android/graphics/BitmapFactory.cpp b/core/jni/android/graphics/BitmapFactory.cpp
index 928a7f8..5106f0d 100644
--- a/core/jni/android/graphics/BitmapFactory.cpp
+++ b/core/jni/android/graphics/BitmapFactory.cpp
@@ -2,11 +2,8 @@
#include "BitmapFactory.h"
#include "NinePatchPeeker.h"
-#include "SkData.h"
#include "SkFrontBufferedStream.h"
#include "SkImageDecoder.h"
-#include "SkImageRef_ashmem.h"
-#include "SkImageRef_GlobalPool.h"
#include "SkMath.h"
#include "SkPixelRef.h"
#include "SkStream.h"
@@ -32,8 +29,6 @@ jfieldID gOptions_configFieldID;
jfieldID gOptions_premultipliedFieldID;
jfieldID gOptions_mutableFieldID;
jfieldID gOptions_ditherFieldID;
-jfieldID gOptions_purgeableFieldID;
-jfieldID gOptions_shareableFieldID;
jfieldID gOptions_preferQualityOverSpeedFieldID;
jfieldID gOptions_scaledFieldID;
jfieldID gOptions_densityFieldID;
@@ -90,14 +85,6 @@ jstring getMimeTypeString(JNIEnv* env, SkImageDecoder::Format format) {
return jstr;
}
-static bool optionsPurgeable(JNIEnv* env, jobject options) {
- return options != NULL && env->GetBooleanField(options, gOptions_purgeableFieldID);
-}
-
-static bool optionsShareable(JNIEnv* env, jobject options) {
- return options != NULL && env->GetBooleanField(options, gOptions_shareableFieldID);
-}
-
static bool optionsJustBounds(JNIEnv* env, jobject options) {
return options != NULL && env->GetBooleanField(options, gOptions_justBoundsFieldID);
}
@@ -125,27 +112,6 @@ static void scaleNinePatchChunk(android::Res_png_9patch* chunk, float scale) {
}
}
-static SkPixelRef* installPixelRef(SkBitmap* bitmap, SkStreamRewindable* stream,
- int sampleSize, bool ditherImage) {
-
- if (kUnknown_SkColorType == bitmap->colorType()) {
- ALOGW("bitmap has unknown configuration so no memory has been allocated");
- return NULL;
- }
-
- SkImageRef* pr;
- // only use ashmem for large images, since mmaps come at a price
- if (bitmap->getSize() >= 32 * 1024) {
- pr = new SkImageRef_ashmem(bitmap->info(), stream, sampleSize);
- } else {
- pr = new SkImageRef_GlobalPool(bitmap->info(), stream, sampleSize);
- }
- pr->setDitherImage(ditherImage);
- bitmap->setPixelRef(pr)->unref();
- pr->isOpaque(bitmap);
- return pr;
-}
-
static SkColorType colorTypeForScaledOutput(SkColorType colorType) {
switch (colorType) {
case kUnknown_SkColorType:
@@ -229,21 +195,17 @@ private:
const unsigned int mSize;
};
-// since we "may" create a purgeable imageref, we require the stream be ref'able
-// i.e. dynamically allocated, since its lifetime may exceed the current stack
-// frame.
static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding,
- jobject options, bool allowPurgeable, bool forcePurgeable = false) {
+ jobject options) {
int sampleSize = 1;
- SkImageDecoder::Mode mode = SkImageDecoder::kDecodePixels_Mode;
+ SkImageDecoder::Mode decodeMode = SkImageDecoder::kDecodePixels_Mode;
SkBitmap::Config prefConfig = SkBitmap::kARGB_8888_Config;
bool doDither = true;
bool isMutable = false;
float scale = 1.0f;
- bool isPurgeable = forcePurgeable || (allowPurgeable && optionsPurgeable(env, options));
bool preferQualityOverSpeed = false;
bool requireUnpremultiplied = false;
@@ -252,7 +214,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
if (options != NULL) {
sampleSize = env->GetIntField(options, gOptions_sampleSizeFieldID);
if (optionsJustBounds(env, options)) {
- mode = SkImageDecoder::kDecodeBounds_Mode;
+ decodeMode = SkImageDecoder::kDecodeBounds_Mode;
}
// initialize these, in case we fail later on
@@ -280,7 +242,6 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
const bool willScale = scale != 1.0f;
- isPurgeable &= !willScale;
SkImageDecoder* decoder = SkImageDecoder::Factory(stream);
if (decoder == NULL) {
@@ -311,8 +272,6 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
NinePatchPeeker peeker(decoder);
decoder->setPeeker(&peeker);
- SkImageDecoder::Mode decodeMode = isPurgeable ? SkImageDecoder::kDecodeBounds_Mode : mode;
-
JavaPixelAllocator javaAllocator(env);
RecyclingPixelAllocator recyclingAllocator(outputBitmap->pixelRef(), existingBufferSize);
ScaleCheckingAllocator scaleCheckingAllocator(scale, existingBufferSize);
@@ -353,7 +312,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
int scaledWidth = decodingBitmap.width();
int scaledHeight = decodingBitmap.height();
- if (willScale && mode != SkImageDecoder::kDecodeBounds_Mode) {
+ if (willScale && decodeMode != SkImageDecoder::kDecodeBounds_Mode) {
scaledWidth = int(scaledWidth * scale + 0.5f);
scaledHeight = int(scaledHeight * scale + 0.5f);
}
@@ -367,7 +326,7 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
// if we're in justBounds mode, return now (skip the java bitmap)
- if (mode == SkImageDecoder::kDecodeBounds_Mode) {
+ if (decodeMode == SkImageDecoder::kDecodeBounds_Mode) {
return NULL;
}
@@ -459,21 +418,15 @@ static jobject doDecode(JNIEnv* env, SkStreamRewindable* stream, jobject padding
}
}
- SkPixelRef* pr;
- if (isPurgeable) {
- pr = installPixelRef(outputBitmap, stream, sampleSize, doDither);
- } else {
- // if we get here, we're in kDecodePixels_Mode and will therefore
- // already have a pixelref installed.
- pr = outputBitmap->pixelRef();
- }
- if (pr == NULL) {
+ // if we get here, we're in kDecodePixels_Mode and will therefore
+ // already have a pixelref installed.
+ if (outputBitmap->pixelRef() == NULL) {
return nullObjectReturn("Got null SkPixelRef");
}
if (!isMutable && javaBitmap == NULL) {
// promise we will never change our pixels (great for sharing and pictures)
- pr->setImmutable();
+ outputBitmap->setImmutable();
}
// detach bitmap from its autodeleter, since we want to own it now
@@ -512,8 +465,7 @@ static jobject nativeDecodeStream(JNIEnv* env, jobject clazz, jobject is, jbyteA
SkAutoTUnref<SkStreamRewindable> bufferedStream(
SkFrontBufferedStream::Create(stream, BYTES_TO_BUFFER));
SkASSERT(bufferedStream.get() != NULL);
- // for now we don't allow purgeable with java inputstreams
- bitmap = doDecode(env, bufferedStream, padding, options, false, false);
+ bitmap = doDecode(env, bufferedStream, padding, options);
}
return bitmap;
}
@@ -542,76 +494,33 @@ static jobject nativeDecodeFileDescriptor(JNIEnv* env, jobject clazz, jobject fi
SkAutoTUnref<SkFILEStream> fileStream(new SkFILEStream(file,
SkFILEStream::kCallerRetains_Ownership));
- SkAutoTUnref<SkStreamRewindable> stream;
-
- // Retain the old behavior of allowing purgeable if both purgeable and
- // shareable are set to true.
- bool isPurgeable = optionsPurgeable(env, bitmapFactoryOptions)
- && optionsShareable(env, bitmapFactoryOptions);
- if (isPurgeable) {
- // Copy the stream, so the image can be decoded multiple times without
- // continuing to modify the original file descriptor.
- // Copy beginning from the current position.
- const size_t fileSize = fileStream->getLength() - fileStream->getPosition();
- void* buffer = sk_malloc_flags(fileSize, 0);
- if (buffer == NULL) {
- return nullObjectReturn("Could not make a copy for ashmem");
- }
-
- SkAutoTUnref<SkData> data(SkData::NewFromMalloc(buffer, fileSize));
+ // Use a buffered stream. Although an SkFILEStream can be rewound, this
+ // ensures that SkImageDecoder::Factory never rewinds beyond the
+ // current position of the file descriptor.
+ SkAutoTUnref<SkStreamRewindable> stream(SkFrontBufferedStream::Create(fileStream,
+ BYTES_TO_BUFFER));
- if (fileStream->read(buffer, fileSize) != fileSize) {
- return nullObjectReturn("Could not read the file.");
- }
-
- stream.reset(new SkMemoryStream(data));
- } else {
- // Use a buffered stream. Although an SkFILEStream can be rewound, this
- // ensures that SkImageDecoder::Factory never rewinds beyond the
- // current position of the file descriptor.
- stream.reset(SkFrontBufferedStream::Create(fileStream, BYTES_TO_BUFFER));
- }
-
- return doDecode(env, stream, padding, bitmapFactoryOptions, isPurgeable);
+ return doDecode(env, stream, padding, bitmapFactoryOptions);
}
static jobject nativeDecodeAsset(JNIEnv* env, jobject clazz, jlong native_asset,
jobject padding, jobject options) {
- SkStreamRewindable* stream;
Asset* asset = reinterpret_cast<Asset*>(native_asset);
- bool forcePurgeable = optionsPurgeable(env, options);
- if (forcePurgeable) {
- // if we could "ref/reopen" the asset, we may not need to copy it here
- // and we could assume optionsShareable, since assets are always RO
- stream = CopyAssetToStream(asset);
- if (stream == NULL) {
- return NULL;
- }
- } else {
- // since we know we'll be done with the asset when we return, we can
- // just use a simple wrapper
- stream = new AssetStreamAdaptor(asset,
- AssetStreamAdaptor::kNo_OwnAsset,
- AssetStreamAdaptor::kNo_HasMemoryBase);
- }
- SkAutoUnref aur(stream);
- return doDecode(env, stream, padding, options, forcePurgeable, forcePurgeable);
+ // since we know we'll be done with the asset when we return, we can
+ // just use a simple wrapper
+ SkAutoTUnref<SkStreamRewindable> stream(new AssetStreamAdaptor(asset,
+ AssetStreamAdaptor::kNo_OwnAsset, AssetStreamAdaptor::kNo_HasMemoryBase));
+ return doDecode(env, stream, padding, options);
}
static jobject nativeDecodeByteArray(JNIEnv* env, jobject, jbyteArray byteArray,
jint offset, jint length, jobject options) {
- /* If optionsShareable() we could decide to just wrap the java array and
- share it, but that means adding a globalref to the java array object
- and managing its lifetime. For now we just always copy the array's data
- if optionsPurgeable(), unless we're just decoding bounds.
- */
- bool purgeable = optionsPurgeable(env, options) && !optionsJustBounds(env, options);
AutoJavaByteArray ar(env, byteArray);
- SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, purgeable);
+ SkMemoryStream* stream = new SkMemoryStream(ar.ptr() + offset, length, false);
SkAutoUnref aur(stream);
- return doDecode(env, stream, NULL, options, purgeable);
+ return doDecode(env, stream, NULL, options);
}
static void nativeRequestCancel(JNIEnv*, jobject joptions) {
@@ -675,8 +584,6 @@ int register_android_graphics_BitmapFactory(JNIEnv* env) {
gOptions_premultipliedFieldID = getFieldIDCheck(env, options_class, "inPremultiplied", "Z");
gOptions_mutableFieldID = getFieldIDCheck(env, options_class, "inMutable", "Z");
gOptions_ditherFieldID = getFieldIDCheck(env, options_class, "inDither", "Z");
- gOptions_purgeableFieldID = getFieldIDCheck(env, options_class, "inPurgeable", "Z");
- gOptions_shareableFieldID = getFieldIDCheck(env, options_class, "inInputShareable", "Z");
gOptions_preferQualityOverSpeedFieldID = getFieldIDCheck(env, options_class,
"inPreferQualityOverSpeed", "Z");
gOptions_scaledFieldID = getFieldIDCheck(env, options_class, "inScaled", "Z");
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 5fca582..bdaf3a0 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -22,7 +22,6 @@
#include "SkDevice.h"
#include "SkDrawFilter.h"
#include "SkGraphics.h"
-#include "SkImageRef_GlobalPool.h"
#include "SkPorterDuff.h"
#include "SkShader.h"
#include "SkTemplates.h"
@@ -161,8 +160,6 @@ public:
}
static void freeCaches(JNIEnv* env, jobject) {
- // these are called in no particular order
- SkImageRef_GlobalPool::SetRAMUsed(0);
SkGraphics::PurgeFontCache();
}
@@ -170,56 +167,33 @@ public:
TextLayoutEngine::getInstance().purgeCaches();
}
- static jboolean isOpaque(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static jboolean isOpaque(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
bool result = canvas->getDevice()->accessBitmap(false).isOpaque();
return result ? JNI_TRUE : JNI_FALSE;
}
- static jint getWidth(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static jint getWidth(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
int width = canvas->getDevice()->accessBitmap(false).width();
return static_cast<jint>(width);
}
- static jint getHeight(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static jint getHeight(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
int height = canvas->getDevice()->accessBitmap(false).height();
return static_cast<jint>(height);
}
- static jint saveAll(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save();
- return static_cast<jint>(result);
- }
-
- static jint save(JNIEnv* env, jobject jcanvas, jint flagsHandle) {
- SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->save(flags);
- return static_cast<jint>(result);
- }
-
- static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle, jobject bounds,
- jlong paintHandle, jint flags) {
+ static jint save(JNIEnv*, jobject, jlong canvasHandle, jint flagsHandle) {
SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect* bounds_ = NULL;
- SkRect storage;
- if (bounds != NULL) {
- GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
- bounds_ = &storage;
- }
- return canvas->saveLayer(bounds_, paint, static_cast<SkCanvas::SaveFlags>(flags));
+ SkCanvas::SaveFlags flags = static_cast<SkCanvas::SaveFlags>(flagsHandle);
+ return static_cast<jint>(canvas->save(flags));
}
- static jint saveLayer4F(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat l, jfloat t, jfloat r, jfloat b,
- jlong paintHandle, jint flags) {
+ static jint saveLayer(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloat l, jfloat t, jfloat r, jfloat b,
+ jlong paintHandle, jint flags) {
SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
SkRect bounds;
@@ -230,22 +204,8 @@ public:
}
static jint saveLayerAlpha(JNIEnv* env, jobject, jlong canvasHandle,
- jobject bounds, jint alpha, jint flags) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkRect* bounds_ = NULL;
- SkRect storage;
- if (bounds != NULL) {
- GraphicsJNI::jrectf_to_rect(env, bounds, &storage);
- bounds_ = &storage;
- }
- int result = canvas->saveLayerAlpha(bounds_, alpha,
- static_cast<SkCanvas::SaveFlags>(flags));
- return static_cast<jint>(result);
- }
-
- static jint saveLayerAlpha4F(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat l, jfloat t, jfloat r, jfloat b,
- jint alpha, jint flags) {
+ jfloat l, jfloat t, jfloat r, jfloat b,
+ jint alpha, jint flags) {
SkCanvas* canvas = getNativeCanvas(canvasHandle);
SkRect bounds;
bounds.set(l, t, r, b);
@@ -254,9 +214,8 @@ public:
return static_cast<jint>(result);
}
- static void restore(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static void restore(JNIEnv* env, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
if (canvas->getSaveCount() <= 1) { // cannot restore anymore
doThrowISE(env, "Underflow in restore");
return;
@@ -264,15 +223,14 @@ public:
canvas->restore();
}
- static jint getSaveCount(JNIEnv* env, jobject jcanvas) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- int result = GraphicsJNI::getNativeCanvas(env, jcanvas)->getSaveCount();
- return static_cast<jint>(result);
+ static jint getSaveCount(JNIEnv*, jobject, jlong canvasHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ return static_cast<jint>(canvas->getSaveCount());
}
- static void restoreToCount(JNIEnv* env, jobject jcanvas, jint restoreCount) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
+ static void restoreToCount(JNIEnv* env, jobject, jlong canvasHandle,
+ jint restoreCount) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
if (restoreCount < 1) {
doThrowIAE(env, "Underflow in restoreToCount");
return;
@@ -280,24 +238,24 @@ public:
canvas->restoreToCount(restoreCount);
}
- static void translate(JNIEnv* env, jobject jcanvas, jfloat dx, jfloat dy) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->translate(dx, dy);
+ static void translate(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat dx, jfloat dy) {
+ getNativeCanvas(canvasHandle)->translate(dx, dy);
}
- static void scale__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->scale(sx, sy);
+ static void scale__FF(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat sx, jfloat sy) {
+ getNativeCanvas(canvasHandle)->scale(sx, sy);
}
- static void rotate__F(JNIEnv* env, jobject jcanvas, jfloat degrees) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->rotate(degrees);
+ static void rotate__F(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat degrees) {
+ getNativeCanvas(canvasHandle)->rotate(degrees);
}
- static void skew__FF(JNIEnv* env, jobject jcanvas, jfloat sx, jfloat sy) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- (void)GraphicsJNI::getNativeCanvas(env, jcanvas)->skew(sx, sy);
+ static void skew__FF(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat sx, jfloat sy) {
+ getNativeCanvas(canvasHandle)->skew(sx, sy);
}
static void concat(JNIEnv* env, jobject, jlong canvasHandle,
@@ -318,56 +276,16 @@ public:
}
}
- static jboolean clipRect_FFFF(JNIEnv* env, jobject jcanvas, jfloat left,
- jfloat top, jfloat right, jfloat bottom) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
+ static jboolean clipRect(JNIEnv*, jobject, jlong canvasHandle,
+ jfloat left, jfloat top, jfloat right,
+ jfloat bottom, jint op) {
SkRect r;
r.set(left, top, right, bottom);
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- c->clipRect(r);
- return hasNonEmptyClip(*c);
- }
-
- static jboolean clipRect_IIII(JNIEnv* env, jobject jcanvas, jint left,
- jint top, jint right, jint bottom) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- SkRect r;
- r.set(SkIntToScalar(left), SkIntToScalar(top),
- SkIntToScalar(right), SkIntToScalar(bottom));
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- c->clipRect(r);
- return hasNonEmptyClip(*c);
- }
-
- static jboolean clipRect_RectF(JNIEnv* env, jobject jcanvas, jobject rectf) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- NPE_CHECK_RETURN_ZERO(env, rectf);
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- SkRect tmp;
- c->clipRect(*GraphicsJNI::jrectf_to_rect(env, rectf, &tmp));
+ SkCanvas* c = getNativeCanvas(canvasHandle);
+ c->clipRect(r, static_cast<SkRegion::Op>(op));
return hasNonEmptyClip(*c);
}
- static jboolean clipRect_Rect(JNIEnv* env, jobject jcanvas, jobject rect) {
- NPE_CHECK_RETURN_ZERO(env, jcanvas);
- NPE_CHECK_RETURN_ZERO(env, rect);
- SkCanvas* c = GraphicsJNI::getNativeCanvas(env, jcanvas);
- SkRect tmp;
- c->clipRect(*GraphicsJNI::jrect_to_rect(env, rect, &tmp));
- return hasNonEmptyClip(*c);
-
- }
-
- static jboolean clipRect(JNIEnv* env, jobject, jlong canvasHandle,
- jfloat left, jfloat top, jfloat right, jfloat bottom,
- jint op) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkRect rect;
- rect.set(left, top, right, bottom);
- canvas->clipRect(rect, static_cast<SkRegion::Op>(op));
- return hasNonEmptyClip(*canvas);
- }
-
static jboolean clipPath(JNIEnv* env, jobject, jlong canvasHandle,
jlong pathHandle, jint op) {
SkCanvas* canvas = getNativeCanvas(canvasHandle);
@@ -390,15 +308,6 @@ public:
canvas->setDrawFilter(reinterpret_cast<SkDrawFilter*>(filterHandle));
}
- static jboolean quickReject__RectF(JNIEnv* env, jobject, jlong canvasHandle,
- jobject rect) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkRect rect_;
- GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
- bool result = canvas->quickReject(rect_);
- return result ? JNI_TRUE : JNI_FALSE;
- }
-
static jboolean quickReject__Path(JNIEnv* env, jobject, jlong canvasHandle,
jlong pathHandle) {
SkCanvas* canvas = getNativeCanvas(canvasHandle);
@@ -448,15 +357,13 @@ public:
canvas->drawPaint(*paint);
}
- static void doPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
- jint offset, jint count, jobject jpaint,
- jint modeHandle) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
+ static void doPoints(JNIEnv* env, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset, jint count,
+ jlong paintHandle, jint modeHandle) {
NPE_CHECK_RETURN_VOID(env, jptsArray);
- NPE_CHECK_RETURN_VOID(env, jpaint);
SkCanvas::PointMode mode = static_cast<SkCanvas::PointMode>(modeHandle);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
- const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
AutoJavaFloatArray autoPts(env, jptsArray);
float* floats = autoPts.ptr();
@@ -476,29 +383,28 @@ public:
pts[i].set(src[0], src[1]);
src += 2;
}
- canvas->drawPoints(mode, count, pts, paint);
+ canvas->drawPoints(mode, count, pts, *paint);
}
- static void drawPoints(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
- jint offset, jint count, jobject jpaint) {
- doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
+ static void drawPoints(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset,
+ jint count, jlong paintHandle) {
+ doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
SkCanvas::kPoints_PointMode);
}
- static void drawLines(JNIEnv* env, jobject jcanvas, jfloatArray jptsArray,
- jint offset, jint count, jobject jpaint) {
- doPoints(env, jcanvas, jptsArray, offset, count, jpaint,
+ static void drawLines(JNIEnv* env, jobject, jlong canvasHandle,
+ jfloatArray jptsArray, jint offset, jint count,
+ jlong paintHandle) {
+ doPoints(env, canvasHandle, jptsArray, offset, count, paintHandle,
SkCanvas::kLines_PointMode);
}
- static void drawPoint(JNIEnv* env, jobject jcanvas, jfloat x, jfloat y,
- jobject jpaint) {
- NPE_CHECK_RETURN_VOID(env, jcanvas);
- NPE_CHECK_RETURN_VOID(env, jpaint);
- SkCanvas* canvas = GraphicsJNI::getNativeCanvas(env, jcanvas);
- const SkPaint& paint = *GraphicsJNI::getNativePaint(env, jpaint);
-
- canvas->drawPoint(x, y, paint);
+ static void drawPoint(JNIEnv*, jobject, jlong canvasHandle, jfloat x, jfloat y,
+ jlong paintHandle) {
+ SkCanvas* canvas = getNativeCanvas(canvasHandle);
+ const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ canvas->drawPoint(x, y, *paint);
}
static void drawLine__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
@@ -509,15 +415,6 @@ public:
canvas->drawLine(startX, startY, stopX, stopY, *paint);
}
- static void drawRect__RectFPaint(JNIEnv* env, jobject, jlong canvasHandle,
- jobject rect, jlong paintHandle) {
- SkCanvas* canvas = getNativeCanvas(canvasHandle);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
- SkRect rect_;
- GraphicsJNI::jrectf_to_rect(env, rect, &rect_);
- canvas->drawRect(rect_, *paint);
- }
-
static void drawRect__FFFFPaint(JNIEnv* env, jobject, jlong canvasHandle,
jfloat left, jfloat top, jfloat right,
jfloat bottom, jlong paintHandle) {
@@ -863,32 +760,45 @@ public:
}
#ifdef USE_MINIKIN
- static void drawGlyphsToSkia(SkCanvas* canvas, SkPaint* paint, Layout* layout, float x, float y) {
- size_t nGlyphs = layout->nGlyphs();
- uint16_t *glyphs = new uint16_t[nGlyphs];
- SkPoint *pos = new SkPoint[nGlyphs];
- SkTypeface *lastFace = NULL;
- SkTypeface *skFace = NULL;
- size_t start = 0;
-
- paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
- for (size_t i = 0; i < nGlyphs; i++) {
- MinikinFontSkia *mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
- skFace = mfs->GetSkTypeface();
- glyphs[i] = layout->getGlyphId(i);
- pos[i].fX = x + layout->getX(i);
- pos[i].fY = y + layout->getY(i);
- if (i > 0 && skFace != lastFace) {
- paint->setTypeface(lastFace);
- canvas->drawPosText(glyphs + start, (i - start) << 1, pos + start, *paint);
- start = i;
+ class DrawTextFunctor {
+ public:
+ DrawTextFunctor(const Layout& layout, SkCanvas* canvas, jfloat x, jfloat y, SkPaint* paint,
+ uint16_t* glyphs, SkPoint* pos)
+ : layout(layout), canvas(canvas), x(x), y(y), paint(paint), glyphs(glyphs),
+ pos(pos) { }
+
+ void operator()(SkTypeface* t, size_t start, size_t end) {
+ for (size_t i = start; i < end; i++) {
+ glyphs[i] = layout.getGlyphId(i);
+ pos[i].fX = x + layout.getX(i);
+ pos[i].fY = y + layout.getY(i);
}
- lastFace = skFace;
- }
- if (skFace != NULL) {
- paint->setTypeface(skFace);
- canvas->drawPosText(glyphs + start, (nGlyphs - start) << 1, pos + start, *paint);
+ paint->setTypeface(t);
+ canvas->drawPosText(glyphs + start, (end - start) << 1, pos + start, *paint);
}
+ private:
+ const Layout& layout;
+ SkCanvas* canvas;
+ jfloat x;
+ jfloat y;
+ SkPaint* paint;
+ uint16_t* glyphs;
+ SkPoint* pos;
+ };
+
+ static void drawGlyphsToSkia(SkCanvas* canvas, SkPaint* paint, const Layout& layout, float x, float y) {
+ size_t nGlyphs = layout.nGlyphs();
+ uint16_t* glyphs = new uint16_t[nGlyphs];
+ SkPoint* pos = new SkPoint[nGlyphs];
+
+ x += MinikinUtils::xOffsetForTextAlign(paint, layout);
+ SkPaint::Align align = paint->getTextAlign();
+ paint->setTextAlign(SkPaint::kLeft_Align);
+ paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ DrawTextFunctor f(layout, canvas, x, y, paint, glyphs, pos);
+ MinikinUtils::forFontRun(layout, f);
+ doDrawTextDecorations(canvas, x, y, layout.getAdvance(), paint);
+ paint->setTextAlign(align);
delete[] glyphs;
delete[] pos;
}
@@ -910,7 +820,7 @@ public:
Layout layout;
MinikinUtils::SetLayoutProperties(&layout, paint, flags, typeface);
layout.doLayout(textArray + start, count);
- drawGlyphsToSkia(canvas, paint, &layout, x, y);
+ drawGlyphsToSkia(canvas, paint, layout, x, y);
#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(paint,
textArray, start, count, contextCount, flags);
@@ -1153,33 +1063,21 @@ static JNINativeMethod gCanvasMethods[] = {
{"initRaster", "(J)J", (void*) SkCanvasGlue::initRaster},
{"initCanvas", "(J)J", (void*) SkCanvasGlue::initCanvas},
{"native_setBitmap", "(JJZ)V", (void*) SkCanvasGlue::setBitmap},
- {"isOpaque","()Z", (void*) SkCanvasGlue::isOpaque},
- {"getWidth","()I", (void*) SkCanvasGlue::getWidth},
- {"getHeight","()I", (void*) SkCanvasGlue::getHeight},
- {"save","()I", (void*) SkCanvasGlue::saveAll},
- {"save","(I)I", (void*) SkCanvasGlue::save},
- {"native_saveLayer","(JLandroid/graphics/RectF;JI)I",
- (void*) SkCanvasGlue::saveLayer},
- {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer4F},
- {"native_saveLayerAlpha","(JLandroid/graphics/RectF;II)I",
- (void*) SkCanvasGlue::saveLayerAlpha},
- {"native_saveLayerAlpha","(JFFFFII)I",
- (void*) SkCanvasGlue::saveLayerAlpha4F},
- {"restore","()V", (void*) SkCanvasGlue::restore},
- {"getSaveCount","()I", (void*) SkCanvasGlue::getSaveCount},
- {"restoreToCount","(I)V", (void*) SkCanvasGlue::restoreToCount},
- {"translate","(FF)V", (void*) SkCanvasGlue::translate},
- {"scale","(FF)V", (void*) SkCanvasGlue::scale__FF},
- {"rotate","(F)V", (void*) SkCanvasGlue::rotate__F},
- {"skew","(FF)V", (void*) SkCanvasGlue::skew__FF},
+ {"native_isOpaque","(J)Z", (void*) SkCanvasGlue::isOpaque},
+ {"native_getWidth","(J)I", (void*) SkCanvasGlue::getWidth},
+ {"native_getHeight","(J)I", (void*) SkCanvasGlue::getHeight},
+ {"native_save","(JI)I", (void*) SkCanvasGlue::save},
+ {"native_saveLayer","(JFFFFJI)I", (void*) SkCanvasGlue::saveLayer},
+ {"native_saveLayerAlpha","(JFFFFII)I", (void*) SkCanvasGlue::saveLayerAlpha},
+ {"native_restore","(J)V", (void*) SkCanvasGlue::restore},
+ {"native_getSaveCount","(J)I", (void*) SkCanvasGlue::getSaveCount},
+ {"native_restoreToCount","(JI)V", (void*) SkCanvasGlue::restoreToCount},
+ {"native_translate","(JFF)V", (void*) SkCanvasGlue::translate},
+ {"native_scale","(JFF)V", (void*) SkCanvasGlue::scale__FF},
+ {"native_rotate","(JF)V", (void*) SkCanvasGlue::rotate__F},
+ {"native_skew","(JFF)V", (void*) SkCanvasGlue::skew__FF},
{"native_concat","(JJ)V", (void*) SkCanvasGlue::concat},
{"native_setMatrix","(JJ)V", (void*) SkCanvasGlue::setMatrix},
- {"clipRect","(FFFF)Z", (void*) SkCanvasGlue::clipRect_FFFF},
- {"clipRect","(IIII)Z", (void*) SkCanvasGlue::clipRect_IIII},
- {"clipRect","(Landroid/graphics/RectF;)Z",
- (void*) SkCanvasGlue::clipRect_RectF},
- {"clipRect","(Landroid/graphics/Rect;)Z",
- (void*) SkCanvasGlue::clipRect_Rect},
{"native_clipRect","(JFFFFI)Z", (void*) SkCanvasGlue::clipRect},
{"native_clipPath","(JJI)Z", (void*) SkCanvasGlue::clipPath},
{"native_clipRegion","(JJI)Z", (void*) SkCanvasGlue::clipRegion},
@@ -1187,8 +1085,6 @@ static JNINativeMethod gCanvasMethods[] = {
{"native_getClipBounds","(JLandroid/graphics/Rect;)Z",
(void*) SkCanvasGlue::getClipBounds},
{"native_getCTM", "(JJ)V", (void*)SkCanvasGlue::getCTM},
- {"native_quickReject","(JLandroid/graphics/RectF;)Z",
- (void*) SkCanvasGlue::quickReject__RectF},
{"native_quickReject","(JJ)Z", (void*) SkCanvasGlue::quickReject__Path},
{"native_quickReject","(JFFFF)Z", (void*)SkCanvasGlue::quickReject__FFFF},
{"native_drawRGB","(JIII)V", (void*) SkCanvasGlue::drawRGB},
@@ -1196,15 +1092,10 @@ static JNINativeMethod gCanvasMethods[] = {
{"native_drawColor","(JI)V", (void*) SkCanvasGlue::drawColor__I},
{"native_drawColor","(JII)V", (void*) SkCanvasGlue::drawColor__II},
{"native_drawPaint","(JJ)V", (void*) SkCanvasGlue::drawPaint},
- {"drawPoint", "(FFLandroid/graphics/Paint;)V",
- (void*) SkCanvasGlue::drawPoint},
- {"drawPoints", "([FIILandroid/graphics/Paint;)V",
- (void*) SkCanvasGlue::drawPoints},
- {"drawLines", "([FIILandroid/graphics/Paint;)V",
- (void*) SkCanvasGlue::drawLines},
+ {"native_drawPoint", "(JFFJ)V", (void*) SkCanvasGlue::drawPoint},
+ {"native_drawPoints", "(J[FIIJ)V", (void*) SkCanvasGlue::drawPoints},
+ {"native_drawLines", "(J[FIIJ)V", (void*) SkCanvasGlue::drawLines},
{"native_drawLine","(JFFFFJ)V", (void*) SkCanvasGlue::drawLine__FFFFPaint},
- {"native_drawRect","(JLandroid/graphics/RectF;J)V",
- (void*) SkCanvasGlue::drawRect__RectFPaint},
{"native_drawRect","(JFFFFJ)V", (void*) SkCanvasGlue::drawRect__FFFFPaint},
{"native_drawOval","(JLandroid/graphics/RectF;J)V",
(void*) SkCanvasGlue::drawOval},
diff --git a/core/jni/android/graphics/FontFamily.cpp b/core/jni/android/graphics/FontFamily.cpp
index 3bab8a2..dd6b36f 100644
--- a/core/jni/android/graphics/FontFamily.cpp
+++ b/core/jni/android/graphics/FontFamily.cpp
@@ -23,6 +23,9 @@
#include "GraphicsJNI.h"
#include <ScopedPrimitiveArray.h>
#include <ScopedUtfChars.h>
+#include <android_runtime/android_util_AssetManager.h>
+#include <androidfw/AssetManager.h>
+#include "Utils.h"
#ifdef USE_MINIKIN
#include <minikin/FontFamily.h>
@@ -51,19 +54,60 @@ static void FontFamily_unref(JNIEnv* env, jobject clazz, jlong familyPtr) {
#endif
}
+#ifdef USE_MINIKIN
+static jboolean addSkTypeface(FontFamily* family, SkTypeface* face) {
+ MinikinFont* minikinFont = new MinikinFontSkia(face);
+ bool result = family->addFont(minikinFont);
+ minikinFont->Unref();
+ return result;
+}
+#endif
+
static jboolean FontFamily_addFont(JNIEnv* env, jobject clazz, jlong familyPtr, jstring path) {
#ifdef USE_MINIKIN
NPE_CHECK_RETURN_ZERO(env, path);
ScopedUtfChars str(env, path);
- ALOGD("addFont %s", str.c_str());
SkTypeface* face = SkTypeface::CreateFromFile(str.c_str());
if (face == NULL) {
ALOGE("addFont failed to create font %s", str.c_str());
return false;
}
- MinikinFont* minikinFont = new MinikinFontSkia(face);
FontFamily* fontFamily = (FontFamily*)familyPtr;
- return fontFamily->addFont(minikinFont);
+ return addSkTypeface(fontFamily, face);
+#else
+ return false;
+#endif
+}
+
+static jboolean FontFamily_addFontFromAsset(JNIEnv* env, jobject, jlong familyPtr,
+ jobject jassetMgr, jstring jpath) {
+#ifdef USE_MINIKIN
+ NPE_CHECK_RETURN_ZERO(env, jassetMgr);
+ NPE_CHECK_RETURN_ZERO(env, jpath);
+
+ AssetManager* mgr = assetManagerForJavaObject(env, jassetMgr);
+ if (NULL == mgr) {
+ return false;
+ }
+
+ ScopedUtfChars str(env, jpath);
+ Asset* asset = mgr->open(str.c_str(), Asset::ACCESS_BUFFER);
+ if (NULL == asset) {
+ return false;
+ }
+
+ SkStream* stream = new AssetStreamAdaptor(asset,
+ AssetStreamAdaptor::kYes_OwnAsset,
+ AssetStreamAdaptor::kYes_HasMemoryBase);
+ SkTypeface* face = SkTypeface::CreateFromStream(stream);
+ // Note: SkTypeface::CreateFromStream holds its own reference to the stream
+ stream->unref();
+ if (face == NULL) {
+ ALOGE("addFontFromAsset failed to create font %s", str.c_str());
+ return false;
+ }
+ FontFamily* fontFamily = (FontFamily*)familyPtr;
+ return addSkTypeface(fontFamily, face);
#else
return false;
#endif
@@ -75,6 +119,8 @@ static JNINativeMethod gFontFamilyMethods[] = {
{ "nCreateFamily", "(Ljava/lang/String;I)J", (void*)FontFamily_create },
{ "nUnrefFamily", "(J)V", (void*)FontFamily_unref },
{ "nAddFont", "(JLjava/lang/String;)Z", (void*)FontFamily_addFont },
+ { "nAddFontFromAsset", "(JLandroid/content/res/AssetManager;Ljava/lang/String;)Z",
+ (void*)FontFamily_addFontFromAsset },
};
int register_android_graphics_FontFamily(JNIEnv* env)
diff --git a/core/jni/android/graphics/MinikinSkia.h b/core/jni/android/graphics/MinikinSkia.h
index 7a8954d..1cc2c51 100644
--- a/core/jni/android/graphics/MinikinSkia.h
+++ b/core/jni/android/graphics/MinikinSkia.h
@@ -18,6 +18,7 @@ namespace android {
class MinikinFontSkia : public MinikinFont {
public:
+ // Note: this takes ownership of the reference (will unref on dtor)
explicit MinikinFontSkia(SkTypeface *typeface);
~MinikinFontSkia();
diff --git a/core/jni/android/graphics/MinikinUtils.cpp b/core/jni/android/graphics/MinikinUtils.cpp
index 79381ad..a88b747 100644
--- a/core/jni/android/graphics/MinikinUtils.cpp
+++ b/core/jni/android/graphics/MinikinUtils.cpp
@@ -17,12 +17,13 @@
#include "SkPaint.h"
#include "minikin/Layout.h"
#include "TypefaceImpl.h"
+#include "MinikinSkia.h"
#include "MinikinUtils.h"
namespace android {
-void MinikinUtils::SetLayoutProperties(Layout* layout, SkPaint* paint, int flags,
+void MinikinUtils::SetLayoutProperties(Layout* layout, const SkPaint* paint, int flags,
TypefaceImpl* typeface) {
TypefaceImpl* resolvedFace = TypefaceImpl_resolveDefault(typeface);
layout->setFontCollection(resolvedFace->fFontCollection);
@@ -42,4 +43,18 @@ void MinikinUtils::SetLayoutProperties(Layout* layout, SkPaint* paint, int flags
layout->setProperties(css);
}
-} \ No newline at end of file
+float MinikinUtils::xOffsetForTextAlign(SkPaint* paint, const Layout& layout) {
+ switch (paint->getTextAlign()) {
+ case SkPaint::kCenter_Align:
+ return layout.getAdvance() * -0.5f;
+ break;
+ case SkPaint::kRight_Align:
+ return -layout.getAdvance();
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+}
diff --git a/core/jni/android/graphics/MinikinUtils.h b/core/jni/android/graphics/MinikinUtils.h
index 42f5e2f..997d6e3 100644
--- a/core/jni/android/graphics/MinikinUtils.h
+++ b/core/jni/android/graphics/MinikinUtils.h
@@ -28,8 +28,29 @@ namespace android {
class MinikinUtils {
public:
- static void SetLayoutProperties(Layout* layout, SkPaint* paint, int flags,
+ static void SetLayoutProperties(Layout* layout, const SkPaint* paint, int flags,
TypefaceImpl* face);
+ static float xOffsetForTextAlign(SkPaint* paint, const Layout& layout);
+
+ // f is a functor of type void f(SkTypeface *, size_t start, size_t end);
+ template <typename F>
+ static void forFontRun(const Layout& layout, F& f) {
+ SkTypeface* lastFace = NULL;
+ size_t start = 0;
+ size_t nGlyphs = layout.nGlyphs();
+ for (size_t i = 0; i < nGlyphs; i++) {
+ MinikinFontSkia* mfs = static_cast<MinikinFontSkia*>(layout.getFont(i));
+ SkTypeface* skFace = mfs->GetSkTypeface();
+ if (i > 0 && skFace != lastFace) {
+ f(lastFace, start, i);
+ start = i;
+ }
+ lastFace = skFace;
+ }
+ if (nGlyphs > start) {
+ f(lastFace, start, nGlyphs);
+ }
+ }
};
} // namespace android
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 8418162..4000b07 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -822,26 +822,83 @@ public:
return result;
}
- static void getTextPath(JNIEnv* env, SkPaint* paint, const jchar* text, jint count,
- jint bidiFlags, jfloat x, jfloat y, SkPath *path) {
+#ifdef USE_MINIKIN
+ class GetTextFunctor {
+ public:
+ GetTextFunctor(const Layout& layout, SkPath* path, jfloat x, jfloat y, SkPaint* paint,
+ uint16_t* glyphs, SkPoint* pos)
+ : layout(layout), path(path), x(x), y(y), paint(paint), glyphs(glyphs), pos(pos) {
+ }
+
+ void operator()(SkTypeface* t, size_t start, size_t end) {
+ for (size_t i = start; i < end; i++) {
+ glyphs[i] = layout.getGlyphId(i);
+ pos[i].fX = x + layout.getX(i);
+ pos[i].fY = y + layout.getY(i);
+ }
+ paint->setTypeface(t);
+ if (start == 0) {
+ paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, path);
+ } else {
+ paint->getPosTextPath(glyphs + start, (end - start) << 1, pos + start, &tmpPath);
+ path->addPath(tmpPath);
+ }
+ }
+ private:
+ const Layout& layout;
+ SkPath* path;
+ jfloat x;
+ jfloat y;
+ SkPaint* paint;
+ uint16_t* glyphs;
+ SkPoint* pos;
+ SkPath tmpPath;
+ };
+#endif
+
+ static void getTextPath(JNIEnv* env, SkPaint* paint, TypefaceImpl* typeface, const jchar* text,
+ jint count, jint bidiFlags, jfloat x, jfloat y, SkPath* path) {
+#ifdef USE_MINIKIN
+ Layout layout;
+ MinikinUtils::SetLayoutProperties(&layout, paint, bidiFlags, typeface);
+ layout.doLayout(text, count);
+ size_t nGlyphs = layout.nGlyphs();
+ uint16_t* glyphs = new uint16_t[nGlyphs];
+ SkPoint* pos = new SkPoint[nGlyphs];
+
+ x += MinikinUtils::xOffsetForTextAlign(paint, layout);
+ SkPaint::Align align = paint->getTextAlign();
+ paint->setTextAlign(SkPaint::kLeft_Align);
+ paint->setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ GetTextFunctor f(layout, path, x, y, paint, glyphs, pos);
+ MinikinUtils::forFontRun(layout, f);
+ paint->setTextAlign(align);
+ delete[] glyphs;
+ delete[] pos;
+#else
TextLayout::getTextPath(paint, text, count, bidiFlags, x, y, path);
+#endif
}
- static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
+ static void getTextPath___C(JNIEnv* env, jobject clazz, jlong paintHandle,
+ jlong typefaceHandle, jint bidiFlags,
jcharArray text, jint index, jint count, jfloat x, jfloat y, jlong pathHandle) {
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
const jchar* textArray = env->GetCharArrayElements(text, NULL);
- getTextPath(env, paint, textArray + index, count, bidiFlags, x, y, path);
+ getTextPath(env, paint, typeface, textArray + index, count, bidiFlags, x, y, path);
env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray), JNI_ABORT);
}
- static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle, jint bidiFlags,
+ static void getTextPath__String(JNIEnv* env, jobject clazz, jlong paintHandle,
+ jlong typefaceHandle, jint bidiFlags,
jstring text, jint start, jint end, jfloat x, jfloat y, jlong pathHandle) {
SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
SkPath* path = reinterpret_cast<SkPath*>(pathHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
- getTextPath(env, paint, textArray + start, end - start, bidiFlags, x, y, path);
+ getTextPath(env, paint, typeface, textArray + start, end - start, bidiFlags, x, y, path);
env->ReleaseStringChars(text, textArray);
}
@@ -928,34 +985,48 @@ public:
return count;
}
- static void doTextBounds(JNIEnv* env, const jchar* text, int count,
- jobject bounds, const SkPaint& paint, jint bidiFlags) {
+ static void doTextBounds(JNIEnv* env, const jchar* text, int count, jobject bounds,
+ const SkPaint& paint, TypefaceImpl* typeface, jint bidiFlags) {
SkRect r;
SkIRect ir;
+#ifdef USE_MINIKIN
+ Layout layout;
+ MinikinUtils::SetLayoutProperties(&layout, &paint, bidiFlags, typeface);
+ layout.doLayout(text, count);
+ MinikinRect rect;
+ layout.getBounds(&rect);
+ r.fLeft = rect.mLeft;
+ r.fTop = rect.mTop;
+ r.fRight = rect.mRight;
+ r.fBottom = rect.mBottom;
+#else
sp<TextLayoutValue> value = TextLayoutEngine::getInstance().getValue(&paint,
text, 0, count, count, bidiFlags);
if (value == NULL) {
return;
}
paint.measureText(value->getGlyphs(), value->getGlyphsCount() << 1, &r);
+#endif
r.roundOut(&ir);
GraphicsJNI::irect_to_jrect(ir, env, bounds);
}
- static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle,
+ static void getStringBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
jstring text, jint start, jint end, jint bidiFlags, jobject bounds) {
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);;
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetStringChars(text, NULL);
- doTextBounds(env, textArray + start, end - start, bounds, *paint, bidiFlags);
+ doTextBounds(env, textArray + start, end - start, bounds, *paint, typeface, bidiFlags);
env->ReleaseStringChars(text, textArray);
}
- static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle,
+ static void getCharArrayBounds(JNIEnv* env, jobject, jlong paintHandle, jlong typefaceHandle,
jcharArray text, jint index, jint count, jint bidiFlags, jobject bounds) {
const SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
+ TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefaceHandle);
const jchar* textArray = env->GetCharArrayElements(text, NULL);
- doTextBounds(env, textArray + index, count, bounds, *paint, bidiFlags);
+ doTextBounds(env, textArray + index, count, bounds, *paint, typeface, bidiFlags);
env->ReleaseCharArrayElements(text, const_cast<jchar*>(textArray),
JNI_ABORT);
}
@@ -1035,11 +1106,11 @@ static JNINativeMethod methods[] = {
{"native_getTextRunCursor", "(J[CIIIII)I", (void*) SkPaintGlue::getTextRunCursor___C},
{"native_getTextRunCursor", "(JLjava/lang/String;IIIII)I",
(void*) SkPaintGlue::getTextRunCursor__String},
- {"native_getTextPath","(JI[CIIFFJ)V", (void*) SkPaintGlue::getTextPath___C},
- {"native_getTextPath","(JILjava/lang/String;IIFFJ)V", (void*) SkPaintGlue::getTextPath__String},
- {"nativeGetStringBounds", "(JLjava/lang/String;IIILandroid/graphics/Rect;)V",
+ {"native_getTextPath","(JJI[CIIFFJ)V", (void*) SkPaintGlue::getTextPath___C},
+ {"native_getTextPath","(JJILjava/lang/String;IIFFJ)V", (void*) SkPaintGlue::getTextPath__String},
+ {"nativeGetStringBounds", "(JJLjava/lang/String;IIILandroid/graphics/Rect;)V",
(void*) SkPaintGlue::getStringBounds },
- {"nativeGetCharArrayBounds", "(J[CIIILandroid/graphics/Rect;)V",
+ {"nativeGetCharArrayBounds", "(JJ[CIIILandroid/graphics/Rect;)V",
(void*) SkPaintGlue::getCharArrayBounds },
{"native_setShadowLayer", "(JFFFI)V", (void*)SkPaintGlue::setShadowLayer},
{"native_hasShadowLayer", "(J)Z", (void*)SkPaintGlue::hasShadowLayer}
diff --git a/core/jni/android/graphics/TextLayoutCache.cpp b/core/jni/android/graphics/TextLayoutCache.cpp
index 9279758..495d08a 100644
--- a/core/jni/android/graphics/TextLayoutCache.cpp
+++ b/core/jni/android/graphics/TextLayoutCache.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "TextLayoutCache"
#include <utils/JenkinsHash.h>
+#include <utils/CallStack.h>
#include "TextLayoutCache.h"
#include "TextLayout.h"
@@ -89,6 +90,11 @@ void TextLayoutCache::purgeCaches() {
sp<TextLayoutValue> TextLayoutCache::getValue(const SkPaint* paint,
const jchar* text, jint start, jint count, jint contextCount, jint dirFlags) {
AutoMutex _l(mLock);
+#ifdef USE_MINIKIN
+ // We want to get rid of all legacy calls in the Minikin case, so log
+ ALOGW("TextLayoutCache being invoked!");
+ CallStack _cs(LOG_TAG);
+#endif
nsecs_t startTime = 0;
if (mDebugEnabled) {
startTime = systemTime(SYSTEM_TIME_MONOTONIC);
diff --git a/core/jni/android/graphics/TypefaceImpl.cpp b/core/jni/android/graphics/TypefaceImpl.cpp
index 958cd85..786d19c 100644
--- a/core/jni/android/graphics/TypefaceImpl.cpp
+++ b/core/jni/android/graphics/TypefaceImpl.cpp
@@ -134,18 +134,19 @@ static TypefaceImpl* createFromSkTypeface(SkTypeface* typeface) {
return result;
}
+// Delete when removing USE_MINIKIN ifdef
TypefaceImpl* TypefaceImpl_createFromName(const char* name, SkTypeface::Style style) {
- // TODO: should create a font collection with all styles corresponding to
- // the name
SkTypeface* face = SkTypeface::CreateFromName(name, style);
return createFromSkTypeface(face);
}
+// Delete when removing USE_MINIKIN ifdef
TypefaceImpl* TypefaceImpl_createFromFile(const char* filename) {
SkTypeface* face = SkTypeface::CreateFromFile(filename);
return createFromSkTypeface(face);
}
+// Delete when removing USE_MINIKIN ifdef
TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
SkStream* stream = new AssetStreamAdaptor(asset,
AssetStreamAdaptor::kYes_OwnAsset,
@@ -158,7 +159,6 @@ TypefaceImpl* TypefaceImpl_createFromAsset(Asset* asset) {
}
TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size) {
- ALOGD("createFromFamilies size=%d", size);
std::vector<FontFamily *>familyVec;
for (size_t i = 0; i < size; i++) {
FontFamily* family = reinterpret_cast<FontFamily*>(families[i]);
@@ -166,12 +166,25 @@ TypefaceImpl* TypefaceImpl_createFromFamilies(const jlong* families, size_t size
}
TypefaceImpl* result = new TypefaceImpl;
result->fFontCollection = new FontCollection(familyVec);
- result->fStyle = FontStyle(); // TODO: improve
+ if (size == 0) {
+ ALOGW("createFromFamilies creating empty collection");
+ result->fStyle = FontStyle();
+ } else {
+ const FontStyle defaultStyle;
+ FontFamily* firstFamily = reinterpret_cast<FontFamily*>(families[0]);
+ MinikinFont* mf = firstFamily->getClosestMatch(defaultStyle);
+ SkTypeface* skTypeface = reinterpret_cast<MinikinFontSkia*>(mf)->GetSkTypeface();
+ // TODO: probably better to query more precise style from family, will be important
+ // when we open up API to access 100..900 weights
+ result->fStyle = styleFromSkiaStyle(skTypeface->style());
+ }
return result;
}
void TypefaceImpl_unref(TypefaceImpl* face) {
- face->fFontCollection->Unref();
+ if (face != NULL) {
+ face->fFontCollection->Unref();
+ }
delete face;
}
diff --git a/core/jni/android_hardware_camera2_DngCreator.cpp b/core/jni/android_hardware_camera2_DngCreator.cpp
index 7b686e7..33100bf 100644
--- a/core/jni/android_hardware_camera2_DngCreator.cpp
+++ b/core/jni/android_hardware_camera2_DngCreator.cpp
@@ -31,6 +31,8 @@
#include <utils/RefBase.h>
#include <cutils/properties.h>
+#include <string.h>
+
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_hardware_camera2_CameraMetadata.h"
@@ -175,7 +177,7 @@ static void DngCreator_nativeClassInit(JNIEnv* env, jclass clazz) {
}
static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPtr,
- jobject resultsPtr) {
+ jobject resultsPtr, jstring formattedCaptureTime) {
ALOGV("%s:", __FUNCTION__);
CameraMetadata characteristics;
CameraMetadata results;
@@ -205,7 +207,6 @@ static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPt
OpcodeListBuilder::CfaLayout opcodeCfaLayout = OpcodeListBuilder::CFA_RGGB;
// TODO: Greensplit.
- // TODO: UniqueCameraModel
// TODO: Add remaining non-essential tags
{
// Set orientation
@@ -352,6 +353,176 @@ static void DngCreator_init(JNIEnv* env, jobject thiz, jobject characteristicsPt
}
{
+ // image description
+ uint8_t imageDescription = '\0'; // empty
+ BAIL_IF_INVALID(writer->addEntry(TAG_IMAGEDESCRIPTION, 1, &imageDescription, TIFF_IFD_0),
+ env, TAG_IMAGEDESCRIPTION);
+ }
+
+ {
+ // make
+ char manufacturer[PROPERTY_VALUE_MAX];
+
+ // Use "" to represent unknown make as suggested in TIFF/EP spec.
+ property_get("ro.product.manufacturer", manufacturer, "");
+ uint32_t count = static_cast<uint32_t>(strlen(manufacturer)) + 1;
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_MAKE, count, reinterpret_cast<uint8_t*>(manufacturer),
+ TIFF_IFD_0), env, TAG_MAKE);
+ }
+
+ {
+ // model
+ char model[PROPERTY_VALUE_MAX];
+
+ // Use "" to represent unknown model as suggested in TIFF/EP spec.
+ property_get("ro.product.model", model, "");
+ uint32_t count = static_cast<uint32_t>(strlen(model)) + 1;
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_MODEL, count, reinterpret_cast<uint8_t*>(model),
+ TIFF_IFD_0), env, TAG_MODEL);
+ }
+
+ {
+ // x resolution
+ uint32_t xres[] = { 72, 1 }; // default 72 ppi
+ BAIL_IF_INVALID(writer->addEntry(TAG_XRESOLUTION, 1, xres, TIFF_IFD_0),
+ env, TAG_XRESOLUTION);
+
+ // y resolution
+ uint32_t yres[] = { 72, 1 }; // default 72 ppi
+ BAIL_IF_INVALID(writer->addEntry(TAG_YRESOLUTION, 1, yres, TIFF_IFD_0),
+ env, TAG_YRESOLUTION);
+
+ uint16_t unit = 2; // inches
+ BAIL_IF_INVALID(writer->addEntry(TAG_RESOLUTIONUNIT, 1, &unit, TIFF_IFD_0),
+ env, TAG_RESOLUTIONUNIT);
+ }
+
+ {
+ // software
+ char software[PROPERTY_VALUE_MAX];
+ property_get("ro.build.fingerprint", software, "");
+ uint32_t count = static_cast<uint32_t>(strlen(software)) + 1;
+ BAIL_IF_INVALID(writer->addEntry(TAG_SOFTWARE, count, reinterpret_cast<uint8_t*>(software),
+ TIFF_IFD_0), env, TAG_SOFTWARE);
+ }
+
+ {
+ // datetime
+ const size_t DATETIME_COUNT = 20;
+ const char* captureTime = env->GetStringUTFChars(formattedCaptureTime, NULL);
+
+ size_t len = strlen(captureTime) + 1;
+ if (len != DATETIME_COUNT) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Timestamp string length is not required 20 characters");
+ return;
+ }
+
+ BAIL_IF_INVALID(writer->addEntry(TAG_DATETIME, DATETIME_COUNT,
+ reinterpret_cast<const uint8_t*>(captureTime), TIFF_IFD_0), env, TAG_DATETIMEORIGINAL);
+
+ // datetime original
+ BAIL_IF_INVALID(writer->addEntry(TAG_DATETIMEORIGINAL, DATETIME_COUNT,
+ reinterpret_cast<const uint8_t*>(captureTime), TIFF_IFD_0), env, TAG_DATETIMEORIGINAL);
+ env->ReleaseStringUTFChars(formattedCaptureTime, captureTime);
+ }
+
+ {
+ // TIFF/EP standard id
+ uint8_t standardId[] = { 1, 0, 0, 0 };
+ BAIL_IF_INVALID(writer->addEntry(TAG_TIFFEPSTANDARDID, 4, standardId,
+ TIFF_IFD_0), env, TAG_TIFFEPSTANDARDID);
+ }
+
+ {
+ // copyright
+ uint8_t copyright = '\0'; // empty
+ BAIL_IF_INVALID(writer->addEntry(TAG_COPYRIGHT, 1, &copyright,
+ TIFF_IFD_0), env, TAG_COPYRIGHT);
+ }
+
+ {
+ // exposure time
+ camera_metadata_entry entry =
+ results.find(ANDROID_SENSOR_EXPOSURE_TIME);
+ BAIL_IF_EMPTY(entry, env, TAG_EXPOSURETIME);
+
+ int64_t exposureTime = *(entry.data.i64);
+
+ if (exposureTime < 0) {
+ // Should be unreachable
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Negative exposure time in metadata");
+ return;
+ }
+
+ // Ensure exposure time doesn't overflow (for exposures > 4s)
+ uint32_t denominator = 1000000000;
+ while (exposureTime > UINT32_MAX) {
+ exposureTime >>= 1;
+ denominator >>= 1;
+ if (denominator == 0) {
+ // Should be unreachable
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Exposure time too long");
+ return;
+ }
+ }
+
+ uint32_t exposure[] = { static_cast<uint32_t>(exposureTime), denominator };
+ BAIL_IF_INVALID(writer->addEntry(TAG_EXPOSURETIME, 1, exposure,
+ TIFF_IFD_0), env, TAG_EXPOSURETIME);
+
+ }
+
+ {
+ // ISO speed ratings
+ camera_metadata_entry entry =
+ results.find(ANDROID_SENSOR_SENSITIVITY);
+ BAIL_IF_EMPTY(entry, env, TAG_ISOSPEEDRATINGS);
+
+ int32_t tempIso = *(entry.data.i32);
+ if (tempIso < 0) {
+ jniThrowException(env, "java/lang/IllegalArgumentException",
+ "Negative ISO value");
+ return;
+ }
+
+ if (tempIso > UINT16_MAX) {
+ ALOGW("%s: ISO value overflows UINT16_MAX, clamping to max", __FUNCTION__);
+ tempIso = UINT16_MAX;
+ }
+
+ uint16_t iso = static_cast<uint16_t>(tempIso);
+ BAIL_IF_INVALID(writer->addEntry(TAG_ISOSPEEDRATINGS, 1, &iso,
+ TIFF_IFD_0), env, TAG_ISOSPEEDRATINGS);
+ }
+
+ {
+ // focal length
+ camera_metadata_entry entry =
+ results.find(ANDROID_LENS_FOCAL_LENGTH);
+ BAIL_IF_EMPTY(entry, env, TAG_FOCALLENGTH);
+
+ uint32_t focalLength[] = { static_cast<uint32_t>(*(entry.data.f) * 100), 100 };
+ BAIL_IF_INVALID(writer->addEntry(TAG_FOCALLENGTH, 1, focalLength,
+ TIFF_IFD_0), env, TAG_FOCALLENGTH);
+ }
+
+ {
+ // f number
+ camera_metadata_entry entry =
+ results.find(ANDROID_LENS_APERTURE);
+ BAIL_IF_EMPTY(entry, env, TAG_FNUMBER);
+
+ uint32_t fnum[] = { static_cast<uint32_t>(*(entry.data.f) * 100), 100 };
+ BAIL_IF_INVALID(writer->addEntry(TAG_FNUMBER, 1, fnum,
+ TIFF_IFD_0), env, TAG_FNUMBER);
+ }
+
+ {
// Set DNG version information
uint8_t version[4] = {1, 4, 0, 0};
BAIL_IF_INVALID(writer->addEntry(TAG_DNGVERSION, 4, version, TIFF_IFD_0),
@@ -751,7 +922,8 @@ static void DngCreator_nativeWriteInputStream(JNIEnv* env, jobject thiz, jobject
static JNINativeMethod gDngCreatorMethods[] = {
{"nativeClassInit", "()V", (void*) DngCreator_nativeClassInit},
{"nativeInit", "(Landroid/hardware/camera2/impl/CameraMetadataNative;"
- "Landroid/hardware/camera2/impl/CameraMetadataNative;)V", (void*) DngCreator_init},
+ "Landroid/hardware/camera2/impl/CameraMetadataNative;Ljava/lang/String;)V",
+ (void*) DngCreator_init},
{"nativeDestroy", "()V", (void*) DngCreator_destroy},
{"nativeSetOrientation", "(I)V", (void*) DngCreator_nativeSetOrientation},
{"nativeSetThumbnailBitmap","(Landroid/graphics/Bitmap;)V",
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 0f7e140..bf47dd3 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -613,8 +613,12 @@ static jint convertAudioPortConfigFromNative(JNIEnv *env,
goto exit;
}
}
- //TODO: replace popcount by audio utils function mask to count
- int numValues = popcount(nAudioPortConfig->gain.channel_mask);
+ int numValues;
+ if (useInMask) {
+ numValues = audio_channel_count_from_in_mask(nAudioPortConfig->gain.channel_mask);
+ } else {
+ numValues = audio_channel_count_from_out_mask(nAudioPortConfig->gain.channel_mask);
+ }
jGainValues = env->NewIntArray(numValues);
if (jGainValues == NULL) {
ALOGV("convertAudioPortConfigFromNative could not create gain values %d", numValues);
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 9141d44..6b35be1 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -91,53 +91,9 @@ static struct {
} gRectClassInfo;
// ----------------------------------------------------------------------------
-// Caching
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_flushCaches(JNIEnv* env, jobject clazz,
- jint mode) {
- if (Caches::hasInstance()) {
- Caches::getInstance().flush(static_cast<Caches::FlushMode>(mode));
- }
-}
-
-static jboolean android_view_GLES20Canvas_initCaches(JNIEnv* env, jobject clazz) {
- if (Caches::hasInstance()) {
- return Caches::getInstance().init() ? JNI_TRUE : JNI_FALSE;
- }
- return JNI_FALSE;
-}
-
-static void android_view_GLES20Canvas_terminateCaches(JNIEnv* env, jobject clazz) {
- if (Caches::hasInstance()) {
- Caches::getInstance().terminate();
- }
-}
-
-// ----------------------------------------------------------------------------
-// Caching
-// ----------------------------------------------------------------------------
-
-static void android_view_GLES20Canvas_initAtlas(JNIEnv* env, jobject clazz,
- jobject graphicBuffer, jlongArray atlasMapArray, jint count) {
-
- sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer);
- jlong* jAtlasMap = env->GetLongArrayElements(atlasMapArray, NULL);
- Caches::getInstance().assetAtlas.init(buffer, jAtlasMap, count);
- env->ReleaseLongArrayElements(atlasMapArray, jAtlasMap, 0);
-}
-
-// ----------------------------------------------------------------------------
// Constructors
// ----------------------------------------------------------------------------
-static jlong android_view_GLES20Canvas_createRenderer(JNIEnv* env, jobject clazz) {
- RENDERER_LOGD("Create OpenGLRenderer");
- OpenGLRenderer* renderer = new OpenGLRenderer();
- renderer->initProperties();
- return reinterpret_cast<jlong>(renderer);
-}
-
static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz,
jlong rendererPtr) {
OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
@@ -174,10 +130,6 @@ static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
renderer->finish();
}
-static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
- return Stencil::getStencilSize();
-}
-
static void android_view_GLES20Canvas_setProperty(JNIEnv* env,
jobject clazz, jstring name, jstring value) {
if (!Caches::hasInstance()) {
@@ -577,15 +529,6 @@ static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject cla
}
}
-static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jfloatArray rects, jint count, jlong paintPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- jfloat* storage = env->GetFloatArrayElements(rects, NULL);
- SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
- renderer->drawRects(storage, count, paint);
- env->ReleaseFloatArrayElements(rects, storage, 0);
-}
-
static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz,
jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) {
OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
@@ -632,6 +575,7 @@ static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject claz
// Text
// ----------------------------------------------------------------------------
+// TODO: this is moving to MinikinUtils, remove with USE_MINIKIN ifdef
static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
switch (paint->getTextAlign()) {
case SkPaint::kCenter_Align:
@@ -647,43 +591,51 @@ static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) {
}
#ifdef USE_MINIKIN
+
+class RenderTextFunctor {
+public:
+ RenderTextFunctor(const Layout& layout, OpenGLRenderer* renderer, jfloat x, jfloat y,
+ SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance,
+ uirenderer::Rect& bounds)
+ : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs),
+ pos(pos), totalAdvance(totalAdvance), bounds(bounds) { }
+ void operator()(SkTypeface* t, size_t start, size_t end) {
+ for (size_t i = start; i < end; i++) {
+ glyphs[i] = layout.getGlyphId(i);
+ pos[2 * i] = layout.getX(i);
+ pos[2 * i + 1] = layout.getY(i);
+ }
+ paint->setTypeface(t);
+ size_t glyphsCount = end - start;
+ int bytesCount = glyphsCount * sizeof(jchar);
+ renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
+ x, y, pos + 2 * start, paint, totalAdvance, bounds);
+ }
+private:
+ const Layout& layout;
+ OpenGLRenderer* renderer;
+ jfloat x;
+ jfloat y;
+ SkPaint* paint;
+ uint16_t* glyphs;
+ float* pos;
+ float totalAdvance;
+ uirenderer::Rect& bounds;
+};
+
static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout,
jfloat x, jfloat y, SkPaint* paint) {
size_t nGlyphs = layout->nGlyphs();
float* pos = new float[nGlyphs * 2];
uint16_t* glyphs = new uint16_t[nGlyphs];
- SkTypeface* lastFace = 0;
- SkTypeface* skFace = 0;
- size_t start = 0;
MinikinRect b;
layout->getBounds(&b);
android::uirenderer::Rect bounds(b.mLeft, b.mTop, b.mRight, b.mBottom);
bounds.translate(x, y);
float totalAdvance = layout->getAdvance();
- for (size_t i = 0; i < nGlyphs; i++) {
- MinikinFontSkia* mfs = static_cast<MinikinFontSkia *>(layout->getFont(i));
- skFace = mfs->GetSkTypeface();
- glyphs[i] = layout->getGlyphId(i);
- pos[2 * i] = layout->getX(i);
- pos[2 * i + 1] = layout->getY(i);
- if (i > 0 && skFace != lastFace) {
- paint->setTypeface(lastFace);
- size_t glyphsCount = i - start;
- int bytesCount = glyphsCount * sizeof(jchar);
- renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
- x, y, pos + 2 * start, paint, totalAdvance, bounds);
- start = i;
- }
- lastFace = skFace;
- }
- if (skFace != NULL) {
- paint->setTypeface(skFace);
- size_t glyphsCount = nGlyphs - start;
- int bytesCount = glyphsCount * sizeof(jchar);
- renderer->drawText((const char*) (glyphs + start), bytesCount, glyphsCount,
- x, y, pos + 2 * start, paint, totalAdvance, bounds);
- }
+ RenderTextFunctor f(*layout, renderer, x, y, paint, glyphs, pos, totalAdvance, bounds);
+ MinikinUtils::forFontRun(*layout, f);
delete[] glyphs;
delete[] pos;
}
@@ -924,39 +876,6 @@ static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
renderer->drawLayer(layer, x, y);
}
-static jboolean android_view_GLES20Canvas_copyLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr, jlong bitmapPtr) {
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr);
- return LayerRenderer::copyLayer(layer, bitmap);
-}
-
-static void android_view_GLES20Canvas_pushLayerUpdate(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong layerPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- renderer->pushLayerUpdate(layer);
-}
-
-static void android_view_GLES20Canvas_cancelLayerUpdate(JNIEnv* env, jobject clazz,
- jlong rendererPtr, jlong layerPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- renderer->cancelLayerUpdate(layer);
-}
-
-static void android_view_GLES20Canvas_clearLayerUpdates(JNIEnv* env, jobject clazz,
- jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- renderer->clearLayerUpdates();
-}
-
-static void android_view_GLES20Canvas_flushLayerUpdates(JNIEnv* env, jobject clazz,
- jlong rendererPtr) {
- OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
- renderer->flushLayerUpdates();
-}
-
#endif // USE_OPENGL_RENDERER
// ----------------------------------------------------------------------------
@@ -1001,14 +920,7 @@ static JNINativeMethod gMethods[] = {
{ "nIsAvailable", "()Z", (void*) android_view_GLES20Canvas_isAvailable },
#ifdef USE_OPENGL_RENDERER
- { "nFlushCaches", "(I)V", (void*) android_view_GLES20Canvas_flushCaches },
- { "nInitCaches", "()Z", (void*) android_view_GLES20Canvas_initCaches },
- { "nTerminateCaches", "()V", (void*) android_view_GLES20Canvas_terminateCaches },
-
- { "nInitAtlas", "(Landroid/view/GraphicBuffer;[JI)V",
- (void*) android_view_GLES20Canvas_initAtlas },
- { "nCreateRenderer", "()J", (void*) android_view_GLES20Canvas_createRenderer },
{ "nDestroyRenderer", "(J)V", (void*) android_view_GLES20Canvas_destroyRenderer },
{ "nSetViewport", "(JII)V", (void*) android_view_GLES20Canvas_setViewport },
{ "nPrepare", "(JZ)I", (void*) android_view_GLES20Canvas_prepare },
@@ -1017,9 +929,6 @@ static JNINativeMethod gMethods[] = {
{ "nSetProperty", "(Ljava/lang/String;Ljava/lang/String;)V",
(void*) android_view_GLES20Canvas_setProperty },
-
- { "nGetStencilSize", "()I", (void*) android_view_GLES20Canvas_getStencilSize },
-
{ "nCallDrawGLFunction", "(JJ)I", (void*) android_view_GLES20Canvas_callDrawGLFunction },
{ "nSave", "(JI)I", (void*) android_view_GLES20Canvas_save },
@@ -1059,7 +968,6 @@ static JNINativeMethod gMethods[] = {
{ "nDrawColor", "(JII)V", (void*) android_view_GLES20Canvas_drawColor },
{ "nDrawRect", "(JFFFFJ)V", (void*) android_view_GLES20Canvas_drawRect },
{ "nDrawRects", "(JJJ)V", (void*) android_view_GLES20Canvas_drawRegionAsRects },
- { "nDrawRects", "(J[FIJ)V", (void*) android_view_GLES20Canvas_drawRects },
{ "nDrawRoundRect", "(JFFFFFFJ)V", (void*) android_view_GLES20Canvas_drawRoundRect },
{ "nDrawCircle", "(JFFFJ)V", (void*) android_view_GLES20Canvas_drawCircle },
{ "nDrawCircle", "(JJJJJ)V", (void*) android_view_GLES20Canvas_drawCircleProps },
@@ -1099,11 +1007,6 @@ static JNINativeMethod gMethods[] = {
{ "nCreateDisplayListRenderer", "()J", (void*) android_view_GLES20Canvas_createDisplayListRenderer },
{ "nDrawLayer", "(JJFF)V", (void*) android_view_GLES20Canvas_drawLayer },
- { "nCopyLayer", "(JJ)Z", (void*) android_view_GLES20Canvas_copyLayer },
- { "nClearLayerUpdates", "(J)V", (void*) android_view_GLES20Canvas_clearLayerUpdates },
- { "nFlushLayerUpdates", "(J)V", (void*) android_view_GLES20Canvas_flushLayerUpdates },
- { "nPushLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_pushLayerUpdate },
- { "nCancelLayerUpdate", "(JJ)V", (void*) android_view_GLES20Canvas_cancelLayerUpdate },
{ "nGetMaximumTextureWidth", "()I", (void*) android_view_GLES20Canvas_getMaxTextureWidth },
{ "nGetMaximumTextureHeight", "()I", (void*) android_view_GLES20Canvas_getMaxTextureHeight },
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
deleted file mode 100644
index d0269a3..0000000
--- a/core/jni/android_view_GLRenderer.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "GLRenderer"
-
-#include "jni.h"
-#include <nativehelper/JNIHelp.h>
-#include <android_runtime/AndroidRuntime.h>
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <EGL/egl_cache.h>
-
-#include <utils/Timers.h>
-
-#include <private/hwui/DrawGlInfo.h>
-
-#include <Caches.h>
-#include <Extensions.h>
-#include <LayerRenderer.h>
-#include <RenderNode.h>
-
-#ifdef USE_OPENGL_RENDERER
- EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface);
-#endif
-
-namespace android {
-
-/**
- * Note: OpenGLRenderer JNI layer is generated and compiled only on supported
- * devices. This means all the logic must be compiled only when the
- * preprocessor variable USE_OPENGL_RENDERER is defined.
- */
-#ifdef USE_OPENGL_RENDERER
-
-// ----------------------------------------------------------------------------
-// Defines
-// ----------------------------------------------------------------------------
-
-// Debug
-#define DEBUG_RENDERER 0
-
-// Debug
-#if DEBUG_RENDERER
- #define RENDERER_LOGD(...) ALOGD(__VA_ARGS__)
-#else
- #define RENDERER_LOGD(...)
-#endif
-
-// ----------------------------------------------------------------------------
-// Surface and display management
-// ----------------------------------------------------------------------------
-
-static jboolean android_view_GLRenderer_preserveBackBuffer(JNIEnv* env, jobject clazz) {
- EGLDisplay display = eglGetCurrentDisplay();
- EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
-
- eglGetError();
- eglSurfaceAttrib(display, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
-
- EGLint error = eglGetError();
- if (error != EGL_SUCCESS) {
- RENDERER_LOGD("Could not enable buffer preserved swap behavior (%x)", error);
- }
-
- return error == EGL_SUCCESS;
-}
-
-static jboolean android_view_GLRenderer_isBackBufferPreserved(JNIEnv* env, jobject clazz) {
- EGLDisplay display = eglGetCurrentDisplay();
- EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
- EGLint value;
-
- eglGetError();
- eglQuerySurface(display, surface, EGL_SWAP_BEHAVIOR, &value);
-
- EGLint error = eglGetError();
- if (error != EGL_SUCCESS) {
- RENDERER_LOGD("Could not query buffer preserved swap behavior (%x)", error);
- }
-
- return error == EGL_SUCCESS && value == EGL_BUFFER_PRESERVED;
-}
-
-// ----------------------------------------------------------------------------
-// Tracing and debugging
-// ----------------------------------------------------------------------------
-
-static bool android_view_GLRenderer_loadProperties(JNIEnv* env, jobject clazz) {
- if (uirenderer::Caches::hasInstance()) {
- return uirenderer::Caches::getInstance().initProperties();
- }
- return false;
-}
-
-static void android_view_GLRenderer_beginFrame(JNIEnv* env, jobject clazz,
- jintArray size) {
-
- EGLDisplay display = eglGetCurrentDisplay();
- EGLSurface surface = eglGetCurrentSurface(EGL_DRAW);
-
- if (size) {
- EGLint value;
- jint* storage = env->GetIntArrayElements(size, NULL);
-
- eglQuerySurface(display, surface, EGL_WIDTH, &value);
- storage[0] = value;
-
- eglQuerySurface(display, surface, EGL_HEIGHT, &value);
- storage[1] = value;
-
- env->ReleaseIntArrayElements(size, storage, 0);
- }
-
- eglBeginFrame(display, surface);
-}
-
-static jlong android_view_GLRenderer_getSystemTime(JNIEnv* env, jobject clazz) {
- if (uirenderer::Extensions::getInstance().hasNvSystemTime()) {
- return eglGetSystemTimeNV();
- }
- return systemTime(SYSTEM_TIME_MONOTONIC);
-}
-
-static void android_view_GLRenderer_destroyLayer(JNIEnv* env, jobject clazz,
- jlong layerPtr) {
- using namespace android::uirenderer;
- Layer* layer = reinterpret_cast<Layer*>(layerPtr);
- LayerRenderer::destroyLayer(layer);
-}
-
-static void android_view_GLRenderer_prepareTree(JNIEnv* env, jobject clazz,
- jlong renderNodePtr) {
- using namespace android::uirenderer;
- RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
- TreeInfo ignoredInfo;
- renderNode->prepareTree(ignoredInfo);
-}
-
-static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
- jlong functorPtr, jboolean hasContext) {
- using namespace android::uirenderer;
- Functor* functor = reinterpret_cast<Functor*>(functorPtr);
- DrawGlInfo::Mode mode = hasContext ? DrawGlInfo::kModeProcess : DrawGlInfo::kModeProcessNoContext;
- (*functor)(mode, NULL);
-}
-
-#endif // USE_OPENGL_RENDERER
-
-// ----------------------------------------------------------------------------
-// Shaders
-// ----------------------------------------------------------------------------
-
-static void android_view_GLRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
- jstring diskCachePath) {
-
- const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
- egl_cache_t::get()->setCacheFilename(cacheArray);
- env->ReleaseStringUTFChars(diskCachePath, cacheArray);
-}
-
-// ----------------------------------------------------------------------------
-// JNI Glue
-// ----------------------------------------------------------------------------
-
-const char* const kClassPathName = "android/view/GLRenderer";
-
-static JNINativeMethod gMethods[] = {
-#ifdef USE_OPENGL_RENDERER
- { "isBackBufferPreserved", "()Z", (void*) android_view_GLRenderer_isBackBufferPreserved },
- { "preserveBackBuffer", "()Z", (void*) android_view_GLRenderer_preserveBackBuffer },
- { "loadProperties", "()Z", (void*) android_view_GLRenderer_loadProperties },
-
- { "beginFrame", "([I)V", (void*) android_view_GLRenderer_beginFrame },
-
- { "getSystemTime", "()J", (void*) android_view_GLRenderer_getSystemTime },
- { "nDestroyLayer", "(J)V", (void*) android_view_GLRenderer_destroyLayer },
- { "nPrepareTree", "(J)V", (void*) android_view_GLRenderer_prepareTree },
- { "nInvokeFunctor", "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor },
-#endif
-
- { "setupShadersDiskCache", "(Ljava/lang/String;)V",
- (void*) android_view_GLRenderer_setupShadersDiskCache },
-};
-
-int register_android_view_GLRenderer(JNIEnv* env) {
- return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
-}
-
-};
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 33a2705..879836d 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -43,21 +43,6 @@ using namespace uirenderer;
#ifdef USE_OPENGL_RENDERER
-static jlong android_view_HardwareLayer_createTextureLayer(JNIEnv* env, jobject clazz) {
- Layer* layer = LayerRenderer::createTextureLayer();
- if (!layer) return 0;
-
- return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
-}
-
-static jlong android_view_HardwareLayer_createRenderLayer(JNIEnv* env, jobject clazz,
- jint width, jint height) {
- Layer* layer = LayerRenderer::createRenderLayer(width, height);
- if (!layer) return 0;
-
- return reinterpret_cast<jlong>( new DeferredLayerUpdater(layer) );
-}
-
static void android_view_HardwareLayer_onTextureDestroyed(JNIEnv* env, jobject clazz,
jlong layerUpdaterPtr) {
DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
@@ -140,8 +125,6 @@ const char* const kClassPathName = "android/view/HardwareLayer";
static JNINativeMethod gMethods[] = {
#ifdef USE_OPENGL_RENDERER
- { "nCreateTextureLayer", "()J", (void*) android_view_HardwareLayer_createTextureLayer },
- { "nCreateRenderLayer", "(II)J", (void*) android_view_HardwareLayer_createRenderLayer },
{ "nOnTextureDestroyed", "(J)V", (void*) android_view_HardwareLayer_onTextureDestroyed },
{ "nPrepare", "(JIIZ)Z", (void*) android_view_HardwareLayer_prepare },
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 1397131..a550649 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -22,6 +22,10 @@
#include <nativehelper/JNIHelp.h>
#include <android_runtime/AndroidRuntime.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <EGL/egl_cache.h>
+
#include <utils/StrongPointer.h>
#include <android_runtime/android_view_Surface.h>
#include <system/window.h>
@@ -329,6 +333,18 @@ static void android_view_ThreadedRenderer_dumpProfileInfo(JNIEnv* env, jobject c
#endif
// ----------------------------------------------------------------------------
+// Shaders
+// ----------------------------------------------------------------------------
+
+static void android_view_ThreadedRenderer_setupShadersDiskCache(JNIEnv* env, jobject clazz,
+ jstring diskCachePath) {
+
+ const char* cacheArray = env->GetStringUTFChars(diskCachePath, NULL);
+ egl_cache_t::get()->setCacheFilename(cacheArray);
+ env->ReleaseStringUTFChars(diskCachePath, cacheArray);
+}
+
+// ----------------------------------------------------------------------------
// JNI Glue
// ----------------------------------------------------------------------------
@@ -361,6 +377,8 @@ static JNINativeMethod gMethods[] = {
{ "nNotifyFramePending", "(J)V", (void*) android_view_ThreadedRenderer_notifyFramePending },
{ "nDumpProfileInfo", "(JLjava/io/FileDescriptor;)V", (void*) android_view_ThreadedRenderer_dumpProfileInfo },
#endif
+ { "setupShadersDiskCache", "(Ljava/lang/String;)V",
+ (void*) android_view_ThreadedRenderer_setupShadersDiskCache },
};
int register_android_view_ThreadedRenderer(JNIEnv* env) {
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index 230658f..e55e4ea 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -46,6 +46,9 @@
#define LIB_SUFFIX ".so"
#define LIB_SUFFIX_LEN (sizeof(LIB_SUFFIX) - 1)
+#define RS_BITCODE_SUFFIX ".bc"
+#define RS_BITCODE_SUFFIX_LEN (sizeof(RS_BITCODE_SUFFIX) -1)
+
#define GDBSERVER "gdbserver"
#define GDBSERVER_LEN (sizeof(GDBSERVER) - 1)
@@ -486,6 +489,42 @@ com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, j
return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch);
}
+enum bitcode_scan_result_t {
+ APK_SCAN_ERROR = -1,
+ NO_BITCODE_PRESENT = 0,
+ BITCODE_PRESENT = 1,
+};
+
+static jint
+com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode(JNIEnv *env, jclass clazz,
+ jlong apkHandle) {
+ ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+ void* cookie = NULL;
+ if (!zipFile->startIteration(&cookie)) {
+ return APK_SCAN_ERROR;
+ }
+
+ char fileName[PATH_MAX];
+ ZipEntryRO next = NULL;
+ while ((next = zipFile->nextEntry(cookie)) != NULL) {
+ if (zipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
+ continue;
+ }
+
+ const size_t fileNameLen = strlen(fileName);
+ const char* lastSlash = strrchr(fileName, '/');
+ const char* baseName = (lastSlash == NULL) ? fileName : fileName + 1;
+ if (!strncmp(fileName + fileNameLen - RS_BITCODE_SUFFIX_LEN, RS_BITCODE_SUFFIX,
+ RS_BITCODE_SUFFIX_LEN) && isFilenameSafe(baseName)) {
+ zipFile->endIteration(cookie);
+ return BITCODE_PRESENT;
+ }
+ }
+
+ zipFile->endIteration(cookie);
+ return NO_BITCODE_PRESENT;
+}
+
static jlong
com_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath)
{
@@ -517,6 +556,8 @@ static JNINativeMethod gMethods[] = {
{"nativeFindSupportedAbi",
"(J[Ljava/lang/String;)I",
(void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
+ {"hasRenderscriptBitcode", "(J)I",
+ (void *)com_android_internal_content_NativeLibraryHelper_hasRenderscriptBitcode},
};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index bb6a1cb..dfe2a58 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -2076,7 +2076,7 @@
android:description="@string/permdesc_bindRemoteDisplay"
android:protectionLevel="signature" />
- <!-- Must be required by a {@link android.tv.TvInputService}
+ <!-- Must be required by a {@link android.media.tv.TvInputService}
to ensure that only the system can bind to it. -->
<permission android:name="android.permission.BIND_TV_INPUT"
android:label="@string/permlab_bindTvInput"
@@ -2239,6 +2239,14 @@
android:description="@string/permdesc_captureAudioHotword"
android:protectionLevel="signature|system" />
+ <!-- Allows an application to modify audio routing and override policy decisions.
+ <p>Not for use by third-party applications.</p>
+ @hide -->
+ <permission android:name="android.permission.MODIFY_AUDIO_ROUTING"
+ android:label="@string/permlab_modifyAudioRouting"
+ android:description="@string/permdesc_modifyAudioRouting"
+ android:protectionLevel="signature|system" />
+
<!-- Allows an application to capture video output.
<p>Not for use by third-party applications.</p> -->
<permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT"
@@ -2616,6 +2624,13 @@
android:label="@string/permlab_trust_listener"
android:description="@string/permdesc_trust_listener" />
+ <!-- Allows an application to provide a trust agent.
+ @hide For security reasons, this is a platform-only permission. -->
+ <permission android:name="android.permission.PROVIDE_TRUST_AGENT"
+ android:protectionLevel="signatureOrSystem"
+ android:label="@string/permlab_provide_trust_agent"
+ android:description="@string/permdesc_provide_trust_agent" />
+
<!-- Must be required by an {@link
android.service.trust.TrustAgentService},
to ensure that only the system can bind to it. -->
diff --git a/core/res/res/anim/voice_activity_open_enter.xml b/core/res/res/anim/voice_activity_open_enter.xml
index 57fba2a..ce7a4f9 100644
--- a/core/res/res/anim/voice_activity_open_enter.xml
+++ b/core/res/res/anim/voice_activity_open_enter.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/* //device/apps/common/res/anim/fade_in.xml
**
** Copyright 2007, The Android Open Source Project
**
diff --git a/core/res/res/anim/voice_layer_enter.xml b/core/res/res/anim/voice_layer_enter.xml
index 57fba2a..ce7a4f9 100644
--- a/core/res/res/anim/voice_layer_enter.xml
+++ b/core/res/res/anim/voice_layer_enter.xml
@@ -1,6 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
-/* //device/apps/common/res/anim/fade_in.xml
**
** Copyright 2007, The Android Open Source Project
**
diff --git a/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index ba5bd01..0000000
--- a/core/res/res/drawable-hdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_accessibility_features.png b/core/res/res/drawable-hdpi/perm_group_accessibility_features.png
index 849c19c..7a1948e 100755..100644
--- a/core/res/res/drawable-hdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-hdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_accounts.png b/core/res/res/drawable-hdpi/perm_group_accounts.png
index db59ab0..68a7c88 100644
--- a/core/res/res/drawable-hdpi/perm_group_accounts.png
+++ b/core/res/res/drawable-hdpi/perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_affects_battery.png b/core/res/res/drawable-hdpi/perm_group_affects_battery.png
index 8ca8154..14adad1 100644
--- a/core/res/res/drawable-hdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-hdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_app_info.png b/core/res/res/drawable-hdpi/perm_group_app_info.png
index b03e2f3..a263d33 100644
--- a/core/res/res/drawable-hdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-hdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_audio_settings.png b/core/res/res/drawable-hdpi/perm_group_audio_settings.png
index 4e652a8..4e152af 100644
--- a/core/res/res/drawable-hdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-hdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_bluetooth.png b/core/res/res/drawable-hdpi/perm_group_bluetooth.png
index 0f28454..22ab06a 100644
--- a/core/res/res/drawable-hdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-hdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_bookmarks.png b/core/res/res/drawable-hdpi/perm_group_bookmarks.png
index 06f6344..069bd85 100644
--- a/core/res/res/drawable-hdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-hdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_calendar.png b/core/res/res/drawable-hdpi/perm_group_calendar.png
index c0a4dfd..8fe55e7 100644
--- a/core/res/res/drawable-hdpi/perm_group_calendar.png
+++ b/core/res/res/drawable-hdpi/perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_camera.png b/core/res/res/drawable-hdpi/perm_group_camera.png
index cbc07b0..0203147 100644
--- a/core/res/res/drawable-hdpi/perm_group_camera.png
+++ b/core/res/res/drawable-hdpi/perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_device_alarms.png b/core/res/res/drawable-hdpi/perm_group_device_alarms.png
index d44b9de..4010c7a 100644
--- a/core/res/res/drawable-hdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-hdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_display.png b/core/res/res/drawable-hdpi/perm_group_display.png
index e8afece..f60c7e2 100644
--- a/core/res/res/drawable-hdpi/perm_group_display.png
+++ b/core/res/res/drawable-hdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_location.png b/core/res/res/drawable-hdpi/perm_group_location.png
index dc2f8ef..2cc0ba6 100644
--- a/core/res/res/drawable-hdpi/perm_group_location.png
+++ b/core/res/res/drawable-hdpi/perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_messages.png b/core/res/res/drawable-hdpi/perm_group_messages.png
index 680c178..013bc8f 100644
--- a/core/res/res/drawable-hdpi/perm_group_messages.png
+++ b/core/res/res/drawable-hdpi/perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_microphone.png b/core/res/res/drawable-hdpi/perm_group_microphone.png
index a73a945..c94b0ba 100644
--- a/core/res/res/drawable-hdpi/perm_group_microphone.png
+++ b/core/res/res/drawable-hdpi/perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_network.png b/core/res/res/drawable-hdpi/perm_group_network.png
index c750e2a..f7907ef 100644
--- a/core/res/res/drawable-hdpi/perm_group_network.png
+++ b/core/res/res/drawable-hdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_personal_info.png b/core/res/res/drawable-hdpi/perm_group_personal_info.png
index 130e7ad..dcfb160 100644
--- a/core/res/res/drawable-hdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-hdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_phone_calls.png b/core/res/res/drawable-hdpi/perm_group_phone_calls.png
index 577855b..1decd84 100644
--- a/core/res/res/drawable-hdpi/perm_group_phone_calls.png
+++ b/core/res/res/drawable-hdpi/perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_screenlock.png b/core/res/res/drawable-hdpi/perm_group_screenlock.png
index 9c5143d..6abde49 100644
--- a/core/res/res/drawable-hdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-hdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_shortrange_network.png b/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
index 554a4e4..f7907ef 100644
--- a/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-hdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_social_info.png b/core/res/res/drawable-hdpi/perm_group_social_info.png
index 134990b..e7e2488 100644
--- a/core/res/res/drawable-hdpi/perm_group_social_info.png
+++ b/core/res/res/drawable-hdpi/perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_status_bar.png b/core/res/res/drawable-hdpi/perm_group_status_bar.png
index bda963b..73760b2 100644
--- a/core/res/res/drawable-hdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-hdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_storage.png b/core/res/res/drawable-hdpi/perm_group_storage.png
index e6b3965..642ce20 100644
--- a/core/res/res/drawable-hdpi/perm_group_storage.png
+++ b/core/res/res/drawable-hdpi/perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_sync_settings.png b/core/res/res/drawable-hdpi/perm_group_sync_settings.png
index be70866..0bc1506 100644
--- a/core/res/res/drawable-hdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-hdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_system_clock.png b/core/res/res/drawable-hdpi/perm_group_system_clock.png
index 75794c3..7e4e293 100644
--- a/core/res/res/drawable-hdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-hdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_system_tools.png b/core/res/res/drawable-hdpi/perm_group_system_tools.png
index 3fd4385..00a4c03 100644
--- a/core/res/res/drawable-hdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-hdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_user_dictionary.png b/core/res/res/drawable-hdpi/perm_group_user_dictionary.png
index 98a0894..fc41348 100644
--- a/core/res/res/drawable-hdpi/perm_group_user_dictionary.png
+++ b/core/res/res/drawable-hdpi/perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png
index 784ea0f..7fa88aa 100644
--- a/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png
+++ b/core/res/res/drawable-hdpi/perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_voicemail.png b/core/res/res/drawable-hdpi/perm_group_voicemail.png
index b08b153..0ce5d1d 100644
--- a/core/res/res/drawable-hdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-hdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/perm_group_wallpaper.png b/core/res/res/drawable-hdpi/perm_group_wallpaper.png
index cf073a4..5db0361 100644
--- a/core/res/res/drawable-hdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-hdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png b/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 49841ea..0000000
--- a/core/res/res/drawable-hdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png b/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
deleted file mode 100644
index 69f0070..0000000
--- a/core/res/res/drawable-hdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-hdpi/tab_indicator_normal_qntm_alpha.9.png
deleted file mode 100644
index 233d409..0000000
--- a/core/res/res/drawable-hdpi/tab_indicator_normal_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_indicator_qntm_alpha.9.png b/core/res/res/drawable-hdpi/tab_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..21b2135
--- /dev/null
+++ b/core/res/res/drawable-hdpi/tab_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-hdpi/tab_indicator_selected_qntm_alpha.9.png
deleted file mode 100644
index 68b1dd7..0000000
--- a/core/res/res/drawable-hdpi/tab_indicator_selected_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-hdpi/work_icon.png b/core/res/res/drawable-hdpi/work_icon.png
index e90866b..be8a36e 100644
--- a/core/res/res/drawable-hdpi/work_icon.png
+++ b/core/res/res/drawable-hdpi/work_icon.png
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-ldpi/tab_indicator_normal_qntm_alpha.9.png
deleted file mode 100644
index 2244362..0000000
--- a/core/res/res/drawable-ldpi/tab_indicator_normal_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-ldpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-ldpi/tab_indicator_selected_qntm_alpha.9.png
deleted file mode 100644
index 22ea80e..0000000
--- a/core/res/res/drawable-ldpi/tab_indicator_selected_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index 4e2612d..0000000
--- a/core/res/res/drawable-mdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_accessibility_features.png b/core/res/res/drawable-mdpi/perm_group_accessibility_features.png
index ba86d3d..df5c147 100755..100644
--- a/core/res/res/drawable-mdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-mdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_accounts.png b/core/res/res/drawable-mdpi/perm_group_accounts.png
index 3dd4043..0c4dd02 100644
--- a/core/res/res/drawable-mdpi/perm_group_accounts.png
+++ b/core/res/res/drawable-mdpi/perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_affects_battery.png b/core/res/res/drawable-mdpi/perm_group_affects_battery.png
index 7291916..511921d 100644
--- a/core/res/res/drawable-mdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-mdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_app_info.png b/core/res/res/drawable-mdpi/perm_group_app_info.png
index 8ba65bd..e715177 100644
--- a/core/res/res/drawable-mdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-mdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_audio_settings.png b/core/res/res/drawable-mdpi/perm_group_audio_settings.png
index f2f461b..26ff28e 100644
--- a/core/res/res/drawable-mdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-mdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_bluetooth.png b/core/res/res/drawable-mdpi/perm_group_bluetooth.png
index 6db6fde..effa405 100644
--- a/core/res/res/drawable-mdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-mdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_bookmarks.png b/core/res/res/drawable-mdpi/perm_group_bookmarks.png
index f908e14..2103632 100644
--- a/core/res/res/drawable-mdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-mdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_calendar.png b/core/res/res/drawable-mdpi/perm_group_calendar.png
index 5905973..e22fd7f 100644
--- a/core/res/res/drawable-mdpi/perm_group_calendar.png
+++ b/core/res/res/drawable-mdpi/perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_camera.png b/core/res/res/drawable-mdpi/perm_group_camera.png
index be1c9e6..463654b 100644
--- a/core/res/res/drawable-mdpi/perm_group_camera.png
+++ b/core/res/res/drawable-mdpi/perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_device_alarms.png b/core/res/res/drawable-mdpi/perm_group_device_alarms.png
index 48d6d6a..1348131 100644
--- a/core/res/res/drawable-mdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-mdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_display.png b/core/res/res/drawable-mdpi/perm_group_display.png
index e10609c..ea51240 100644
--- a/core/res/res/drawable-mdpi/perm_group_display.png
+++ b/core/res/res/drawable-mdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_location.png b/core/res/res/drawable-mdpi/perm_group_location.png
index e79ec25..2fcb124 100644
--- a/core/res/res/drawable-mdpi/perm_group_location.png
+++ b/core/res/res/drawable-mdpi/perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_messages.png b/core/res/res/drawable-mdpi/perm_group_messages.png
index dfb3ba7..6f3ecf8 100644
--- a/core/res/res/drawable-mdpi/perm_group_messages.png
+++ b/core/res/res/drawable-mdpi/perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_microphone.png b/core/res/res/drawable-mdpi/perm_group_microphone.png
index 9bab315..b4717a3 100644
--- a/core/res/res/drawable-mdpi/perm_group_microphone.png
+++ b/core/res/res/drawable-mdpi/perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_network.png b/core/res/res/drawable-mdpi/perm_group_network.png
index f2798a7..a624e42 100644
--- a/core/res/res/drawable-mdpi/perm_group_network.png
+++ b/core/res/res/drawable-mdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_personal_info.png b/core/res/res/drawable-mdpi/perm_group_personal_info.png
index 6233a82..cf56fa50 100644
--- a/core/res/res/drawable-mdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-mdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_phone_calls.png b/core/res/res/drawable-mdpi/perm_group_phone_calls.png
index ff3ffd5..467f37f 100644
--- a/core/res/res/drawable-mdpi/perm_group_phone_calls.png
+++ b/core/res/res/drawable-mdpi/perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_screenlock.png b/core/res/res/drawable-mdpi/perm_group_screenlock.png
index abfe6e4..f8b351e 100644
--- a/core/res/res/drawable-mdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-mdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_shortrange_network.png b/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
index 5d73375..a624e42 100644
--- a/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-mdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_social_info.png b/core/res/res/drawable-mdpi/perm_group_social_info.png
index c862f9e..8ae10f1 100644
--- a/core/res/res/drawable-mdpi/perm_group_social_info.png
+++ b/core/res/res/drawable-mdpi/perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_status_bar.png b/core/res/res/drawable-mdpi/perm_group_status_bar.png
index 4158fa6..86868ab 100644
--- a/core/res/res/drawable-mdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-mdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_storage.png b/core/res/res/drawable-mdpi/perm_group_storage.png
index 3dcfb22f..61ff8a3 100644
--- a/core/res/res/drawable-mdpi/perm_group_storage.png
+++ b/core/res/res/drawable-mdpi/perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_sync_settings.png b/core/res/res/drawable-mdpi/perm_group_sync_settings.png
index 5a0e5ff..9049f47 100644
--- a/core/res/res/drawable-mdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-mdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_system_clock.png b/core/res/res/drawable-mdpi/perm_group_system_clock.png
index e4d5743..554dd0f 100644
--- a/core/res/res/drawable-mdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-mdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_system_tools.png b/core/res/res/drawable-mdpi/perm_group_system_tools.png
index fc7337d..845a593 100644
--- a/core/res/res/drawable-mdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-mdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_user_dictionary.png b/core/res/res/drawable-mdpi/perm_group_user_dictionary.png
index 92864ba..188343d 100644
--- a/core/res/res/drawable-mdpi/perm_group_user_dictionary.png
+++ b/core/res/res/drawable-mdpi/perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png
index 9f48713..04b9cdc 100644
--- a/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png
+++ b/core/res/res/drawable-mdpi/perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_voicemail.png b/core/res/res/drawable-mdpi/perm_group_voicemail.png
index a34d689..163046b 100644
--- a/core/res/res/drawable-mdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-mdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/perm_group_wallpaper.png b/core/res/res/drawable-mdpi/perm_group_wallpaper.png
index b990e7f..5b96e08 100644
--- a/core/res/res/drawable-mdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-mdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png b/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 4569fae..0000000
--- a/core/res/res/drawable-mdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png b/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
deleted file mode 100644
index 9287dd7..0000000
--- a/core/res/res/drawable-mdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-mdpi/tab_indicator_normal_qntm_alpha.9.png
deleted file mode 100644
index fd668ee..0000000
--- a/core/res/res/drawable-mdpi/tab_indicator_normal_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_indicator_qntm_alpha.9.png b/core/res/res/drawable-mdpi/tab_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..b69529c
--- /dev/null
+++ b/core/res/res/drawable-mdpi/tab_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-mdpi/tab_indicator_selected_qntm_alpha.9.png
deleted file mode 100644
index ace579f..0000000
--- a/core/res/res/drawable-mdpi/tab_indicator_selected_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index e6ca1ea..0000000
--- a/core/res/res/drawable-xhdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png b/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png
index 2fec7a3..9edbada 100644
--- a/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png
+++ b/core/res/res/drawable-xhdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_accounts.png b/core/res/res/drawable-xhdpi/perm_group_accounts.png
index 74cd33b..b2cad91 100644
--- a/core/res/res/drawable-xhdpi/perm_group_accounts.png
+++ b/core/res/res/drawable-xhdpi/perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_affects_battery.png b/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
index d4a9bb5d..123e0a2 100644
--- a/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
+++ b/core/res/res/drawable-xhdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_app_info.png b/core/res/res/drawable-xhdpi/perm_group_app_info.png
index 46089e5..8373633 100644
--- a/core/res/res/drawable-xhdpi/perm_group_app_info.png
+++ b/core/res/res/drawable-xhdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_audio_settings.png b/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
index 2f7cbc3..7c10395 100644
--- a/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
+++ b/core/res/res/drawable-xhdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_bluetooth.png b/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
index 6bbde52..ce58d66 100644
--- a/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
+++ b/core/res/res/drawable-xhdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_bookmarks.png b/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
index 1277d03..db28d89 100644
--- a/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
+++ b/core/res/res/drawable-xhdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_calendar.png b/core/res/res/drawable-xhdpi/perm_group_calendar.png
index 3c7f2d3..d49b883 100644
--- a/core/res/res/drawable-xhdpi/perm_group_calendar.png
+++ b/core/res/res/drawable-xhdpi/perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_camera.png b/core/res/res/drawable-xhdpi/perm_group_camera.png
index a454554..5287e00 100644
--- a/core/res/res/drawable-xhdpi/perm_group_camera.png
+++ b/core/res/res/drawable-xhdpi/perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_device_alarms.png b/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
index 1bb151c..c52148d 100644
--- a/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
+++ b/core/res/res/drawable-xhdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_display.png b/core/res/res/drawable-xhdpi/perm_group_display.png
index 9e36cf8..90fcc73 100644
--- a/core/res/res/drawable-xhdpi/perm_group_display.png
+++ b/core/res/res/drawable-xhdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_location.png b/core/res/res/drawable-xhdpi/perm_group_location.png
index 4c49521..99dbcbc 100644
--- a/core/res/res/drawable-xhdpi/perm_group_location.png
+++ b/core/res/res/drawable-xhdpi/perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_messages.png b/core/res/res/drawable-xhdpi/perm_group_messages.png
index f046d46..c674d54 100644
--- a/core/res/res/drawable-xhdpi/perm_group_messages.png
+++ b/core/res/res/drawable-xhdpi/perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_microphone.png b/core/res/res/drawable-xhdpi/perm_group_microphone.png
index bdb66e2..9c2a6b6 100644
--- a/core/res/res/drawable-xhdpi/perm_group_microphone.png
+++ b/core/res/res/drawable-xhdpi/perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_network.png b/core/res/res/drawable-xhdpi/perm_group_network.png
index fe1adad..8557889 100644
--- a/core/res/res/drawable-xhdpi/perm_group_network.png
+++ b/core/res/res/drawable-xhdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_personal_info.png b/core/res/res/drawable-xhdpi/perm_group_personal_info.png
index 1ae418f..3a1419a 100644
--- a/core/res/res/drawable-xhdpi/perm_group_personal_info.png
+++ b/core/res/res/drawable-xhdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_phone_calls.png b/core/res/res/drawable-xhdpi/perm_group_phone_calls.png
index 288e15c..9a24905 100644
--- a/core/res/res/drawable-xhdpi/perm_group_phone_calls.png
+++ b/core/res/res/drawable-xhdpi/perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_screenlock.png b/core/res/res/drawable-xhdpi/perm_group_screenlock.png
index bf3ec34..49f526e 100644
--- a/core/res/res/drawable-xhdpi/perm_group_screenlock.png
+++ b/core/res/res/drawable-xhdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png b/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
index 5e1e240..8557889 100644
--- a/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
+++ b/core/res/res/drawable-xhdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_social_info.png b/core/res/res/drawable-xhdpi/perm_group_social_info.png
index 2111a83..1ecda40 100644
--- a/core/res/res/drawable-xhdpi/perm_group_social_info.png
+++ b/core/res/res/drawable-xhdpi/perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_status_bar.png b/core/res/res/drawable-xhdpi/perm_group_status_bar.png
index ce65380..19a611b 100644
--- a/core/res/res/drawable-xhdpi/perm_group_status_bar.png
+++ b/core/res/res/drawable-xhdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_storage.png b/core/res/res/drawable-xhdpi/perm_group_storage.png
index 4cd5c9b..85753f1 100644
--- a/core/res/res/drawable-xhdpi/perm_group_storage.png
+++ b/core/res/res/drawable-xhdpi/perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_sync_settings.png b/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
index 24eb579..7249716 100644
--- a/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
+++ b/core/res/res/drawable-xhdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_system_clock.png b/core/res/res/drawable-xhdpi/perm_group_system_clock.png
index 36d1294..bf829e4 100644
--- a/core/res/res/drawable-xhdpi/perm_group_system_clock.png
+++ b/core/res/res/drawable-xhdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_system_tools.png b/core/res/res/drawable-xhdpi/perm_group_system_tools.png
index 7b6cdd8..8a942b6 100644
--- a/core/res/res/drawable-xhdpi/perm_group_system_tools.png
+++ b/core/res/res/drawable-xhdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png b/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png
index c0106bb..345b29f 100644
--- a/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png
+++ b/core/res/res/drawable-xhdpi/perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png
index 36bb395..f0a98a3 100644
--- a/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png
+++ b/core/res/res/drawable-xhdpi/perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_voicemail.png b/core/res/res/drawable-xhdpi/perm_group_voicemail.png
index eb17a63..53417ba 100644
--- a/core/res/res/drawable-xhdpi/perm_group_voicemail.png
+++ b/core/res/res/drawable-xhdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/perm_group_wallpaper.png b/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
index be4663c..6cac9bf 100644
--- a/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
+++ b/core/res/res/drawable-xhdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 76e9428..0000000
--- a/core/res/res/drawable-xhdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
deleted file mode 100644
index 6f693d6..0000000
--- a/core/res/res/drawable-xhdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/tab_indicator_normal_qntm_alpha.9.png
deleted file mode 100644
index a677f9a..0000000
--- a/core/res/res/drawable-xhdpi/tab_indicator_normal_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_indicator_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/tab_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..5610d8c
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/tab_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/tab_indicator_selected_qntm_alpha.9.png
deleted file mode 100644
index 7de791d..0000000
--- a/core/res/res/drawable-xhdpi/tab_indicator_selected_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png b/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
deleted file mode 100644
index d6018dd..0000000
--- a/core/res/res/drawable-xxhdpi/ic_lock_bugreport_alpha.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_accessibility_features.png b/core/res/res/drawable-xxhdpi/perm_group_accessibility_features.png
new file mode 100644
index 0000000..75cfa8f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_accessibility_features.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_accounts.png b/core/res/res/drawable-xxhdpi/perm_group_accounts.png
new file mode 100644
index 0000000..148c5d1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_accounts.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_affects_battery.png b/core/res/res/drawable-xxhdpi/perm_group_affects_battery.png
new file mode 100644
index 0000000..b453a97
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_affects_battery.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_app_info.png b/core/res/res/drawable-xxhdpi/perm_group_app_info.png
new file mode 100644
index 0000000..c723e78
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_app_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_audio_settings.png b/core/res/res/drawable-xxhdpi/perm_group_audio_settings.png
new file mode 100644
index 0000000..36109e5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_audio_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_bluetooth.png b/core/res/res/drawable-xxhdpi/perm_group_bluetooth.png
new file mode 100644
index 0000000..f545010
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_bluetooth.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_bookmarks.png b/core/res/res/drawable-xxhdpi/perm_group_bookmarks.png
new file mode 100644
index 0000000..ddfcfd5
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_bookmarks.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_calendar.png b/core/res/res/drawable-xxhdpi/perm_group_calendar.png
new file mode 100644
index 0000000..75f7f77
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_calendar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_camera.png b/core/res/res/drawable-xxhdpi/perm_group_camera.png
new file mode 100644
index 0000000..2ee83f6
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_camera.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_device_alarms.png b/core/res/res/drawable-xxhdpi/perm_group_device_alarms.png
new file mode 100644
index 0000000..4218c29
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_device_alarms.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_display.png b/core/res/res/drawable-xxhdpi/perm_group_display.png
new file mode 100644
index 0000000..a03e670
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_display.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_location.png b/core/res/res/drawable-xxhdpi/perm_group_location.png
new file mode 100644
index 0000000..4ac3fb4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_location.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_messages.png b/core/res/res/drawable-xxhdpi/perm_group_messages.png
new file mode 100644
index 0000000..f406a9d
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_messages.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_microphone.png b/core/res/res/drawable-xxhdpi/perm_group_microphone.png
new file mode 100644
index 0000000..6137b86
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_microphone.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_network.png b/core/res/res/drawable-xxhdpi/perm_group_network.png
new file mode 100644
index 0000000..72d2ef0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_personal_info.png b/core/res/res/drawable-xxhdpi/perm_group_personal_info.png
new file mode 100644
index 0000000..fe18ec9
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_personal_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_phone_calls.png b/core/res/res/drawable-xxhdpi/perm_group_phone_calls.png
new file mode 100644
index 0000000..acfa435
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_phone_calls.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_screenlock.png b/core/res/res/drawable-xxhdpi/perm_group_screenlock.png
new file mode 100644
index 0000000..2fd88ff
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_screenlock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_shortrange_network.png b/core/res/res/drawable-xxhdpi/perm_group_shortrange_network.png
new file mode 100644
index 0000000..72d2ef0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_shortrange_network.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_social_info.png b/core/res/res/drawable-xxhdpi/perm_group_social_info.png
new file mode 100644
index 0000000..73076e0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_social_info.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_status_bar.png b/core/res/res/drawable-xxhdpi/perm_group_status_bar.png
new file mode 100644
index 0000000..380fd66
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_status_bar.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_storage.png b/core/res/res/drawable-xxhdpi/perm_group_storage.png
new file mode 100644
index 0000000..b2da3ae
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_storage.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_sync_settings.png b/core/res/res/drawable-xxhdpi/perm_group_sync_settings.png
new file mode 100644
index 0000000..60aecd1
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_sync_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_system_clock.png b/core/res/res/drawable-xxhdpi/perm_group_system_clock.png
new file mode 100644
index 0000000..30cc29c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_system_clock.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_system_tools.png b/core/res/res/drawable-xxhdpi/perm_group_system_tools.png
new file mode 100644
index 0000000..129c221
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_system_tools.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_user_dictionary.png b/core/res/res/drawable-xxhdpi/perm_group_user_dictionary.png
new file mode 100644
index 0000000..020167f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_user_dictionary.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_user_dictionary_write.png b/core/res/res/drawable-xxhdpi/perm_group_user_dictionary_write.png
new file mode 100644
index 0000000..6218f62
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_user_dictionary_write.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_voicemail.png b/core/res/res/drawable-xxhdpi/perm_group_voicemail.png
new file mode 100644
index 0000000..336cb6b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_voicemail.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/perm_group_wallpaper.png b/core/res/res/drawable-xxhdpi/perm_group_wallpaper.png
new file mode 100644
index 0000000..e7d8f43
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/perm_group_wallpaper.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png b/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png
deleted file mode 100644
index 6cbd1f4..0000000
--- a/core/res/res/drawable-xxhdpi/spinner_20_inner_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png b/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png
deleted file mode 100644
index b6af5e7..0000000
--- a/core/res/res/drawable-xxhdpi/spinner_20_outer_holo.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_indicator_normal_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/tab_indicator_normal_qntm_alpha.9.png
deleted file mode 100644
index 0a14025..0000000
--- a/core/res/res/drawable-xxhdpi/tab_indicator_normal_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_indicator_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/tab_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..248f4f8
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/tab_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/tab_indicator_selected_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/tab_indicator_selected_qntm_alpha.9.png
deleted file mode 100644
index 20e291a..0000000
--- a/core/res/res/drawable-xxhdpi/tab_indicator_selected_qntm_alpha.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xxxhdpi/tab_indicator_qntm_alpha.9.png b/core/res/res/drawable-xxxhdpi/tab_indicator_qntm_alpha.9.png
new file mode 100644
index 0000000..5813179
--- /dev/null
+++ b/core/res/res/drawable-xxxhdpi/tab_indicator_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/edit_text_quantum.xml b/core/res/res/drawable/edit_text_quantum.xml
index 67339e8..ab2580a 100644
--- a/core/res/res/drawable/edit_text_quantum.xml
+++ b/core/res/res/drawable/edit_text_quantum.xml
@@ -15,25 +15,20 @@
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
- android:tint="?attr/colorControlActivated">
+ android:tint="?attr/colorControlActivated"
+ android:tintMode="src_over">
<item>
<selector>
- <item android:state_window_focused="false">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
<item android:state_enabled="false">
<nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
- <item android:state_focused="false" android:state_activated="false">
- <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
+ android:tint="?attr/colorControlNormal"
+ android:alpha="?attr/disabledAlpha" />
</item>
<item>
- <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
+ <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
android:tint="?attr/colorControlNormal" />
</item>
</selector>
</item>
+ <item android:id="@+id/mask" android:drawable="@drawable/textfield_activated_qntm_alpha" />
</ripple>
diff --git a/core/res/res/drawable/ic_lock_bugreport.xml b/core/res/res/drawable/ic_lock_bugreport.xml
index a3f82ce..b93a09a 100644
--- a/core/res/res/drawable/ic_lock_bugreport.xml
+++ b/core/res/res/drawable/ic_lock_bugreport.xml
@@ -1,19 +1,28 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2014 The Android Open Source Project
+<!--
+Copyright (C) 2014 The Android Open Source Project
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+ 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
+ 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.
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+ <size
+ android:width="32dp"
+ android:height="32dp"/>
-<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
- android:src="@drawable/ic_lock_bugreport_alpha"
- android:tint="?attr/colorControlNormal" />
+ <viewport
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0"/>
+
+ <path
+ android:fill="?attr/colorControlNormal"
+ android:pathData="M20.0,8.0l-2.8,0.0c-0.5,-0.8 -1.1,-1.5 -1.8,-2.0L17.0,4.4L15.6,3.0l-2.2,2.2C13.0,5.1 12.5,5.0 12.0,5.0s-1.0,0.1 -1.4,0.2L8.4,3.0L7.0,4.4L8.6,6.0C7.9,6.5 7.3,7.2 6.8,8.0L4.0,8.0l0.0,2.0l2.1,0.0C6.0,10.3 6.0,10.7 6.0,11.0l0.0,1.0L4.0,12.0l0.0,2.0l2.0,0.0l0.0,1.0c0.0,0.3 0.0,0.7 0.1,1.0L4.0,16.0l0.0,2.0l2.8,0.0c1.0,1.8 3.0,3.0 5.2,3.0s4.2,-1.2 5.2,-3.0L20.0,18.0l0.0,-2.0l-2.1,0.0c0.1,-0.3 0.1,-0.7 0.1,-1.0l0.0,-1.0l2.0,0.0l0.0,-2.0l-2.0,0.0l0.0,-1.0c0.0,-0.3 0.0,-0.7 -0.1,-1.0L20.0,10.0L20.0,8.0zM14.0,16.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,16.0zM14.0,12.0l-4.0,0.0l0.0,-2.0l4.0,0.0L14.0,12.0z"/>
+</vector>
diff --git a/core/res/res/drawable/progress_large_quantum.xml b/core/res/res/drawable/progress_large_quantum.xml
new file mode 100644
index 0000000..7bef637
--- /dev/null
+++ b/core/res/res/drawable/progress_large_quantum.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<quantum-progress xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?attr/colorControlActivated"
+ android:width="76dp"
+ android:height="76dp"
+ android:thickness="6.3dp"
+ android:innerRadius="30.1dp" />
diff --git a/core/res/res/drawable/progress_medium_quantum.xml b/core/res/res/drawable/progress_medium_quantum.xml
new file mode 100644
index 0000000..adc72f0
--- /dev/null
+++ b/core/res/res/drawable/progress_medium_quantum.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<quantum-progress xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?attr/colorControlActivated"
+ android:width="48dp"
+ android:height="48dp"
+ android:thickness="4dp"
+ android:innerRadius="19dp" />
diff --git a/core/res/res/drawable/progress_small_quantum.xml b/core/res/res/drawable/progress_small_quantum.xml
new file mode 100644
index 0000000..eb4884a
--- /dev/null
+++ b/core/res/res/drawable/progress_small_quantum.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<quantum-progress xmlns:android="http://schemas.android.com/apk/res/android"
+ android:color="?attr/colorControlActivated"
+ android:width="16dp"
+ android:height="16dp"
+ android:thickness="1.3dp"
+ android:innerRadius="6.3dp" />
diff --git a/core/res/res/drawable/tab_indicator_quantum.xml b/core/res/res/drawable/tab_indicator_quantum.xml
index 6fabe23..ff14d9c 100644
--- a/core/res/res/drawable/tab_indicator_quantum.xml
+++ b/core/res/res/drawable/tab_indicator_quantum.xml
@@ -15,29 +15,9 @@
-->
<selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:state_selected="true" android:state_pressed="true">
- <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item android:state_selected="true" android:state_focused="true">
- <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
<item android:state_selected="true">
- <nine-patch android:src="@drawable/tab_indicator_selected_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
-
- <item android:state_pressed="true">
- <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="?attr/colorControlActivated" />
- </item>
- <item android:state_focused="true">
- <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
+ <nine-patch android:src="@drawable/tab_indicator_qntm_alpha"
android:tint="?attr/colorControlActivated" />
</item>
- <item>
- <nine-patch android:src="@drawable/tab_indicator_normal_qntm_alpha"
- android:tint="?attr/colorControlNormal" />
- </item>
+ <item android:drawable="@color/transparent" />
</selector>
diff --git a/core/res/res/transition/fade.xml b/core/res/res/transition/fade.xml
new file mode 100644
index 0000000..22397d4
--- /dev/null
+++ b/core/res/res/transition/fade.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<fade xmlns:android="http://schemas.android.com/apk/res/android"/>
diff --git a/core/res/res/transition/move.xml b/core/res/res/transition/move.xml
new file mode 100644
index 0000000..d4863ee
--- /dev/null
+++ b/core/res/res/transition/move.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
+ <transitionSet>
+ <changeBounds/>
+ <changeTransform/>
+ <changeClipBounds/>
+ <targets>
+ <target android:excludeClass="android.widget.ImageView"/>
+ </targets>
+ </transitionSet>
+ <moveImage>
+ <targets>
+ <target android:targetClass="android.widget.ImageView"/>
+ </targets>
+ </moveImage>
+</transitionSet>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index f3b8495..dbe2d7f 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -68,7 +68,7 @@
</plurals>
<string name="imei" msgid="2625429890869005782">"IMEI"</string>
<string name="meid" msgid="4841221237681254195">"MEID"</string>
- <string name="ClipMmi" msgid="6952821216480289285">"លេខ​សម្គាល់​អ្នក​ហៅ​​ចូល"</string>
+ <string name="ClipMmi" msgid="6952821216480289285">"លេខ​សម្គាល់​អ្នក​ហៅ​​ចូល​"</string>
<string name="ClirMmi" msgid="7784673673446833091">"លេខ​សម្គាល់​អ្នក​ហៅ​ចេញ"</string>
<string name="CfMmi" msgid="5123218989141573515">"បញ្ជូន​ការ​ហៅ​បន្ត"</string>
<string name="CwMmi" msgid="9129678056795016867">"រង់ចាំ​ការ​ហៅ"</string>
@@ -125,7 +125,7 @@
<string name="cfTemplateRegisteredTime" msgid="6781621964320635172">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g> ៖ មិន​បាន​បញ្ជូន​បន្ត"</string>
<string name="fcComplete" msgid="3118848230966886575">"កូដ​លក្ខណៈ​ពេញលេញ។"</string>
<string name="fcError" msgid="3327560126588500777">"បញ្ហា​ការ​តភ្ជាប់​ ឬ​កូដ​លក្ខណៈ​​​មិន​ត្រឹមត្រូវ​។"</string>
- <string name="httpErrorOk" msgid="1191919378083472204">"យល់​ព្រម"</string>
+ <string name="httpErrorOk" msgid="1191919378083472204">"យល់​ព្រម​"</string>
<string name="httpError" msgid="7956392511146698522">"មាន​កំហុស​បណ្ដាញ។"</string>
<string name="httpErrorLookup" msgid="4711687456111963163">"រក​មិន​ឃើញ URL ។"</string>
<string name="httpErrorUnsupportedAuthScheme" msgid="6299980280442076799">"គ្រោងការណ៍​ផ្ទៀងផ្ទាត់​តំបន់បណ្ដាញ​មិន​ត្រូវ​បាន​គាំទ្រ។"</string>
@@ -183,7 +183,7 @@
<string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"បើក​សំឡេង"</string>
<string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ពេល​ជិះ​យន្តហោះ"</string>
<string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"បាន​បើក​របៀប​ពេល​ជិះ​យន្ត​ហោះ"</string>
- <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ"</string>
+ <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ​"</string>
<string name="global_action_settings" msgid="1756531602592545966">"ការ​កំណត់"</string>
<string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
<string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
@@ -195,7 +195,7 @@
<string name="permgrouplab_messages" msgid="7521249148445456662">"សារ​របស់​អ្នក"</string>
<string name="permgroupdesc_messages" msgid="7821999071003699236">"អាន និង​សរសេរ​សារ SMS, អ៊ីមែល និង​សារ​ផ្សេងៗ​ទៀត​របស់​អ្នក។"</string>
<string name="permgrouplab_personalInfo" msgid="3519163141070533474">"ព័ត៌មាន​ផ្ទាល់ខ្លួន​របស់​អ្នក"</string>
- <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​អ្នក​ ដែល​បា​ន​រក្សាទុក​ក្នុង​កាត​ទំនាក់ទំនង​របស់​អ្នក។"</string>
+ <string name="permgroupdesc_personalInfo" msgid="8426453129788861338">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​អ្នក​ ដែល​បា​ន​រក្សាទុក​ក្នុង​កាត​ទំនាក់ទំនង​របស់​អ្នក។​"</string>
<string name="permgrouplab_socialInfo" msgid="5799096623412043791">"ព័ត៌មាន​សង្គម​របស់​អ្នក"</string>
<string name="permgroupdesc_socialInfo" msgid="7129842457611643493">"ចូល​ដំណើរការ​ព័ត៌មាន​ដោយ​ផ្ទាល់​អំពី​ទំនាក់ទំនង និង​ការ​ភ្ជាប់​សង្គម​របស់​អ្នក។"</string>
<string name="permgrouplab_location" msgid="635149742436692049">"ទីតាំង​របស់​អ្នក"</string>
@@ -384,7 +384,7 @@
<string name="permdesc_readInputState" msgid="8387754901688728043">"ឲ្យ​កម្មវិធី​មើល​គ្រាប់​ចុច​ដែល​អ្នក​ចុច​ពេល​មាន​អន្តរកម្ម​ជា​មួយ​កម្មវិធី​ផ្សេង (ដូចជា បញ្ចូល​ពាក្យ​សម្ងាត់)។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
<string name="permlab_bindInputMethod" msgid="3360064620230515776">"ចង​ទៅ​វិធីសាស្ត្រ​បញ្ចូល"</string>
<string name="permdesc_bindInputMethod" msgid="3250440322807286331">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​វិធី​សាស្ត្រ​បញ្ចូល។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
- <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចង​សេវា​កម្ម​ភាព​មធ្យោបាយ​ងាយស្រួល"</string>
+ <string name="permlab_bindAccessibilityService" msgid="5357733942556031593">"ចង​សេវា​កម្ម​ភាព​មធ្យោបាយ​ងាយស្រួល​"</string>
<string name="permdesc_bindAccessibilityService" msgid="7034615928609331368">"ឲ្យ​​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ភាព​ងាយស្រួល។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
<string name="permlab_bindPrintService" msgid="8462815179572748761">"ចង​សេវាកម្ម​​បោះពុម្ព"</string>
<string name="permdesc_bindPrintService" msgid="7960067623209111135">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -402,7 +402,7 @@
<string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​​របស់​សេវាកម្ម​អន្តរកម្ម​សំឡេង។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
<string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ភ្ជាប់​ទៅ​ការ​បង្ហាញ​ពី​ចម្ងាយ"</string>
<string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​ការ​បង្ហាញ​ពី​ចម្ងាយ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
- <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក"</string>
+ <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក​"</string>
<string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
<string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ភ្ជាប់​ទៅ​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​ច្រក"</string>
<string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ក្រុមហ៊ុន​ផ្ដល់​​ច្រក​ដែល​បាន​ចុះ​ឈ្មោះ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
@@ -410,7 +410,7 @@
<string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យ​ម្ចាស់​ផ្ញើ​គោលបំណង​​ទៅ​អ្នក​គ្រប់គ្រង​ឧបករណ៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
<string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់​ទៅ​ការ​បញ្ចូល​ទូរទស្សន៍"</string>
<string name="permdesc_bindTvInput" msgid="2371008331852001924">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុចប្រទាក់​កម្រិត​ខ្ពស់​នៃ​ការ​បញ្ចូល​ទូរទស្សន៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</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>
@@ -422,9 +422,9 @@
<string name="permdesc_signalPersistentProcesses" msgid="4896992079182649141">"ឲ្យ​កម្មវិធី​ស្នើ​​សញ្ញា​ដែល​បាន​ផ្ដល់​ត្រូវ​ផ្ញើ​ទៅ​ដំណើរការ​ស្ថិតស្ថេរ​​ទាំង​អស់។"</string>
<string name="permlab_persistentActivity" msgid="8841113627955563938">"ធ្វើ​ឲ្យ​កម្មវិធី​ដំណើរការ​ជា​និច្ច"</string>
<string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"ឲ្យ​កម្មវិធី​ធ្វើជា​ផ្នែក​​ស្ថិតស្ថេរ​ដោយ​ខ្លួន​ឯង​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កំណត់​អង្គ​ចងចាំ​ដែល​អាច​ប្រើ​បាន​ចំពោះ​កម្មវិធី​ផ្សេងៗ​ ដោយ​ធ្វើឲ្យ​កុំព្យូទ័រ​បន្ទះ​យឺត។"</string>
- <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យ​កម្មវិធី ធ្វើជា​ផ្នែក​អចិន្ត្រៃយ៍​នៃ​ខ្លួន​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កម្រិត​អង្គ​ចងចាំ​អាច​ប្រើ​បាន​ ដើម្បី​ធ្វើ​ឲ្យ​កម្មវិធី​ផ្សេង​ធ្វើ​ឲ្យ​ទូរស័ព្ទ​របស់​អ្នក​យឺត។"</string>
+ <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"ឲ្យ​កម្មវិធី ធ្វើជា​ផ្នែក​អចិន្ត្រៃយ៍​នៃ​ខ្លួន​ក្នុង​អង្គ​ចងចាំ។ វា​អាច​កម្រិត​អង្គ​ចងចាំ​អាច​ប្រើ​បាន​ ដើម្បី​ធ្វើ​ឲ្យ​កម្មវិធី​ផ្សេង​ធ្វើ​ឲ្យ​ទូរស័ព្ទ​របស់​អ្នក​យឺត។​"</string>
<string name="permlab_deletePackages" msgid="184385129537705938">"លុប​កម្មវិធី"</string>
- <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យ​កម្មវិធី​លុប​កញ្ចប់ Android ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប​កម្មវិធី​សំខាន់​ៗ។"</string>
+ <string name="permdesc_deletePackages" msgid="7411480275167205081">"ឲ្យ​កម្មវិធី​លុប​កញ្ចប់ Android ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប​កម្មវិធី​សំខាន់​ៗ។ ​"</string>
<string name="permlab_clearAppUserData" msgid="274109191845842756">"លុប​ទិន្នន័យ​របស់​​កម្មវិធី​ផ្សេង"</string>
<string name="permdesc_clearAppUserData" msgid="4625323684125459488">"ឲ្យ​កម្មវិធី​សម្អាត​ទិន្នន័យ​អ្នក​ប្រើ។"</string>
<string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"លុប​ឃ្លាំង​សម្ងាត់​កម្មវិធី​ផ្សេងៗ"</string>
@@ -475,7 +475,7 @@
<string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​កុំព្យូទ័រ​បន្ទះ រួមមាន​ប្រេកង់​​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​ទាក់ទង​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់ទំនង​ជាក់លាក់។ សិទ្ធិ​​នេះ​អនុញ្ញាត​ឲ្យ​​​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង​របស់​អ្នក។"</string>
<string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"ឲ្យ​កម្មវិធី​កែ​ទិន្នន័យ​អំពី​ទំនាក់ទំនង​របស់​អ្នក​ដែល​បាន​រក្សាទុក​ក្នុង​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ប្រេកង់​ដែល​អ្នក​បាន​ហៅ អ៊ីមែល ឬ​បាន​ទាក់ទង​​តាម​វិធី​ផ្សេងៗ​ជា​មួយ​ទំនាក់​ទំនាក់​ជាក់លាក់។ សិទ្ធិ​នេះ​ឲ្យ​កម្មវិធី​លុប​ទិន្នន័យ​ទំនាក់ទំនង។"</string>
<string name="permlab_readCallLog" msgid="3478133184624102739">"អាន​​កំណត់​ហេតុ​​​ហៅ"</string>
- <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យ​កម្មវិធី​អាន​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នក​ដឹង។"</string>
+ <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"ឲ្យ​កម្មវិធី​អាន​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នក​ដឹង។​"</string>
<string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"ឲ្យ​កម្មវិធី​អាន​​​បញ្ជី​ហៅ​ទូរស័ព្ទ​របស់​អ្នក រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។ សិទ្ធិ​នេះ​អនុញ្ញាត​ឲ្យ​កម្មវិធី​រក្សាទុក​ទិន្នន័យ​បញ្ជី​ហៅ​របស់​អ្នក ហើយ​កម្មវិធី​ព្យាបាទ​អាច​ចែករំលែក​ទិន្នន័យ​បញ្ជី​ហៅ​ដោយ​មិន​ឲ្យ​អ្នកដឹង។"</string>
<string name="permlab_writeCallLog" msgid="8552045664743499354">"សរសេរ​បញ្ជី​ហៅ"</string>
<string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"ឲ្យ​កម្មវិធី​កែ​បញ្ជី​ហៅ​កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក​រួមមាន​ទិន្នន័យ​អំពី​ការ​ហៅ​ចូល និង​ចេញ។​កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា ដើម្បី​លុប ឬ​កែ​បញ្ជី​ហៅ​របស់​អ្នក។"</string>
@@ -609,7 +609,7 @@
<string name="permdesc_setWallpaperHints" msgid="8235784384223730091">"ឲ្យ​កម្មវិធី​កំណត់​ជំនួយ​ទំហំ​ផ្ទាំង​រូបភាព​ប្រព័ន្ធ។"</string>
<string name="permlab_masterClear" msgid="2315750423139697397">"កំណត់​ប្រព័ន្ធ​ទៅ​លំនាំដើម​រោងចក្រ​ឡើងវិញ"</string>
<string name="permdesc_masterClear" msgid="3665380492633910226">"ឲ្យ​កម្មវិធី​កំណត់​ប្រព័ន្ធ​​ដូច​ការ​កំណត់​ចេញ​ពី​រោងចក្រ​ឡើងវិញ​ពេញលេញ ដោយ​លុប​ទិន្នន័យ ការ​កំណត់​រចនាសម្ព័ន្ធ និង​កម្មវិធី​បាន​ដំឡើង។"</string>
- <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់​​ម៉ោង"</string>
+ <string name="permlab_setTime" msgid="2021614829591775646">"កំណត់​​ម៉ោង​"</string>
<string name="permdesc_setTime" product="tablet" msgid="1896341438151152881">"ឲ្យ​កម្មវិធី​ប្ដូរ​ម៉ោង​កុំព្យូទ័រ​បន្ទះ។"</string>
<string name="permdesc_setTime" product="default" msgid="1855702730738020">"ឲ្យ​កម្មវិធី​ប្ដូរ​ម៉ោង​ទូរស័ព្ទ។"</string>
<string name="permlab_setTimeZone" msgid="2945079801013077340">"កំណត់​តំបន់​ពេលវេលា"</string>
@@ -775,7 +775,7 @@
<string-array name="organizationTypes">
<item msgid="7546335612189115615">"កន្លែង​ធ្វើការ"</item>
<item msgid="4378074129049520373">"ផ្សេងៗ"</item>
- <item msgid="3455047468583965104">"តាម​តម្រូវ​ការ"</item>
+ <item msgid="3455047468583965104">"តាម​តម្រូវ​ការ​"</item>
</string-array>
<string-array name="imProtocols">
<item msgid="8595261363518459565">"AIM"</item>
@@ -791,7 +791,7 @@
<string name="phoneTypeHome" msgid="2570923463033985887">"ផ្ទះ"</string>
<string name="phoneTypeMobile" msgid="6501463557754751037">"​ចល័ត"</string>
<string name="phoneTypeWork" msgid="8863939667059911633">"កន្លែង​ធ្វើការ"</string>
- <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារ​កន្លែង​ធ្វើការ"</string>
+ <string name="phoneTypeFaxWork" msgid="3517792160008890912">"ទូរសារ​កន្លែង​ធ្វើការ​"</string>
<string name="phoneTypeFaxHome" msgid="2067265972322971467">"ទូរសារ​ផ្ទះ"</string>
<string name="phoneTypePager" msgid="7582359955394921732">"ភេយ័រ"</string>
<string name="phoneTypeOther" msgid="1544425847868765990">"ផ្សេងៗ"</string>
@@ -916,7 +916,7 @@
<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>
+ <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"ពាក្យសម្ងាត់​"</string>
<string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"ចូល"</string>
<string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
<string name="lockscreen_glogin_account_recovery_hint" msgid="1696924763690379073">"ភ្លេច​ឈ្មោះ​អ្នក​ប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
@@ -961,7 +961,7 @@
<string name="factorytest_failed" msgid="5410270329114212041">"បាន​បរាជ័យ​ក្នុង​ការ​សាកល្បង​រោងចក្រ"</string>
<string name="factorytest_not_system" msgid="4435201656767276723">"សកម្មភាព FACTORY_TEST ត្រូវ​បាន​គាំទ្រ​សម្រាប់​តែ​កញ្ចប់​បាន​ដំឡើង​ក្នុង /system/app."</string>
<string name="factorytest_no_action" msgid="872991874799998561">"រក​មិន​ឃើញ​កញ្ចប់​ដែល​ផ្ដល់​សកម្មភាព FACTORY_TEST ។"</string>
- <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់​ផ្ដើម​ឡើង​វិញ"</string>
+ <string name="factorytest_reboot" msgid="6320168203050791643">"ចាប់​ផ្ដើម​ឡើង​វិញ​"</string>
<string name="js_dialog_title" msgid="1987483977834603872">"ទំព័រ​មាន​ចំណងជើង \"<xliff:g id="TITLE">%s</xliff:g>\" សរសេរ៖"</string>
<string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
<string name="js_dialog_before_unload_title" msgid="2619376555525116593">"បញ្ជាក់​ការ​រុករក"</string>
@@ -1019,7 +1019,7 @@
<string name="prepend_shortcut_label" msgid="2572214461676015642">"ម៉ឺនុយ +"</string>
<string name="menu_space_shortcut_label" msgid="2410328639272162537">"ដកឃ្លា"</string>
<string name="menu_enter_shortcut_label" msgid="2743362785111309668">"enter"</string>
- <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប"</string>
+ <string name="menu_delete_shortcut_label" msgid="3658178007202748164">"លុប​"</string>
<string name="search_go" msgid="8298016669822141719">"ស្វែងរក"</string>
<string name="searchview_description_search" msgid="6749826639098512120">"ស្វែងរក"</string>
<string name="searchview_description_query" msgid="5911778593125355124">"ស្វែងរក​សំណួរ"</string>
@@ -1103,18 +1103,18 @@
<string name="preposition_for_date" msgid="9093949757757445117">"នៅ <xliff:g id="DATE">%s</xliff:g>"</string>
<string name="preposition_for_time" msgid="5506831244263083793">"នៅ​ម៉ោង <xliff:g id="TIME">%s</xliff:g>"</string>
<string name="preposition_for_year" msgid="5040395640711867177">"ក្នុង​ឆ្នាំ <xliff:g id="YEAR">%s</xliff:g>"</string>
- <string name="day" msgid="8144195776058119424">"ថ្ងៃ"</string>
+ <string name="day" msgid="8144195776058119424">"ថ្ងៃ​"</string>
<string name="days" msgid="4774547661021344602">"​ថ្ងៃ"</string>
<string name="hour" msgid="2126771916426189481">"ម៉ោង"</string>
<string name="hours" msgid="894424005266852993">"ម៉ោង"</string>
- <string name="minute" msgid="9148878657703769868">"នាទី"</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>
+ <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="other" msgid="1886107766577166786">"<xliff:g id="COUNT">%d</xliff:g> វិនាទី"</item>
@@ -1130,12 +1130,12 @@
<string name="VideoView_error_title" msgid="3534509135438353077">"បញ្ហា​វីដេអូ"</string>
<string name="VideoView_error_text_invalid_progressive_playback" msgid="3186670335938670444">"វីដេអូ​នេះ​មិន​ត្រឹមត្រូវ​សម្រាប់​​ចរន្ត​ចូល​ឧបករណ៍​នេះ។"</string>
<string name="VideoView_error_text_unknown" msgid="3450439155187810085">"មិន​អាច​ចាក់​វីដេអូ​នេះ។"</string>
- <string name="VideoView_error_button" msgid="2822238215100679592">"យល់​ព្រម"</string>
+ <string name="VideoView_error_button" msgid="2822238215100679592">"យល់​ព្រម​"</string>
<string name="relative_time" msgid="1818557177829411417">"<xliff:g id="DATE">%1$s</xliff:g>, <xliff:g id="TIME">%2$s</xliff:g>"</string>
<string name="noon" msgid="7245353528818587908">"រសៀល"</string>
<string name="Noon" msgid="3342127745230013127">"រសៀល"</string>
<string name="midnight" msgid="7166259508850457595">"កណ្ដាលអធ្រាត្រ"</string>
- <string name="Midnight" msgid="5630806906897892201">"កណ្ដាល​អធ្រាត្រ"</string>
+ <string name="Midnight" msgid="5630806906897892201">"កណ្ដាល​អធ្រាត្រ​"</string>
<string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
<string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
<string name="selectAll" msgid="6876518925844129331">"ជ្រើស​ទាំងអស់"</string>
@@ -1152,13 +1152,13 @@
<string name="inputMethod" msgid="1653630062304567879">"វិធីសាស្ត្រ​បញ្ចូល"</string>
<string name="editTextMenuTitle" msgid="4909135564941815494">"សកម្មភាព​អត្ថបទ"</string>
<string name="low_internal_storage_view_title" msgid="5576272496365684834">"អស់​ទំហំ​ផ្ទុក"</string>
- <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារ​ប្រព័ន្ធ​មួយ​ចំនួន​អាច​មិន​ដំណើរការ"</string>
+ <string name="low_internal_storage_view_text" msgid="6640505817617414371">"មុខងារ​ប្រព័ន្ធ​មួយ​ចំនួន​អាច​មិន​ដំណើរការ​"</string>
<string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> កំពុង​ដំណើរការ"</string>
<string name="app_running_notification_text" msgid="4653586947747330058">"ប៉ះ​ ដើម្បី​មើល​ព័ត៌មាន​បន្ថែម ឬ​បញ្ឈប់​កម្មវិធី។"</string>
- <string name="ok" msgid="5970060430562524910">"យល់​ព្រម"</string>
- <string name="cancel" msgid="6442560571259935130">"បោះ​បង់"</string>
- <string name="yes" msgid="5362982303337969312">"យល់​ព្រម"</string>
- <string name="no" msgid="5141531044935541497">"បោះ​បង់"</string>
+ <string name="ok" msgid="5970060430562524910">"យល់​ព្រម​"</string>
+ <string name="cancel" msgid="6442560571259935130">"បោះ​បង់​"</string>
+ <string name="yes" msgid="5362982303337969312">"យល់​ព្រម​"</string>
+ <string name="no" msgid="5141531044935541497">"បោះ​បង់​"</string>
<string name="dialog_alert_title" msgid="2049658708609043103">"ប្រយ័ត្ន"</string>
<string name="loading" msgid="7933681260296021180">"កំពុង​ផ្ទុក..."</string>
<string name="capital_on" msgid="1544682755514494298">"បើក"</string>
@@ -1167,7 +1167,7 @@
<string name="whichHomeApplication" msgid="4616420172727326782">"ជ្រើស​កម្មវិធី​ដើម"</string>
<string name="alwaysUse" msgid="4583018368000610438">"ប្រើ​តាម​លំនាំដើម​សម្រាប់​សកម្មភាព​នេះ។"</string>
<string name="clearDefaultHintMsg" msgid="3252584689512077257">"សម្អាត​លំនាំដើម​ក្នុង​ការកំណត់​ប្រព័ន្ធ &gt; កម្មវិធី &gt; ទាញ​យក។"</string>
- <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព"</string>
+ <string name="chooseActivity" msgid="7486876147751803333">"ជ្រើស​សកម្មភាព​​"</string>
<string name="chooseUsbActivity" msgid="6894748416073583509">"ជ្រើស​កម្មវិធី​សម្រាប់​ឧបករណ៍​យូអេសប៊ី"</string>
<string name="noApplications" msgid="2991814273936504689">"គ្មាន​កម្មវិធី​អាច​អនុវត្ត​សកម្មភាព​នេះ។"</string>
<string name="aerr_title" msgid="1905800560317137752"></string>
@@ -1178,7 +1178,7 @@
<string name="anr_activity_process" msgid="5776209883299089767">"សកម្មភាព <xliff:g id="ACTIVITY">%1$s</xliff:g> មិន​ឆ្លើយតប។\n\nតើ​អ្នក​ចង់​បិទ​វា?"</string>
<string name="anr_application_process" msgid="8941757607340481057">"<xliff:g id="APPLICATION">%1$s</xliff:g> មិន​ឆ្លើយតប។ តើ​អ្នក​ចង់​បិទ​វា?"</string>
<string name="anr_process" msgid="6513209874880517125">"ដំណើរការ <xliff:g id="PROCESS">%1$s</xliff:g> មិន​ឆ្លើយតប។ \n\nតើ​អ្នក​ចង់​បិទ​វា​ឬ?"</string>
- <string name="force_close" msgid="8346072094521265605">"យល់​ព្រម"</string>
+ <string name="force_close" msgid="8346072094521265605">"យល់​ព្រម​"</string>
<string name="report" msgid="4060218260984795706">"រាយការណ៍"</string>
<string name="wait" msgid="7147118217226317732">"រង់ចាំ"</string>
<string name="webpage_unresponsive" msgid="3272758351138122503">"ទំព័រ​ក្លាយ​ជា​មិន​ឆ្លើយតប។\n\nតើ​អ្នក​​ចង់​បិទ​វា?"</string>
@@ -1260,19 +1260,19 @@
<string name="sms_short_code_details" msgid="3492025719868078457"><font fgcolor="#ffffb060">"នេះ​អាច​កាត់​លុយ"</font>" លើ​គណនី​ចល័ត​របស់​អ្នក។"</string>
<string name="sms_premium_short_code_details" msgid="5523826349105123687"><font fgcolor="#ffffb060">"វា​នឹង​គិត​ថ្លៃ​សេវាកម្ម​លើ​គណនី​ចល័ត​របស់​អ្នក។"</font></string>
<string name="sms_short_code_confirm_allow" msgid="4458878637111023413">"ផ្ញើ"</string>
- <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះ​បង់"</string>
+ <string name="sms_short_code_confirm_deny" msgid="2927389840209170706">"បោះ​បង់​"</string>
<string name="sms_short_code_remember_choice" msgid="5289538592272218136">"ចងចាំ​ជម្រើស​របស់​ខ្ញុំ"</string>
<string name="sms_short_code_remember_undo_instruction" msgid="4960944133052287484">"អ្នក​អាច​ប្ដូរ​វា​ពេល​ក្រោយ​ក្នុង​ការ​កំណត់ &gt; កម្មវិធី"</string>
<string name="sms_short_code_confirm_always_allow" msgid="3241181154869493368">"អនុញ្ញាត​ជា​និច្ច"</string>
<string name="sms_short_code_confirm_never_allow" msgid="446992765774269673">"កុំ​អនុញ្ញាត"</string>
<string name="sim_removed_title" msgid="6227712319223226185">"បាន​ដក​ស៊ីម​កាត​ចេញ"</string>
- <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញ​ចល័ត​នឹង​ប្រើ​លែង​បាន​រហូត​ដល់​អ្នក​ចាប់ផ្ដើម​ជា​មួយ​ស៊ីម​កាត​ដែល​បា​បញ្ចូល​ត្រឹមត្រូវ។"</string>
+ <string name="sim_removed_message" msgid="2333164559970958645">"បណ្ដាញ​ចល័ត​នឹង​ប្រើ​លែង​បាន​រហូត​ដល់​អ្នក​ចាប់ផ្ដើម​ជា​មួយ​ស៊ីម​កាត​ដែល​បា​បញ្ចូល​ត្រឹមត្រូវ។​"</string>
<string name="sim_done_button" msgid="827949989369963775">"រួចរាល់"</string>
<string name="sim_added_title" msgid="3719670512889674693">"បាន​បន្ថែម​ស៊ីម​កាត"</string>
<string name="sim_added_message" msgid="6599945301141050216">"ចាប់ផ្ដើម​ឧបករណ៍​របស់​អ្នក​ឡើង​វិញ ដើម្បី​ចូល​ដំណើរការ​បណ្ដាញ​ចល័ត។"</string>
<string name="sim_restart_button" msgid="4722407842815232347">"ចាប់ផ្ដើម​ឡើងវិញ"</string>
- <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់​ម៉ោង"</string>
- <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់​កាល​បរិច្ឆេទ"</string>
+ <string name="time_picker_dialog_title" msgid="8349362623068819295">"កំណត់​ម៉ោង​"</string>
+ <string name="date_picker_dialog_title" msgid="5879450659453782278">"កំណត់​កាល​បរិច្ឆេទ​"</string>
<string name="date_time_set" msgid="5777075614321087758">"កំណត់"</string>
<string name="date_time_done" msgid="2507683751759308828">"រួចរាល់"</string>
<string name="perms_new_perm_prefix" msgid="8257740710754301407"><font size="12" fgcolor="#ff33b5e5">"ថ្មី៖ "</font></string>
@@ -1350,7 +1350,7 @@
<string name="permdesc_copyProtectedData" msgid="4390697124288317831">"ឲ្យ​កម្មវិធី​ដក​សេវាកម្ម​នៃ​កម្មវិធី​ផ្ទុក​​លំនាំដើម ដើម្បី​ចម្លង​មាតិកា។​ មិន​សម្រាប់​ប្រើ​ដោយ​កម្មវិធី​លំនាំដើម។"</string>
<string name="permlab_route_media_output" msgid="1642024455750414694">"នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ"</string>
<string name="permdesc_route_media_output" msgid="4932818749547244346">"ឲ្យ​កម្មវិធី​នាំ​ផ្លូវ​លទ្ធផល​មេឌៀ​ទៅ​ឧបករណ៍​​ខាង​ក្រៅ​ផ្សេង។"</string>
- <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូល​ដំណើរការ​ឧបករណ៍​ផ្ទុក​សុវត្ថិភាព"</string>
+ <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"ចូល​ដំណើរការ​ឧបករណ៍​ផ្ទុក​សុវត្ថិភាព​"</string>
<string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"ឲ្យ​កម្មវិធី​ចូល​​ការ​ផ្ទុក​មាន​សុវត្ថិភាព keguard ។"</string>
<string name="permlab_control_keyguard" msgid="172195184207828387">"ពិនិត្យ​ការ​បង្ហាញ និង​លាក់​ការ​ការពារ"</string>
<string name="permdesc_control_keyguard" msgid="3043732290518629061">"ឲ្យ​កម្មវិធី​គ្រប់គ្រង keguard ។"</string>
@@ -1365,7 +1365,7 @@
<string name="ime_action_go" msgid="8320845651737369027">"ទៅ"</string>
<string name="ime_action_search" msgid="658110271822807811">"ស្វែងរក"</string>
<string name="ime_action_send" msgid="2316166556349314424">"ផ្ញើ"</string>
- <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់"</string>
+ <string name="ime_action_next" msgid="3138843904009813834">"បន្ទាប់​"</string>
<string name="ime_action_done" msgid="8971516117910934605">"រួចរាល់"</string>
<string name="ime_action_previous" msgid="1443550039250105948">"មុន"</string>
<string name="ime_action_default" msgid="2840921885558045721">"អនុវត្ត"</string>
@@ -1374,7 +1374,7 @@
<string name="grant_credentials_permission_message_header" msgid="2106103817937859662">"កម្មវិធី​មួយ ឬ​ច្រើន​ដូច​ខាង​ក្រោម​ស្នើ​សិទ្ធិ ដើម្បី​ចូល​គណនី​របស់​អ្នក​ឥឡូវ និង​ពេល​អនាគត។"</string>
<string name="grant_credentials_permission_message_footer" msgid="3125211343379376561">"តើ​អ្នក​ចង់​អនុញ្ញាត​សំណើ​នេះ?"</string>
<string name="grant_permissions_header_text" msgid="6874497408201826708">"ស្នើ​ចូល"</string>
- <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត"</string>
+ <string name="allow" msgid="7225948811296386551">"អនុញ្ញាត​"</string>
<string name="deny" msgid="2081879885755434506">"បដិសេធ"</string>
<string name="permission_request_notification_title" msgid="6486759795926237907">"បាន​ស្នើ​សិទ្ធិ"</string>
<string name="permission_request_notification_with_subtitle" msgid="8530393139639560189">"បាន​ស្នើ​សិទ្ធិ\nសម្រាប់​គណនី <xliff:g id="ACCOUNT">%s</xliff:g> ។"</string>
@@ -1397,12 +1397,12 @@
<string name="no_file_chosen" msgid="6363648562170759465">"គ្មាន​ឯកសារ​បាន​ជ្រើស"</string>
<string name="reset" msgid="2448168080964209908">"កំណត់​ឡើងវិញ"</string>
<string name="submit" msgid="1602335572089911941">"ដាក់​ស្នើ"</string>
- <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បាន​បើក​របៀប​រថយន្ត"</string>
+ <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"បាន​បើក​របៀប​រថយន្ត​"</string>
<string name="car_mode_disable_notification_message" msgid="8035230537563503262">"ប៉ះ​ ដើម្បី​ចេញ​ពី​របៀប​រថយន្ត​។"</string>
<string name="tethered_notification_title" msgid="3146694234398202601">"ភ្ជាប់ ឬ​ហតស្ពត​សកម្ម"</string>
<string name="tethered_notification_message" msgid="6857031760103062982">"ប៉ះ​ ដើម្បី​រៀបចំ។"</string>
<string name="back_button_label" msgid="2300470004503343439">"ថយក្រោយ"</string>
- <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់"</string>
+ <string name="next_button_label" msgid="1080555104677992408">"បន្ទាប់​"</string>
<string name="skip_button_label" msgid="1275362299471631819">"រំលង"</string>
<string name="throttle_warning_notification_title" msgid="4890894267454867276">"ការ​ប្រើ​ទិន្នន័យ​ចល័ត​ខ្ពស់"</string>
<string name="throttle_warning_notification_message" msgid="3340822228599337743">"ប៉ះ​ ដើម្បី​​ស្វែងយល់​បន្ថែម​អំពី​ការ​ប្រើ​​​ទិន្នន័យ​ចល័ត​។"</string>
@@ -1428,7 +1428,7 @@
<string name="media_shared" product="nosdcard" msgid="5830814349250834225">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី​បច្ចុប្បន្ន​កំពុង​ប្រើ​ដោយ​កុំព្យូទ័រ។"</string>
<string name="media_shared" product="default" msgid="5706130568133540435">"បច្ចុប្បន្ន​កាត​អេសឌី​កំពុង​ប្រើ​ដោយ​កុំព្យូទ័រ"</string>
<string name="media_unknown_state" msgid="729192782197290385">"មិន​ស្គាល់​ស្ថានភាព​មេឌៀ​ខាង​ក្រៅ។"</string>
- <string name="share" msgid="1778686618230011964">"ចែក​រំលែក"</string>
+ <string name="share" msgid="1778686618230011964">"ចែក​រំលែក​"</string>
<string name="find" msgid="4808270900322985960">"រក"</string>
<string name="websearch" msgid="4337157977400211589">"ស្វែងរក​តាម​បណ្ដាញ"</string>
<string name="find_next" msgid="5742124618942193978">"រក​បន្ទាប់"</string>
@@ -1444,7 +1444,7 @@
<string name="sync_undo_deletes" msgid="2941317360600338602">"មិន​ធ្វើ​ការ​លុប​វិញ"</string>
<string name="sync_do_nothing" msgid="3743764740430821845">"មិន​ធ្វើអ្វី​ទេ​ឥឡូវ"</string>
<string name="choose_account_label" msgid="5655203089746423927">"ជ្រើស​គណនី"</string>
- <string name="add_account_label" msgid="2935267344849993553">"បន្ថែម​គណនី​ថ្មី"</string>
+ <string name="add_account_label" msgid="2935267344849993553">"បន្ថែម​គណនី​ថ្មី​​"</string>
<string name="add_account_button_label" msgid="3611982894853435874">"បន្ថែម​គណនី"</string>
<string name="number_picker_increment_button" msgid="2412072272832284313">"បង្កើន"</string>
<string name="number_picker_decrement_button" msgid="476050778386779067">"បន្ថយ"</string>
@@ -1463,15 +1463,15 @@
<string name="date_picker_increment_year_button" msgid="6318697384310808899">"បង្កើន​​ឆ្នាំ"</string>
<string name="date_picker_decrement_year_button" msgid="4482021813491121717">"បន្ថយ​ឆ្នាំ"</string>
<string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
- <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់"</string>
+ <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់​"</string>
<string name="keyboardview_keycode_delete" msgid="3337914833206635744">"លុប"</string>
<string name="keyboardview_keycode_done" msgid="1992571118466679775">"រួចរាល់"</string>
<string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ប្ដូរ​របៀប"</string>
<string name="keyboardview_keycode_shift" msgid="2270748814315147690">"Shift"</string>
<string name="keyboardview_keycode_enter" msgid="2985864015076059467">"Enter"</string>
- <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើស​កម្មវិធី"</string>
+ <string name="activitychooserview_choose_application" msgid="2125168057199941199">"ជ្រើស​កម្មវិធី​​"</string>
<string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"មិន​អាច​ចាប់ផ្ដើម <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
- <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែក​ជា​មួយ"</string>
+ <string name="shareactionprovider_share_with" msgid="806688056141131819">"ចែករំលែក​ជា​មួយ​"</string>
<string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"ចែក​រំលែក​ជា​មួយ <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
<string name="content_description_sliding_handle" msgid="415975056159262248">"គ្រប់គ្រង​ការ​រុញ។ ប៉ះ &amp; សង្កត់។"</string>
<string name="description_target_unlock_tablet" msgid="3833195335629795055">"អូស​ ដើម្បី​ដោះ​សោ។"</string>
@@ -1485,7 +1485,7 @@
<string name="storage_internal" msgid="4891916833657929263">"ឧបករណ៍​ផ្ទុក​ខាង​ក្នុង"</string>
<string name="storage_sd_card" msgid="3282948861378286745">"កាត​អេសឌី"</string>
<string name="storage_usb" msgid="3017954059538517278">"ឧបករណ៍​ផ្ទុក​យូអេសប៊ី"</string>
- <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល"</string>
+ <string name="extract_edit_menu_button" msgid="8940478730496610137">"កែសម្រួល​"</string>
<string name="data_usage_warning_title" msgid="1955638862122232342">"ការព្រមាន​ប្រើ​ទិន្នន័យ"</string>
<string name="data_usage_warning_body" msgid="2814673551471969954">"ប៉ះ ដើម្បី​មើល​ការ​ប្រើ និង​ការ​កំណត់។"</string>
<string name="data_usage_3g_limit_title" msgid="7093334419518706686">"បាន​បិទ​ទិន្នន័យ 2G​-3G"</string>
@@ -1542,7 +1542,7 @@
<string name="media_route_status_available" msgid="6983258067194649391">"ទំនេរ"</string>
<string name="media_route_status_not_available" msgid="6739899962681886401">"មិន​ទំនេរ"</string>
<string name="media_route_status_in_use" msgid="4533786031090198063">"កំពុង​ប្រើ"</string>
- <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់​ជាប់"</string>
+ <string name="display_manager_built_in_display_name" msgid="2583134294292563941">"អេក្រង់​ជាប់​"</string>
<string name="display_manager_hdmi_display_name" msgid="1555264559227470109">"អេក្រង់ HDMI"</string>
<string name="display_manager_overlay_display_name" msgid="5142365982271620716">"#<xliff:g id="ID">%1$d</xliff:g> ត្រួត​គ្នា"</string>
<string name="display_manager_overlay_display_title" msgid="652124517672257172">"<xliff:g id="NAME">%1$s</xliff:g>: <xliff:g id="WIDTH">%2$d</xliff:g>x<xliff:g id="HEIGHT">%3$d</xliff:g>, <xliff:g id="DPI">%4$d</xliff:g> dpi"</string>
@@ -1574,7 +1574,7 @@
<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>
+ <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់​"</string>
<string name="kg_login_submit_button" msgid="5355904582674054702">"ចូល"</string>
<string name="kg_login_invalid_input" msgid="5754664119319872197">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ភ្លេច​ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
@@ -1683,7 +1683,7 @@
<string name="mediasize_japanese_you4" msgid="2091777168747058008">"You4"</string>
<string name="mediasize_unknown_portrait" msgid="3088043641616409762">"​មិន​ស្គាល់​បញ្ឈរ"</string>
<string name="mediasize_unknown_landscape" msgid="4876995327029361552">"មិន​ស្គាល់​ទេសភាព"</string>
- <string name="write_fail_reason_cancelled" msgid="7091258378121627624">"បាន​បោះ​បង់"</string>
+ <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="reason_service_unavailable" msgid="7824008732243903268">"មិន​បា​ន​បើក​សេវាកម្ម​បោះពុម្ព"</string>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 71f55fb..3b275a5 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -1695,7 +1695,7 @@
<string name="restr_pin_enter_old_pin" msgid="1462206225512910757">"PIN ປະ​ຈຸ​ບັນ"</string>
<string name="restr_pin_enter_new_pin" msgid="5959606691619959184">"ລະຫັດ PIN ໃໝ່"</string>
<string name="restr_pin_confirm_pin" msgid="8501523829633146239">"ຢືນຢັນລະຫັດ PIN ໃໝ່"</string>
- <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາ​ລັບ​ການ​ປັບ​ປຸງ​ຂໍ້ຈໍາ​ກັດ"</string>
+ <string name="restr_pin_create_pin" msgid="8017600000263450337">"ສ້າງ PIN ສໍາ​ລັບ​ການ​ປັບ​ປຸງ​ຂໍ້ຈໍາ​ກັດ​"</string>
<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">
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index f01f10e..1de26c7 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -298,6 +298,189 @@
<item>@drawable/quickcontact_badge_overlay_light</item>
<item>@drawable/quickcontact_badge_overlay_normal_light</item>
<item>@drawable/quickcontact_badge_overlay_pressed_light</item>
+
+ <!-- Quantum assets -->
+ <item>@drawable/ab_share_pack_qntm_alpha</item>
+ <item>@drawable/ab_solid_shadow_qntm_alpha</item>
+ <item>@drawable/btn_cab_done_qntm_alpha</item>
+ <item>@drawable/btn_check_to_off_qntm_000</item>
+ <item>@drawable/btn_check_to_off_qntm_001</item>
+ <item>@drawable/btn_check_to_off_qntm_002</item>
+ <item>@drawable/btn_check_to_off_qntm_003</item>
+ <item>@drawable/btn_check_to_off_qntm_004</item>
+ <item>@drawable/btn_check_to_off_qntm_005</item>
+ <item>@drawable/btn_check_to_off_qntm_006</item>
+ <item>@drawable/btn_check_to_off_qntm_007</item>
+ <item>@drawable/btn_check_to_off_qntm_008</item>
+ <item>@drawable/btn_check_to_off_qntm_009</item>
+ <item>@drawable/btn_check_to_off_qntm_010</item>
+ <item>@drawable/btn_check_to_off_qntm_011</item>
+ <item>@drawable/btn_check_to_off_qntm_012</item>
+ <item>@drawable/btn_check_to_off_qntm_013</item>
+ <item>@drawable/btn_check_to_off_qntm_014</item>
+ <item>@drawable/btn_check_to_off_qntm_015</item>
+ <item>@drawable/btn_check_to_on_qntm_000</item>
+ <item>@drawable/btn_check_to_on_qntm_001</item>
+ <item>@drawable/btn_check_to_on_qntm_002</item>
+ <item>@drawable/btn_check_to_on_qntm_003</item>
+ <item>@drawable/btn_check_to_on_qntm_004</item>
+ <item>@drawable/btn_check_to_on_qntm_005</item>
+ <item>@drawable/btn_check_to_on_qntm_006</item>
+ <item>@drawable/btn_check_to_on_qntm_007</item>
+ <item>@drawable/btn_check_to_on_qntm_008</item>
+ <item>@drawable/btn_check_to_on_qntm_009</item>
+ <item>@drawable/btn_check_to_on_qntm_010</item>
+ <item>@drawable/btn_check_to_on_qntm_011</item>
+ <item>@drawable/btn_check_to_on_qntm_012</item>
+ <item>@drawable/btn_check_to_on_qntm_013</item>
+ <item>@drawable/btn_check_to_on_qntm_014</item>
+ <item>@drawable/btn_check_to_on_qntm_015</item>
+ <item>@drawable/btn_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00000_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00001_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00002_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00003_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00004_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00005_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00006_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00007_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00008_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00009_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00010_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00011_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00012_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00013_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00014_qntm_alpha</item>
+ <item>@drawable/btn_radio_anim_00015_qntm_alpha</item>
+ <item>@drawable/btn_radio_to_off_qntm_000</item>
+ <item>@drawable/btn_radio_to_off_qntm_001</item>
+ <item>@drawable/btn_radio_to_off_qntm_002</item>
+ <item>@drawable/btn_radio_to_off_qntm_003</item>
+ <item>@drawable/btn_radio_to_off_qntm_004</item>
+ <item>@drawable/btn_radio_to_off_qntm_005</item>
+ <item>@drawable/btn_radio_to_off_qntm_006</item>
+ <item>@drawable/btn_radio_to_off_qntm_007</item>
+ <item>@drawable/btn_radio_to_off_qntm_008</item>
+ <item>@drawable/btn_radio_to_off_qntm_009</item>
+ <item>@drawable/btn_radio_to_off_qntm_010</item>
+ <item>@drawable/btn_radio_to_off_qntm_011</item>
+ <item>@drawable/btn_radio_to_off_qntm_012</item>
+ <item>@drawable/btn_radio_to_off_qntm_013</item>
+ <item>@drawable/btn_radio_to_off_qntm_014</item>
+ <item>@drawable/btn_radio_to_off_qntm_015</item>
+ <item>@drawable/btn_radio_to_on_qntm_000</item>
+ <item>@drawable/btn_radio_to_on_qntm_001</item>
+ <item>@drawable/btn_radio_to_on_qntm_002</item>
+ <item>@drawable/btn_radio_to_on_qntm_003</item>
+ <item>@drawable/btn_radio_to_on_qntm_004</item>
+ <item>@drawable/btn_radio_to_on_qntm_005</item>
+ <item>@drawable/btn_radio_to_on_qntm_006</item>
+ <item>@drawable/btn_radio_to_on_qntm_007</item>
+ <item>@drawable/btn_radio_to_on_qntm_008</item>
+ <item>@drawable/btn_radio_to_on_qntm_009</item>
+ <item>@drawable/btn_radio_to_on_qntm_010</item>
+ <item>@drawable/btn_radio_to_on_qntm_011</item>
+ <item>@drawable/btn_radio_to_on_qntm_012</item>
+ <item>@drawable/btn_radio_to_on_qntm_013</item>
+ <item>@drawable/btn_radio_to_on_qntm_014</item>
+ <item>@drawable/btn_radio_to_on_qntm_015</item>
+ <item>@drawable/btn_rating_star_off_qntm_alpha</item>
+ <item>@drawable/btn_rating_star_on_qntm_alpha</item>
+ <item>@drawable/btn_star_qntm_alpha</item>
+ <item>@drawable/btn_switch_to_off_qntm_000</item>
+ <item>@drawable/btn_switch_to_off_qntm_001</item>
+ <item>@drawable/btn_switch_to_off_qntm_002</item>
+ <item>@drawable/btn_switch_to_off_qntm_003</item>
+ <item>@drawable/btn_switch_to_off_qntm_004</item>
+ <item>@drawable/btn_switch_to_off_qntm_005</item>
+ <item>@drawable/btn_switch_to_off_qntm_006</item>
+ <item>@drawable/btn_switch_to_off_qntm_007</item>
+ <item>@drawable/btn_switch_to_off_qntm_008</item>
+ <item>@drawable/btn_switch_to_off_qntm_009</item>
+ <item>@drawable/btn_switch_to_off_qntm_010</item>
+ <item>@drawable/btn_switch_to_off_qntm_011</item>
+ <item>@drawable/btn_switch_to_off_qntm_012</item>
+ <item>@drawable/btn_switch_to_off_qntm_013</item>
+ <item>@drawable/btn_switch_to_off_qntm_014</item>
+ <item>@drawable/btn_switch_to_on_qntm_000</item>
+ <item>@drawable/btn_switch_to_on_qntm_001</item>
+ <item>@drawable/btn_switch_to_on_qntm_002</item>
+ <item>@drawable/btn_switch_to_on_qntm_003</item>
+ <item>@drawable/btn_switch_to_on_qntm_004</item>
+ <item>@drawable/btn_switch_to_on_qntm_005</item>
+ <item>@drawable/btn_switch_to_on_qntm_006</item>
+ <item>@drawable/btn_switch_to_on_qntm_007</item>
+ <item>@drawable/btn_switch_to_on_qntm_008</item>
+ <item>@drawable/btn_switch_to_on_qntm_009</item>
+ <item>@drawable/btn_switch_to_on_qntm_010</item>
+ <item>@drawable/btn_switch_to_on_qntm_011</item>
+ <item>@drawable/btn_switch_to_on_qntm_012</item>
+ <item>@drawable/btn_switch_to_on_qntm_013</item>
+ <item>@drawable/btn_switch_to_on_qntm_014</item>
+ <item>@drawable/btn_toggle_indicator_qntm_alpha</item>
+ <item>@drawable/btn_toggle_qntm_alpha</item>
+ <item>@drawable/expander_close_qntm_alpha</item>
+ <item>@drawable/expander_open_qntm_alpha</item>
+ <item>@drawable/fastscroll_thumb_qntm_alpha</item>
+ <item>@drawable/fastscroll_track_qntm_alpha</item>
+ <item>@drawable/ic_ab_back_qntm_am_alpha</item>
+ <item>@drawable/ic_cab_done_qntm_alpha</item>
+ <item>@drawable/ic_clear_qntm_alpha</item>
+ <item>@drawable/ic_commit_search_api_qntm_alpha</item>
+ <item>@drawable/ic_dialog_alert_qntm_alpha</item>
+ <item>@drawable/ic_find_next_qntm_alpha</item>
+ <item>@drawable/ic_find_previous_qntm_alpha</item>
+ <item>@drawable/ic_go_search_api_qntm_alpha</item>
+ <item>@drawable/ic_media_route_disabled_qntm_alpha</item>
+ <item>@drawable/ic_media_route_off_qntm_alpha</item>
+ <item>@drawable/ic_media_route_on_0_qntm_alpha</item>
+ <item>@drawable/ic_media_route_on_1_qntm_alpha</item>
+ <item>@drawable/ic_media_route_on_2_qntm_alpha</item>
+ <item>@drawable/ic_media_route_on_qntm_alpha</item>
+ <item>@drawable/ic_menu_copy_qntm_am_alpha</item>
+ <item>@drawable/ic_menu_cut_qntm_alpha</item>
+ <item>@drawable/ic_menu_find_qntm_alpha</item>
+ <item>@drawable/ic_menu_moreoverflow_qntm_alpha</item>
+ <item>@drawable/ic_menu_paste_qntm_am_alpha</item>
+ <item>@drawable/ic_menu_search_qntm_alpha</item>
+ <item>@drawable/ic_menu_selectall_qntm_alpha</item>
+ <item>@drawable/ic_menu_share_qntm_alpha</item>
+ <item>@drawable/ic_search_api_qntm_alpha</item>
+ <item>@drawable/ic_voice_search_api_qntm_alpha</item>
+ <item>@drawable/list_divider_qntm_alpha</item>
+ <item>@drawable/list_section_divider_qntm_alpha</item>
+ <item>@drawable/popup_background_qntm_mult</item>
+ <item>@drawable/progress_primary_qntm_alpha</item>
+ <item>@drawable/progress_qntm_alpha</item>
+ <item>@drawable/scrollbar_handle_qntm_alpha</item>
+ <item>@drawable/scrubber_control_from_pressed_qntm_000</item>
+ <item>@drawable/scrubber_control_from_pressed_qntm_001</item>
+ <item>@drawable/scrubber_control_from_pressed_qntm_002</item>
+ <item>@drawable/scrubber_control_from_pressed_qntm_003</item>
+ <item>@drawable/scrubber_control_from_pressed_qntm_004</item>
+ <item>@drawable/scrubber_control_from_pressed_qntm_005</item>
+ <item>@drawable/scrubber_control_off_pressed_qntm_alpha</item>
+ <item>@drawable/scrubber_control_off_qntm_alpha</item>
+ <item>@drawable/scrubber_control_on_pressed_qntm_alpha</item>
+ <item>@drawable/scrubber_control_on_qntm_alpha</item>
+ <item>@drawable/scrubber_control_to_pressed_qntm_000</item>
+ <item>@drawable/scrubber_control_to_pressed_qntm_001</item>
+ <item>@drawable/scrubber_control_to_pressed_qntm_002</item>
+ <item>@drawable/scrubber_control_to_pressed_qntm_003</item>
+ <item>@drawable/scrubber_control_to_pressed_qntm_004</item>
+ <item>@drawable/scrubber_control_to_pressed_qntm_005</item>
+ <item>@drawable/scrubber_primary_qntm_alpha</item>
+ <item>@drawable/scrubber_track_qntm_alpha</item>
+ <item>@drawable/spinner_qntm_am_alpha</item>
+ <item>@drawable/switch_track_qntm_alpha</item>
+ <item>@drawable/text_cursor_qntm_alpha</item>
+ <item>@drawable/textfield_activated_qntm_alpha</item>
+ <item>@drawable/textfield_default_qntm_alpha</item>
+ <item>@drawable/textfield_search_activated_qntm_alpha</item>
+ <item>@drawable/textfield_search_default_qntm_alpha</item>
+ <item>@drawable/text_select_handle_left_qntm_alpha</item>
+ <item>@drawable/text_select_handle_middle_qntm_alpha</item>
+ <item>@drawable/text_select_handle_right_qntm_alpha</item>
</array>
<!-- Do not translate. These are all of the color state list resources that should be
@@ -334,6 +517,18 @@
<item>#ff000000</item>
<item>#00000000</item>
<item>#ffffffff</item>
+
+ <!-- Quantum color state lists -->
+ <item>@color/background_cache_hint_selector_quantum_dark</item>
+ <item>@color/background_cache_hint_selector_quantum_light</item>
+ <item>@color/btn_default_quantum_dark</item>
+ <item>@color/btn_default_quantum_light</item>
+ <item>@color/primary_text_disable_only_quantum_dark</item>
+ <item>@color/primary_text_disable_only_quantum_light</item>
+ <item>@color/primary_text_quantum_dark</item>
+ <item>@color/primary_text_quantum_light</item>
+ <item>@color/search_url_text_quantum_dark</item>
+ <item>@color/search_url_text_quantum_light</item>
</array>
<!-- Used in LocalePicker -->
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 489adb4..3b6c1bd 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -963,17 +963,15 @@
<eat-comment />
<!-- The primary branding color for the app. By default, this is the color applied to the
- action bar background and framework controls (via colorControlActivated). -->
+ action bar background. -->
<attr name="colorPrimary" format="color" />
<!-- Dark variant of the primary branding color. By default, this is the color applied to
the status bar (via statusBarColor) and navigation bar (via navigationBarColor). -->
<attr name="colorPrimaryDark" format="color" />
- <!-- Light variant of the primary branding color. TODO: Not used? -->
- <attr name="colorPrimaryLight" format="color" />
-
- <!-- Bright complement to the primary branding color. TODO: Not used? -->
+ <!-- Bright complement to the primary branding color. By default, this is the color applied
+ to framework controls (via colorControlActivated). -->
<attr name="colorAccent" format="color" />
<!-- The color applied to framework controls in their normal state. -->
@@ -982,7 +980,7 @@
<!-- The color applied to framework controls in their activated (ex. checked) state. -->
<attr name="colorControlActivated" format="color" />
- <!-- The color applied to framework control highlights (ex. ripples, selection). -->
+ <!-- The color applied to framework control highlights (ex. ripples, list selectors). -->
<attr name="colorControlHighlight" format="color" />
<!-- The color applied to framework buttons in their normal state. -->
@@ -4564,6 +4562,16 @@
<attr name="drawable" />
</declare-styleable>
+ <!-- Drawable used to render the Quantum progress indicator. -->
+ <declare-styleable name="QuantumProgressDrawable">
+ <attr name="visible" />
+ <attr name="thickness" />
+ <attr name="innerRadius" />
+ <attr name="width" />
+ <attr name="height" />
+ <attr name="color" />
+ </declare-styleable>
+
<declare-styleable name="InsetDrawable">
<attr name="visible" />
<attr name="drawable" />
@@ -4806,6 +4814,8 @@
<attr name="scaleX" />
<!-- The amount to scale the group on X coordinate -->
<attr name="scaleY" />
+ <!-- The alpha of the group (0 is transparent and 1 is opaque) -->
+ <attr name="alpha" />
</declare-styleable>
<!-- Defines the path used in Vector Drawables. -->
@@ -6717,6 +6727,19 @@
<!-- Used as a filter array on the theme to pull out only the EdgeEffect-relevant bits. -->
<declare-styleable name="EdgeEffect">
- <attr name="colorPrimaryLight" />
+ <attr name="colorPrimary" />
+ </declare-styleable>
+
+ <!-- Use <code>tv-input</code> as the root tag of the XML resource that describes an
+ {@link android.media.tv.TvInputService}, which is referenced from its
+ {@link android.media.tv.TvInputService#SERVICE_META_DATA} meta-data entry.
+ Described here are the attributes that can be included in that tag. -->
+ <declare-styleable name="TvInputService">
+ <!-- Component name of an activity for setup of this service.
+ The setup includes scanning channels and registering EPG data. -->
+ <attr name="setupActivity" format="string" />
+ <!-- Component name of an activity that allows the user to modify
+ the settings for this service. -->
+ <attr name="settingsActivity" />
</declare-styleable>
</resources>
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index 976930c..f49861a 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -16,20 +16,20 @@
<!-- Colors specific to Quantum themes. -->
<resources>
- <color name="background_quantum_dark">#ff414042</color>
- <color name="background_quantum_light">#fff1f2f2</color>
+ <color name="background_quantum_dark">#ff212121</color>
+ <color name="background_quantum_light">#fffafafa</color>
- <color name="ripple_quantum_dark">#30ffffff</color>
- <color name="ripple_quantum_light">#30000000</color>
+ <color name="ripple_quantum_light">#20444444</color>
+ <color name="ripple_quantum_dark">#20ffffff</color>
<color name="button_quantum_dark">#ff5a595b</color>
<color name="button_quantum_light">#ffd6d7d7</color>
<color name="bright_foreground_quantum_dark">@color/white</color>
<color name="bright_foreground_quantum_light">@color/black</color>
- <!-- TODO: This is 50% alpha black -->
+ <!-- Black 50% -->
<color name="bright_foreground_disabled_quantum_dark">#80000000</color>
- <!-- TODO: This is 50% alpha white -->
+ <!-- White 50% -->
<color name="bright_foreground_disabled_quantum_light">#80ffffff</color>
<color name="bright_foreground_inverse_quantum_dark">@color/bright_foreground_quantum_light</color>
<color name="bright_foreground_inverse_quantum_light">@color/bright_foreground_quantum_dark</color>
@@ -41,10 +41,27 @@
<color name="hint_foreground_quantum_dark">@color/bright_foreground_disabled_quantum_dark</color>
<color name="hint_foreground_quantum_light">@color/bright_foreground_disabled_quantum_light</color>
- <!-- TODO: This is 40% alpha teal_A200 -->
- <color name="highlighted_text_quantum_dark">#660097a7</color>
- <!-- TODO: This is 40% alpha teal_A200 -->
- <color name="highlighted_text_quantum_light">#660097a7</color>
+ <!-- TODO: This is 40% alpha on the default accent color. -->
+ <color name="highlighted_text_quantum_dark">#6640c4ff</color>
+ <!-- TODO: This is 40% alpha on the default accent color. -->
+ <color name="highlighted_text_quantum_light">#6640c4ff</color>
+
+ <!-- Text & foreground colors -->
+ <eat-comment />
+
+ <!-- Black 87% -->
+ <color name="primary_text_default_quantum_light">#de000000</color>
+ <!-- Black 54% -->
+ <color name="secondary_text_quantum_light">#8a000000</color>
+ <!-- Black 54% (TODO: same as secondary?) -->
+ <color name="tertiary_text_quantum_light">#8a000000</color>
+
+ <!-- White 87% -->
+ <color name="primary_text_default_quantum_dark">#deffffff</color>
+ <!-- White 38% -->
+ <color name="secondary_text_quantum_dark">#61ffffff</color>
+ <!-- White 38% (TODO: same as secondary?) -->
+ <color name="tertiary_text_quantum_dark">#61ffffff</color>
<!-- Primary & accent colors -->
<eat-comment />
@@ -63,6 +80,8 @@
<color name="quantum_blue_A200">#ff448aff</color>
<color name="quantum_blue_A400">#ff2979ff</color>
+ <color name="quantum_light_blue_A200">#ff40c4ff</color>
+
<color name="quantum_teal_100">#ffb2ebf2</color>
<color name="quantum_teal_300">#ff4dd0e1</color>
<color name="quantum_teal_500">#ff00bcd4</color>
@@ -112,27 +131,33 @@
<color name="quantum_grey_100">#fff5f5f5</color>
<color name="quantum_grey_300">#ffeeeeee</color>
<color name="quantum_grey_500">#ffa3a3a3</color>
+ <color name="quantum_grey_600">#ff757575</color>
<color name="quantum_grey_700">#ff717171</color>
+ <color name="quantum_grey_900">#ff212121</color>
<color name="quantum_blue_grey_50">#ffeceff1</color>
<color name="quantum_blue_grey_100">#ffcfd8dc</color>
<color name="quantum_blue_grey_300">#ff90a4ae</color>
+ <color name="quantum_blue_grey_400">#ff78909c</color>
<color name="quantum_blue_grey_500">#ff607d8b</color>
+ <color name="quantum_blue_grey_600">#ff546e7a</color>
<color name="quantum_blue_grey_700">#ff455a64</color>
+ <color name="quantum_blue_grey_800">#ff37474f</color>
+ <color name="quantum_blue_grey_900">#ff263238</color>
<color name="quantum_brown_100">#ffd7ccc8</color>
<color name="quantum_brown_300">#ffa1887f</color>
<color name="quantum_brown_500">#ff795548</color>
<color name="quantum_brown_700">#ff5d4037</color>
- <!-- Text & foreground colors -->
+ <!-- Time picker defaults when no theme is set -->
<eat-comment />
- <color name="primary_text_default_quantum_light">#de000000</color>
- <color name="secondary_text_quantum_light">#8a000000</color>
- <color name="tertiary_text_quantum_light">#4d000000</color>
-
- <color name="primary_text_default_quantum_dark">#deffffff</color>
- <color name="secondary_text_quantum_dark">#8affffff</color>
- <color name="tertiary_text_quantum_dark">#4dffffff</color>
+ <color name="timepicker_default_background_quantum">@color/primary_text_default_quantum_light</color>
+ <color name="timepicker_default_text_color_quantum">@color/black</color>
+ <color name="timepicker_default_disabled_color_quantum">@color/bright_foreground_disabled_quantum_dark</color>
+ <color name="timepicker_default_ampm_selected_background_color_quantum">@color/quantum_light_blue_A200</color>
+ <color name="timepicker_default_ampm_unselected_background_color_quantum">@color/transparent</color>
+ <color name="timepicker_default_selector_color_quantum">@color/quantum_light_blue_A200</color>
+ <color name="timepicker_default_numbers_background_color_quantum">@color/transparent</color>
</resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index f6732d3..8af45db 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -858,6 +858,14 @@
<!-- Boolean indicating if current platform supports BLE peripheral mode -->
<bool name="config_bluetooth_le_peripheral_mode_supported">false</bool>
+ <!-- Max number of scan filters supported by blutooth controller. 0 if the
+ device does not support hardware scan filters-->
+ <integer translatable="false" name="config_bluetooth_max_scan_filters">0</integer>
+
+ <!-- Max number of advertisers supported by bluetooth controller. 0 if the
+ device does not support multiple advertisement-->
+ <integer translatable="false" name="config_bluetooth_max_advertisers">0</integer>
+
<!-- The default data-use polling period. -->
<integer name="config_datause_polling_period_sec">600</integer>
diff --git a/core/res/res/values/dimens_quantum.xml b/core/res/res/values/dimens_quantum.xml
index b5ba1ca..6390667 100644
--- a/core/res/res/values/dimens_quantum.xml
+++ b/core/res/res/values/dimens_quantum.xml
@@ -21,10 +21,6 @@
<dimen name="action_bar_default_padding_quantum">4dp</dimen>
<!-- Vertical padding around action bar icons. -->
<dimen name="action_bar_icon_vertical_padding_quantum">16dp</dimen>
- <!-- Text size for action bar titles -->
- <dimen name="action_bar_title_text_size_quantum">20sp</dimen>
- <!-- Text size for action bar subtitles -->
- <dimen name="action_bar_subtitle_text_size_quantum">16sp</dimen>
<!-- Top margin for action bar subtitles -->
<dimen name="action_bar_subtitle_top_margin_quantum">-3dp</dimen>
<!-- Bottom margin for action bar subtitles -->
@@ -57,6 +53,6 @@
<dimen name="floating_window_margin_right">16dp</dimen>
<dimen name="floating_window_margin_bottom">32dp</dimen>
- <!-- the amount of elevation for pressed button state-->
+ <!-- Amount of elevation for pressed button state -->
<dimen name="button_pressed_z">2dp</dimen>
</resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7fc2f49..3b28bff 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2096,6 +2096,7 @@
<public type="attr" name="windowSwipeToDismiss" id="0x10103f3" />
<public type="attr" name="isGame" id="0x10103f4" />
<public type="attr" name="allowEmbedded" id="0x10103f5" />
+ <public type="attr" name="setupActivity" id="0x10103f6"/>
<!-- ===============================================================
Resources added in version 21 of the platform
@@ -2141,7 +2142,6 @@
<public type="attr" name="slideEdge" />
<public type="attr" name="actionBarTheme" />
<public type="attr" name="textAppearanceListItemSecondary" />
- <public type="attr" name="colorPrimaryLight" />
<public type="attr" name="colorPrimary" />
<public type="attr" name="colorPrimaryDark" />
<public type="attr" name="colorAccent" />
@@ -2278,9 +2278,10 @@
<public type="style" name="ThemeOverlay" />
<public type="style" name="ThemeOverlay.Quantum" />
+ <public type="style" name="ThemeOverlay.Quantum.ActionBar" />
<public type="style" name="ThemeOverlay.Quantum.Light" />
<public type="style" name="ThemeOverlay.Quantum.Dark" />
- <public type="style" name="ThemeOverlay.Quantum.ActionBarWidget" />
+ <public type="style" name="ThemeOverlay.Quantum.Dark.ActionBar" />
<public type="style" name="Widget.Quantum" />
<public type="style" name="Widget.Quantum.ActionBar" />
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 8286ef9..391a32c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -419,6 +419,8 @@
current device state, to send as an e-mail message. It will take a little
time from starting the bug report until it is ready to be sent; please be
patient.</string>
+ <!-- Format for build summary info [CHAR LIMIT=NONE] -->
+ <string name="bugreport_status" translatable="false">%s (%s)</string>
<!-- label for item that enables silent mode in phone options dialog -->
<string name="global_action_toggle_silent_mode">Silent mode</string>
@@ -455,10 +457,10 @@
<string name="android_system_label">Android System</string>
<!-- Label for the user owner in the intent forwarding app. -->
- <string name="user_owner_label">Personal</string>
+ <string name="user_owner_label">Personal apps</string>
<!-- Label for a corporate profile in the intent forwarding app. -->
- <string name="managed_profile_label">Work</string>
+ <string name="managed_profile_label">Android for Work</string>
<!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
<string name="permgrouplab_costMoney">Services that cost you money</string>
@@ -1554,6 +1556,12 @@
happen in the background but does not prevent other audio capture (e.g. Camcorder).</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_modifyAudioRouting">Audio Routing</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_modifyAudioRouting">Allows the app to directly control audio routing and
+ override audio policy decisions.</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_captureVideoOutput">capture video output</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_captureVideoOutput">Allows the app to capture and redirect video output.</string>
@@ -3777,6 +3785,11 @@
<!-- Description of an application permission that lets it listen to trust state changes. -->
<string name="permdesc_trust_listener">Allows an application to listen for changes in trust state.</string>
+ <!-- Title of an application permission that lets it provide a trust agent. -->
+ <string name="permlab_provide_trust_agent">Provide a trust agent.</string>
+ <!-- Description of an application permission that lets it provide a trust agent. -->
+ <string name="permdesc_provide_trust_agent">Allows an application to provide a trust agent.</string>
+
<!-- Title of an application permission that lets it bind to a trust agent service. -->
<string name="permlab_bind_trust_agent_service">Bind to a trust agent service</string>
<!-- Description of an application permission that lets it bind to a trust agent service. -->
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index 59bd667..5bd6122 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -1199,6 +1199,7 @@ please see styles_device_defaults.xml.
<item name="android:buttonGravity">top</item>
<item name="android:navigationButtonStyle">@android:style/Widget.Toolbar.Button.Navigation</item>
<item name="android:collapseIcon">?android:attr/homeAsUpIndicator</item>
+ <item name="android:contentInsetStart">16dp</item>
</style>
<style name="Widget.Toolbar.Button.Navigation" parent="@android:style/Widget">
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index 108334f..b5afc2f 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -91,86 +91,105 @@ please see styles_device_defaults.xml.
<!-- Text styles -->
<style name="TextAppearance.Quantum">
- <item name="textColor">?textColorPrimary</item>
- <item name="textColorHint">?textColorHint</item>
- <item name="textColorHighlight">?textColorHighlight</item>
- <item name="textColorLink">?textColorLink</item>
+ <item name="textColor">?attr/textColorPrimary</item>
+ <item name="textColorHint">?attr/textColorHint</item>
+ <item name="textColorHighlight">?attr/textColorHighlight</item>
+ <item name="textColorLink">?attr/textColorLink</item>
<item name="textSize">@dimen/text_size_body_1_quantum</item>
<item name="fontFamily">@string/font_family_body_1_quantum</item>
- <item name="elegantTextHeight">true</item>
</style>
<style name="TextAppearance.Quantum.Display4">
<item name="textSize">@dimen/text_size_display_4_quantum</item>
<item name="fontFamily">@string/font_family_display_4_quantum</item>
- <item name="textColor">?textColorSecondary</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Quantum.Display3">
<item name="textSize">@dimen/text_size_display_3_quantum</item>
<item name="fontFamily">@string/font_family_display_3_quantum</item>
- <item name="textColor">?textColorSecondary</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Quantum.Display2">
<item name="textSize">@dimen/text_size_display_2_quantum</item>
<item name="fontFamily">@string/font_family_display_2_quantum</item>
- <item name="textColor">?textColorSecondary</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Quantum.Display1">
<item name="textSize">@dimen/text_size_display_1_quantum</item>
<item name="fontFamily">@string/font_family_display_1_quantum</item>
- <item name="textColor">?textColorSecondary</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Quantum.Headline">
<item name="textSize">@dimen/text_size_headline_quantum</item>
<item name="fontFamily">@string/font_family_headline_quantum</item>
- <item name="textColor">?textColorPrimary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Quantum.Title">
<item name="textSize">@dimen/text_size_title_quantum</item>
<item name="fontFamily">@string/font_family_title_quantum</item>
- <item name="textColor">?textColorPrimary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Title.Inverse">
+ <item name="textColor">?attr/textColorPrimaryInverse</item>
+ <item name="textColorHint">?attr/textColorHintInverse</item>
+ <item name="textColorHighlight">?attr/textColorHighlightInverse</item>
+ <item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
<style name="TextAppearance.Quantum.Subhead">
<item name="textSize">@dimen/text_size_subhead_quantum</item>
<item name="fontFamily">@string/font_family_subhead_quantum</item>
- <item name="textColor">?textColorPrimary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Subhead.Inverse">
+ <item name="textColor">?attr/textColorSecondaryInverse</item>
+ <item name="textColorHint">?attr/textColorHintInverse</item>
+ <item name="textColorHighlight">?attr/textColorHighlightInverse</item>
+ <item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
<style name="TextAppearance.Quantum.Body2">
<item name="textSize">@dimen/text_size_body_2_quantum</item>
<item name="fontFamily">@string/font_family_body_2_quantum</item>
- <item name="textColor">?textColorPrimary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Quantum.Body1">
<item name="textSize">@dimen/text_size_body_1_quantum</item>
<item name="fontFamily">@string/font_family_body_1_quantum</item>
- <item name="textColor">?textColorPrimary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
</style>
<style name="TextAppearance.Quantum.Caption">
<item name="textSize">@dimen/text_size_caption_quantum</item>
<item name="fontFamily">@string/font_family_caption_quantum</item>
- <item name="textColor">?textColorSecondary</item>
+ <item name="textColor">?attr/textColorSecondary</item>
</style>
<style name="TextAppearance.Quantum.Menu">
<item name="textSize">@dimen/text_size_menu_quantum</item>
<item name="fontFamily">@string/font_family_menu_quantum</item>
- <item name="textColor">?textColorPrimary</item>
+ </style>
+
+ <style name="TextAppearance.Quantum.Menu.Inverse">
+ <item name="textColor">?attr/textColorSecondaryInverse</item>
+ <item name="textColorHint">?attr/textColorHintInverse</item>
+ <item name="textColorHighlight">?attr/textColorHighlightInverse</item>
+ <item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
<style name="TextAppearance.Quantum.Button">
<item name="textSize">@dimen/text_size_button_quantum</item>
<item name="fontFamily">@string/font_family_button_quantum</item>
<item name="textAllCaps">true</item>
- <item name="textColor">?textColorPrimary</item>
+ <item name="textColor">?attr/textColorPrimary</item>
</style>
<!-- Deprecated text styles -->
@@ -218,9 +237,7 @@ please see styles_device_defaults.xml.
<item name="textColorLink">?attr/textColorLinkInverse</item>
</style>
- <style name="TextAppearance.Quantum.SearchResult">
- </style>
-
+ <style name="TextAppearance.Quantum.SearchResult" />
<style name="TextAppearance.Quantum.SearchResult.Title" parent="TextAppearance.Quantum.Title" />
<style name="TextAppearance.Quantum.SearchResult.Subtitle" parent="TextAppearance.Quantum.Subhead" />
@@ -232,116 +249,55 @@ please see styles_device_defaults.xml.
<item name="textColorHint">?attr/textColorHintInverse</item>
</style>
- <style name="TextAppearance.Quantum.Widget.Switch">
- <item name="textSize">14sp</item>
- </style>
+ <style name="TextAppearance.Quantum.Widget.Switch" parent="TextAppearance.Quantum.Button" />
<style name="TextAppearance.Quantum.Widget.PopupMenu"/>
+ <style name="TextAppearance.Quantum.Widget.PopupMenu.Large" parent="TextAppearance.Quantum.Menu" />
+ <style name="TextAppearance.Quantum.Widget.PopupMenu.Small" parent="TextAppearance.Quantum.Menu" />
- <style name="TextAppearance.Quantum.Widget.PopupMenu.Large">
- <item name="fontFamily">@string/font_family_menu_quantum</item>
- <item name="textSize">@dimen/text_size_menu_quantum</item>>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.PopupMenu.Small">
- <item name="fontFamily">@string/font_family_menu_quantum</item>
- <item name="textSize">@dimen/text_size_menu_quantum</item>>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.DropDownHint">
- <item name="fontFamily">@string/font_family_menu_quantum</item>
- <item name="textSize">@dimen/text_size_menu_quantum</item>>
- </style>
+ <style name="TextAppearance.Quantum.Widget.DropDownHint" parent="TextAppearance.Quantum.Menu" />
<style name="TextAppearance.Quantum.Widget.IconMenu.Item" parent="TextAppearance.Quantum.Small">
<item name="textColor">?attr/textColorPrimary</item>
</style>
- <!-- This style is for smaller screens; values-xlarge defines a version
- for larger screens. -->
- <style name="TextAppearance.Quantum.Widget.TabWidget">
- <item name="textSize">14sp</item>
- <item name="textStyle">normal</item>
- <item name="textColor">@color/tab_indicator_text</item>
- </style>
+ <style name="TextAppearance.Quantum.Widget.TabWidget" parent="TextAppearance.Quantum.Button" />
<style name="TextAppearance.Quantum.Widget.TextView">
<item name="textColor">?attr/textColorPrimaryDisableOnly</item>
<item name="textColorHint">?attr/textColorHint</item>
</style>
- <style name="TextAppearance.Quantum.Widget.TextView.PopupMenu">
- <item name="fontFamily">@string/font_family_menu_quantum</item>
- <item name="textSize">@dimen/text_size_menu_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.TextView.SpinnerItem"/>
+ <style name="TextAppearance.Quantum.Widget.TextView.PopupMenu" parent="TextAppearance.Quantum.Menu" />
+ <style name="TextAppearance.Quantum.Widget.TextView.SpinnerItem" />
<style name="TextAppearance.Quantum.Widget.DropDownItem">
<item name="textColor">?attr/textColorPrimaryDisableOnly</item>
</style>
<style name="TextAppearance.Quantum.Widget.ActionMode"/>
+ <style name="TextAppearance.Quantum.Widget.ActionMode.Title" parent="TextAppearance.Quantum.Title" />
+ <style name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Title.Inverse" />
+ <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Subhead" />
+ <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Subhead.Inverse" />
- <style name="TextAppearance.Quantum.Widget.ActionMode.Title" parent="TextAppearance.Quantum.Medium">
- <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.ActionMode.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
- <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle" parent="TextAppearance.Quantum.Small">
- <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
- </style>
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Title" parent="TextAppearance.Quantum.Title" />
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Quantum.Title.Inverse" />
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Subhead" />
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Quantum.Subhead.Inverse" />
- <style name="TextAppearance.Quantum.Widget.ActionMode.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
- <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
- </style>
-
- <!-- Text styles with no light versions -->
-
- <style name="TextAppearance.Quantum.Widget.ActionBar.Title" parent="TextAppearance.Quantum.Medium">
- <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.ActionBar.Title.Inverse" parent="TextAppearance.Quantum.Medium.Inverse">
- <item name="textSize">@dimen/action_bar_title_text_size_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle" parent="TextAppearance.Quantum.Small">
- <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.ActionBar.Subtitle.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
- <item name="textSize">@dimen/action_bar_subtitle_text_size_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Small">
- <item name="fontFamily">@string/font_family_menu_quantum</item>
- <item name="textSize">@dimen/text_size_menu_quantum</item>>
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Menu" parent="TextAppearance.Quantum.Menu">
<item name="textColor">?attr/actionMenuTextColor</item>
<item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
</style>
- <style name="TextAppearance.Quantum.Widget.ActionBar.Menu.Inverse" parent="TextAppearance.Quantum.Small.Inverse">
- <item name="fontFamily">@string/font_family_menu_quantum</item>
- <item name="textSize">@dimen/text_size_menu_quantum</item>>
+ <style name="TextAppearance.Quantum.Widget.ActionBar.Menu.Inverse" parent="TextAppearance.Quantum.Menu.Inverse">
<item name="textColor">?attr/actionMenuTextColor</item>
<item name="textAllCaps">@bool/config_actionMenuItemAllCaps</item>
</style>
- <style name="TextAppearance.Quantum.WindowTitle">
- <item name="textColor">?attr/textColorPrimary</item>
- <item name="fontFamily">@string/font_family_headline_quantum</item>
- <item name="textSize">@dimen/text_size_headline_quantum</item>
- </style>
-
- <style name="TextAppearance.Quantum.DialogWindowTitle">
- <item name="fontFamily">@string/font_family_headline_quantum</item>
- <item name="textSize">@dimen/text_size_headline_quantum</item>
- <item name="textColor">?attr/textColorPrimary</item>
- </style>
+ <style name="TextAppearance.Quantum.WindowTitle" parent="TextAppearance.Quantum.Headline" />
+ <style name="TextAppearance.Quantum.DialogWindowTitle" parent="TextAppearance.Quantum.Headline" />
<style name="TextAppearance.Quantum.CalendarViewWeekDayView" parent="TextAppearance.Quantum.Small">
<item name="textStyle">bold</item>
@@ -554,11 +510,11 @@ please see styles_device_defaults.xml.
<item name="disabledColor">@color/bright_foreground_disabled_quantum_dark</item>
<item name="headerSelectedTextColor">?attr/colorControlActivated</item>
<item name="headerUnselectedTextColor">?attr/textColorPrimary</item>
- <item name="headerBackgroundColor">?attr/colorBackground</item>
+ <item name="headerBackgroundColor">@color/transparent</item>
<item name="numbersTextColor">?attr/textColorSecondary</item>
- <item name="numbersBackgroundColor">?attr/colorControlNormal</item>
+ <item name="numbersBackgroundColor">@color/transparent</item>
<item name="amPmTextColor">?attr/textColorSecondary</item>
- <item name="amPmUnselectedBackgroundColor">?attr/colorControlNormal</item>
+ <item name="amPmUnselectedBackgroundColor">@color/transparent</item>
<item name="amPmSelectedBackgroundColor">?attr/colorControlActivated</item>
<item name="numbersSelectorColor">?attr/colorControlActivated</item>
</style>
@@ -590,7 +546,7 @@ please see styles_device_defaults.xml.
</style>
<style name="Widget.Quantum.ProgressBar" parent="Widget.ProgressBar">
- <item name="indeterminateDrawable">@drawable/progress_medium_holo</item>
+ <item name="indeterminateDrawable">@drawable/progress_medium_quantum</item>
</style>
<style name="Widget.Quantum.ProgressBar.Inverse"/>
@@ -603,14 +559,14 @@ please see styles_device_defaults.xml.
</style>
<style name="Widget.Quantum.ProgressBar.Small" parent="Widget.ProgressBar.Small">
- <item name="indeterminateDrawable">@drawable/progress_small_holo</item>
+ <item name="indeterminateDrawable">@drawable/progress_small_quantum</item>
</style>
<style name="Widget.Quantum.ProgressBar.Small.Inverse"/>
<style name="Widget.Quantum.ProgressBar.Small.Title"/>
<style name="Widget.Quantum.ProgressBar.Large" parent="Widget.ProgressBar.Large">
- <item name="indeterminateDrawable">@drawable/progress_large_holo</item>
+ <item name="indeterminateDrawable">@drawable/progress_large_quantum</item>
</style>
<style name="Widget.Quantum.ProgressBar.Large.Inverse"/>
@@ -782,6 +738,7 @@ please see styles_device_defaults.xml.
<item name="itemPadding">8dip</item>
<item name="homeLayout">@layout/action_bar_home_quantum</item>
<item name="gravity">center_vertical</item>
+ <item name="contentInsetStart">16dp</item>
</style>
<style name="Widget.Quantum.ActionBar.Solid">
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6cd7cd2..41238a3 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -287,6 +287,8 @@
<java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
<java-symbol type="bool" name="config_windowIsRound" />
+ <java-symbol type="integer" name="config_bluetooth_max_advertisers" />
+ <java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
<java-symbol type="integer" name="config_cursorWindowSize" />
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
<java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
@@ -1388,6 +1390,7 @@
<java-symbol type="string" name="android_upgrading_title" />
<java-symbol type="string" name="bugreport_title" />
<java-symbol type="string" name="bugreport_message" />
+ <java-symbol type="string" name="bugreport_status" />
<java-symbol type="string" name="faceunlock_multiple_failures" />
<java-symbol type="string" name="global_action_power_off" />
<java-symbol type="string" name="global_actions_airplane_mode_off_status" />
@@ -1855,10 +1858,6 @@
<java-symbol type="string" name="timepicker_numbers_radius_multiplier_normal" />
<java-symbol type="string" name="timepicker_transition_mid_radius_multiplier" />
<java-symbol type="string" name="timepicker_transition_end_radius_multiplier" />
- <java-symbol type="color" name="timepicker_default_text_color_holo_light" />
- <java-symbol type="color" name="timepicker_default_disabled_color_holo_light" />
- <java-symbol type="color" name="timepicker_default_ampm_unselected_background_color_holo_light" />
- <java-symbol type="color" name="timepicker_default_ampm_selected_background_color_holo_light" />
<java-symbol type="array" name="config_clockTickVibePattern" />
<!-- From various Quantum changes -->
@@ -1870,5 +1869,12 @@
<java-symbol type="id" name="icon_frame" />
<java-symbol type="style" name="Animation.VolumePanel" />
<java-symbol type="transition" name="no_transition" />
+ <java-symbol type="color" name="timepicker_default_text_color_quantum" />
+ <java-symbol type="color" name="timepicker_default_disabled_color_quantum" />
+ <java-symbol type="color" name="timepicker_default_ampm_unselected_background_color_quantum" />
+ <java-symbol type="color" name="timepicker_default_ampm_selected_background_color_quantum" />
+ <java-symbol type="color" name="timepicker_default_selector_color_quantum" />
+ <java-symbol type="color" name="timepicker_default_numbers_background_color_quantum" />
+ <java-symbol type="style" name="TextAppearance.Quantum.TimePicker.TimeLabel" />
</resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 648660b..cb5cb0c 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -55,7 +55,6 @@ please see themes_device_defaults.xml.
<item name="colorPrimaryDark">@color/legacy_primary_dark</item>
<item name="colorPrimary">@color/legacy_primary</item>
- <item name="colorPrimaryLight">@color/legacy_primary_light</item>
<item name="colorControlActivated">@color/legacy_control_activated</item>
<item name="colorControlNormal">@color/legacy_control_normal</item>
<item name="colorControlHighlight">@color/legacy_button_pressed</item>
@@ -454,7 +453,6 @@ please see themes_device_defaults.xml.
<item name="colorPrimaryDark">@color/legacy_light_primary_dark</item>
<item name="colorPrimary">@color/legacy_light_primary</item>
- <item name="colorPrimaryLight">@color/legacy_light_primary_light</item>
<item name="colorControlActivated">@color/legacy_light_control_activated</item>
<item name="colorControlNormal">@color/legacy_light_control_normal</item>
<item name="colorControlHighlight">@color/legacy_light_button_pressed</item>
@@ -969,7 +967,6 @@ please see themes_device_defaults.xml.
<item name="colorPrimaryDark">@color/holo_primary_dark</item>
<item name="colorPrimary">@color/holo_primary</item>
- <item name="colorPrimaryLight">@color/holo_primary_light</item>
<item name="colorControlActivated">@color/holo_control_activated</item>
<item name="colorControlNormal">@color/holo_control_normal</item>
<item name="colorControlHighlight">@color/holo_button_pressed</item>
@@ -1310,7 +1307,6 @@ please see themes_device_defaults.xml.
<item name="colorPrimaryDark">@color/holo_light_primary_dark</item>
<item name="colorPrimary">@color/holo_light_primary</item>
- <item name="colorPrimaryLight">@color/holo_light_primary_light</item>
<item name="colorControlActivated">@color/holo_light_control_activated</item>
<item name="colorControlNormal">@color/holo_light_control_normal</item>
<item name="colorControlHighlight">@color/holo_light_button_pressed</item>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index cdbd771..eda7174 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -164,7 +164,10 @@ please see themes_device_defaults.xml.
<item name="windowDrawsSystemBarBackgrounds">true</item>
<item name="windowActionBarFullscreenDecorLayout">@layout/screen_toolbar</item>
<item name="statusBarColor">?attr/colorPrimaryDark</item>
- <item name="navigationBarColor">?attr/colorPrimaryDark</item>
+ <item name="navigationBarColor">@color/black</item>
+ <item name="windowEnterTransition">@transition/fade</item>
+ <item name="windowSharedElementEnterTransition">@transition/move</item>
+ <item name="windowSharedElementExitTransition">@transition/move</item>
<!-- Dialog attributes -->
<item name="dialogTheme">@style/Theme.Quantum.Dialog</item>
@@ -306,8 +309,8 @@ please see themes_device_defaults.xml.
<item name="actionBarStyle">@style/Widget.Quantum.ActionBar.Solid</item>
<item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
<item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
- <item name="actionBarWidgetTheme">@style/ThemeOverlay.Quantum.ActionBarWidget</item>
- <item name="actionBarTheme">@null</item>
+ <item name="actionBarWidgetTheme">@null</item>
+ <item name="actionBarTheme">@style/ThemeOverlay.Quantum.ActionBar</item>
<item name="actionBarItemBackground">?attr/selectableItemBackgroundBorderless</item>
<item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -371,13 +374,12 @@ please see themes_device_defaults.xml.
<item name="fastScrollOverlayPosition">atThumb</item>
<!-- Color palette -->
- <item name="colorPrimaryDark">@color/quantum_blue_700</item>
- <item name="colorPrimary">@color/quantum_blue_500</item>
- <item name="colorPrimaryLight">@color/quantum_blue_100</item>
- <item name="colorAccent">@color/quantum_teal_A200</item>
+ <item name="colorPrimaryDark">@color/quantum_blue_grey_900</item>
+ <item name="colorPrimary">@color/quantum_blue_grey_800</item>
+ <item name="colorAccent">@color/quantum_light_blue_A200</item>
<item name="colorControlNormal">?attr/textColorSecondary</item>
- <item name="colorControlActivated">?attr/colorPrimary</item>
+ <item name="colorControlActivated">?attr/colorAccent</item>
<item name="colorControlHighlight">@color/ripple_quantum_dark</item>
<item name="colorButtonNormal">@color/btn_default_quantum_dark</item>
@@ -508,7 +510,7 @@ please see themes_device_defaults.xml.
<item name="windowDrawsSystemBarBackgrounds">true</item>
<item name="windowActionBarFullscreenDecorLayout">@layout/screen_toolbar</item>
<item name="statusBarColor">?attr/colorPrimaryDark</item>
- <item name="navigationBarColor">?attr/colorPrimaryDark</item>
+ <item name="navigationBarColor">@color/black</item>
<!-- Dialog attributes -->
<item name="dialogTheme">@style/Theme.Quantum.Light.Dialog</item>
@@ -653,8 +655,8 @@ please see themes_device_defaults.xml.
<item name="actionBarStyle">@style/Widget.Quantum.Light.ActionBar.Solid</item>
<item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
<item name="actionModePopupWindowStyle">@style/Widget.Quantum.Light.PopupWindow.ActionMode</item>
- <item name="actionBarWidgetTheme">@style/ThemeOverlay.Quantum.ActionBarWidget</item>
- <item name="actionBarTheme">@null</item>
+ <item name="actionBarWidgetTheme">@null</item>
+ <item name="actionBarTheme">@style/ThemeOverlay.Quantum.ActionBar</item>
<item name="actionBarItemBackground">?attr/selectableItemBackgroundBorderless</item>
<item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -714,13 +716,12 @@ please see themes_device_defaults.xml.
<item name="fastScrollOverlayPosition">atThumb</item>
<!-- Color palette -->
- <item name="colorPrimaryDark">@color/quantum_blue_700</item>
- <item name="colorPrimary">@color/quantum_blue_500</item>
- <item name="colorPrimaryLight">@color/quantum_blue_100</item>
- <item name="colorAccent">@color/quantum_teal_A200</item>
+ <item name="colorPrimaryDark">@color/quantum_blue_grey_600</item>
+ <item name="colorPrimary">@color/quantum_blue_grey_400</item>
+ <item name="colorAccent">@color/quantum_light_blue_A200</item>
<item name="colorControlNormal">?attr/textColorSecondary</item>
- <item name="colorControlActivated">?attr/colorPrimary</item>
+ <item name="colorControlActivated">?attr/colorAccent</item>
<item name="colorControlHighlight">@color/ripple_quantum_light</item>
<item name="colorButtonNormal">@color/btn_default_quantum_light</item>
@@ -730,8 +731,8 @@ please see themes_device_defaults.xml.
with an inverse color profile. The dark action bar sharply stands out against
the light content. -->
<style name="Theme.Quantum.Light.DarkActionBar">
- <item name="actionBarWidgetTheme">@style/ThemeOverlay.Quantum.ActionBarWidget</item>
- <item name="actionBarTheme">@style/ThemeOverlay.Quantum.Dark</item>
+ <item name="actionBarWidgetTheme">@null</item>
+ <item name="actionBarTheme">@style/ThemeOverlay.Quantum.Dark.ActionBar</item>
</style>
<style name="ThemeOverlay" />
@@ -810,11 +811,17 @@ please see themes_device_defaults.xml.
<item name="colorButtonNormal">@color/btn_default_quantum_dark</item>
</style>
- <!-- Theme overlay that replaces the activated control color (which by default
- is identical to the action bar background color) with the normal control
- color. -->
- <style name="ThemeOverlay.Quantum.ActionBarWidget">
- <item name="colorControlActivated">?attr/colorControlNormal</item>
+ <!-- Theme overlay that replaces the normal control color, which by default is the same as the
+ secondary text color, with the primary text color. -->
+ <style name="ThemeOverlay.Quantum.ActionBar">
+ <item name="colorControlNormal">?attr/textColorPrimary</item>
+ </style>
+
+ <!-- Theme overlay that replaces colors with their dark versions and replaces the normal
+ control color, which by default is the same as the secondary text color, with the primary
+ text color. -->
+ <style name="ThemeOverlay.Quantum.Dark.ActionBar">
+ <item name="colorControlNormal">?attr/textColorPrimary</item>
</style>
<!-- Variant of the quantum (dark) theme with no action bar. -->
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
index c0c20e2..ca68e93 100644
--- a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
@@ -172,7 +172,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe
final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
- final ControllerImpl controller = new ControllerImpl(enabledItems);
+ final ControllerImpl controller = ControllerImpl.createFrom(
+ null /* currentInstance */, enabledItems);
// switching-aware loop
assertRotationOrder(controller, false /* onlyCurrentIme */,
@@ -214,9 +215,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe
disabledSubtypeUnawareIme, null);
}
- // This test is disabled until DynamicRotationList is enabled.
@SmallTest
- public void DISABLED_testControllerImplWithUserAction() throws Exception {
+ public void testControllerImplWithUserAction() throws Exception {
final List<ImeSubtypeListItem> enabledItems = createEnabledImeSubtypes();
final ImeSubtypeListItem latinIme_en_US = enabledItems.get(0);
final ImeSubtypeListItem latinIme_fr = enabledItems.get(1);
@@ -226,7 +226,8 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe
final ImeSubtypeListItem japaneseIme_ja_JP = enabledItems.get(5);
final ImeSubtypeListItem switchUnawareJapaneseIme_ja_JP = enabledItems.get(6);
- final ControllerImpl controller = new ControllerImpl(enabledItems);
+ final ControllerImpl controller = ControllerImpl.createFrom(
+ null /* currentInstance */, enabledItems);
// === switching-aware loop ===
assertRotationOrder(controller, false /* onlyCurrentIme */,
@@ -272,5 +273,26 @@ public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTe
subtypeUnawareIme, null);
assertNextInputMethod(controller, true /* onlyCurrentIme */,
switchUnawareJapaneseIme_ja_JP, null);
+
+ // Rotation order should be preserved when created with the same subtype list.
+ final List<ImeSubtypeListItem> sameEnabledItems = createEnabledImeSubtypes();
+ final ControllerImpl newController = ControllerImpl.createFrom(controller,
+ sameEnabledItems);
+ assertRotationOrder(newController, false /* onlyCurrentIme */,
+ japaneseIme_ja_JP, latinIme_fr, latinIme_en_US);
+ assertRotationOrder(newController, false /* onlyCurrentIme */,
+ switchingUnawarelatinIme_en_UK, switchingUnawarelatinIme_hi, subtypeUnawareIme,
+ switchUnawareJapaneseIme_ja_JP);
+
+ // Rotation order should be initialized when created with a different subtype list.
+ final List<ImeSubtypeListItem> differentEnabledItems = Arrays.asList(
+ latinIme_en_US, latinIme_fr, switchingUnawarelatinIme_en_UK,
+ switchUnawareJapaneseIme_ja_JP);
+ final ControllerImpl anotherController = ControllerImpl.createFrom(controller,
+ differentEnabledItems);
+ assertRotationOrder(anotherController, false /* onlyCurrentIme */,
+ latinIme_en_US, latinIme_fr);
+ assertRotationOrder(anotherController, false /* onlyCurrentIme */,
+ switchingUnawarelatinIme_en_UK, switchUnawareJapaneseIme_ja_JP);
}
}
diff --git a/docs/html/about/dashboards/index.jd b/docs/html/about/dashboards/index.jd
index c61a94b..32b9c9e 100644
--- a/docs/html/about/dashboards/index.jd
+++ b/docs/html/about/dashboards/index.jd
@@ -64,7 +64,7 @@ Platform Versions</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on May 1, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on June 4, 2014.
<br/>Any versions with less than 0.1% distribution are not shown.</em>
</p>
@@ -95,7 +95,7 @@ Screens</a>.</p>
</div>
-<p style="clear:both"><em>Data collected during a 7-day period ending on May 1, 2014.
+<p style="clear:both"><em>Data collected during a 7-day period ending on June 4, 2014.
<br/>Any screen configurations with less than 0.1% distribution are not shown.</em></p>
@@ -114,7 +114,7 @@ support for any lower version (for example, support for version 2.0 also implies
<img alt="" style="float:right"
-src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C87.0%2C12.9&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
+src="//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A0.1%2C83.6%2C16.3&chf=bg%2Cs%2C00000000&chl=GL%201.1%20only%7CGL%202.0%7CGL%203.0&chco=c4df9b%2C6fad0c" />
<p>To declare which version of OpenGL ES your application requires, you should use the {@code
android:glEsVersion} attribute of the <a
@@ -136,17 +136,17 @@ uses.</p>
</tr>
<tr>
<td>2.0</th>
-<td>87.0%</td>
+<td>83.6%</td>
</tr>
<tr>
<td>3.0</th>
-<td>12.9%</td>
+<td>16.3%</td>
</tr>
</table>
-<p style="clear:both"><em>Data collected during a 7-day period ending on May 1, 2014</em></p>
+<p style="clear:both"><em>Data collected during a 7-day period ending on June 4, 2014</em></p>
@@ -164,47 +164,42 @@ uses.</p>
var VERSION_DATA =
[
{
- "chart": "//chart.googleapis.com/chart?chs=500x250&cht=p&chd=t%3A1.0%2C16.2%2C0.1%2C13.4%2C60.8%2C8.5&chf=bg%2Cs%2C00000000&chl=Froyo%7CGingerbread%7CHoneycomb%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chco=c4df9b%2C6fad0c",
+ "chart": "//chart.googleapis.com/chart?chl=Froyo%7CGingerbread%7CIce%20Cream%20Sandwich%7CJelly%20Bean%7CKitKat&chf=bg%2Cs%2C00000000&chd=t%3A0.8%2C14.9%2C12.3%2C58.4%2C13.6&chco=c4df9b%2C6fad0c&cht=p&chs=500x250",
"data": [
{
"api": 8,
"name": "Froyo",
- "perc": "1.0"
+ "perc": "0.8"
},
{
"api": 10,
"name": "Gingerbread",
- "perc": "16.2"
- },
- {
- "api": 13,
- "name": "Honeycomb",
- "perc": "0.1"
+ "perc": "14.9"
},
{
"api": 15,
"name": "Ice Cream Sandwich",
- "perc": "13.4"
+ "perc": "12.3"
},
{
"api": 16,
"name": "Jelly Bean",
- "perc": "33.5"
+ "perc": "29.0"
},
{
"api": 17,
"name": "Jelly Bean",
- "perc": "18.8"
+ "perc": "19.1"
},
{
"api": 18,
"name": "Jelly Bean",
- "perc": "8.5"
+ "perc": "10.3"
},
{
"api": 19,
"name": "KitKat",
- "perc": "8.5"
+ "perc": "13.6"
}
]
}
@@ -226,23 +221,22 @@ var SCREEN_DATA =
"xhdpi": "0.6"
},
"Normal": {
- "hdpi": "33.9",
- "mdpi": "12.5",
- "xhdpi": "19.9",
- "xxhdpi": "13.5"
+ "hdpi": "34.2",
+ "mdpi": "12.0",
+ "xhdpi": "19.6",
+ "xxhdpi": "14.6"
},
"Small": {
- "ldpi": "7.5"
+ "ldpi": "7.2"
},
"Xlarge": {
"hdpi": "0.3",
- "ldpi": "0.1",
- "mdpi": "4.2",
+ "mdpi": "4.0",
"xhdpi": "0.3"
}
},
- "densitychart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A8.2%2C21.1%2C1.6%2C34.8%2C20.8%2C13.5&chf=bg%2Cs%2C00000000&chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chco=c4df9b%2C6fad0c",
- "layoutchart": "//chart.googleapis.com/chart?chs=400x250&cht=p&chd=t%3A4.9%2C7.8%2C80.0%2C7.5&chf=bg%2Cs%2C00000000&chl=Xlarge%7CLarge%7CNormal%7CSmall&chco=c4df9b%2C6fad0c"
+ "densitychart": "//chart.googleapis.com/chart?chl=ldpi%7Cmdpi%7Ctvdpi%7Chdpi%7Cxhdpi%7Cxxhdpi&chf=bg%2Cs%2C00000000&chd=t%3A7.8%2C20.4%2C1.6%2C35.1%2C20.5%2C14.6&chco=c4df9b%2C6fad0c&cht=p&chs=400x250",
+ "layoutchart": "//chart.googleapis.com/chart?chl=Xlarge%7CLarge%7CNormal%7CSmall&chf=bg%2Cs%2C00000000&chd=t%3A4.6%2C7.8%2C80.4%2C7.2&chco=c4df9b%2C6fad0c&cht=p&chs=400x250"
}
];
diff --git a/docs/html/distribute/engage/deep-linking.jd b/docs/html/distribute/engage/deep-linking.jd
index 50728c5..0417ba1 100644
--- a/docs/html/distribute/engage/deep-linking.jd
+++ b/docs/html/distribute/engage/deep-linking.jd
@@ -68,8 +68,6 @@ page.image=/images/gp-listing-4.jpg
<h2 id="related-resources">
Related Resources
</h2>
-
-
</div>
<div class="resource-widget resource-flow-layout col-13" data-query=
diff --git a/docs/html/distribute/essentials/quality/core.jd b/docs/html/distribute/essentials/quality/core.jd
index c301f8c..cfe1a2a 100644
--- a/docs/html/distribute/essentials/quality/core.jd
+++ b/docs/html/distribute/essentials/quality/core.jd
@@ -234,9 +234,7 @@ page.image=/distribute/images/core-quality-guidelines.jpg
</tr>
</table>
-<h3>
- Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/corequalityguidelines/visualdesign"
@@ -509,9 +507,7 @@ data-maxresults="6">
</tr>
</table>
-<h3>
- Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/corequalityguidelines/functionality"
@@ -670,9 +666,7 @@ data-sortorder="-timestamp" data-cardsizes="6x3" data-maxresults="6">
</tr>
</table>
-<h3>
- Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/core/performance" data-sortorder="-timestamp"
@@ -819,9 +813,7 @@ data-cardsizes="6x3" data-maxresults="6">
</tr>
</table>
-<h3>
- Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/essentials/core/play" data-sortorder="-timestamp"
diff --git a/docs/html/distribute/essentials/quality/tablets.jd b/docs/html/distribute/essentials/quality/tablets.jd
index 966c462..2b2a5ae 100644
--- a/docs/html/distribute/essentials/quality/tablets.jd
+++ b/docs/html/distribute/essentials/quality/tablets.jd
@@ -158,7 +158,7 @@ across the screen:</p>
multi-pane UI for tablets (see next section).</li>
</ul>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/optimize"
@@ -219,7 +219,7 @@ different layouts in the appropriate screen size buckets (such as
<code>sw600dp</code>/<code>sw720</code>).</li>
</ul>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/extrascreen"
@@ -308,7 +308,7 @@ icon at the highest density possible. For example, if a tablet has an {@code xhd
it will request the {@code xxhdpi} version of the launcher icon.</li>
</ul>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/assets"
@@ -345,7 +345,7 @@ larger touch targets. </li>
or just centering the icon within the transparent button.</li>
</ul>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/fonts"
@@ -371,7 +371,7 @@ horizontal or square widget). </li>
possible.</li>
</ul>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/widgets"
@@ -458,7 +458,7 @@ some recommendations:</p>
</li>
</ol>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/versions"
@@ -528,7 +528,7 @@ permissions, make sure to explicitly declare a corresponding
as needed.
</p>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/hardware"
@@ -560,7 +560,7 @@ app supports. Note that, if possible, you should avoid using the
<a href="{@docRoot}guide/topics/manifest/compatible-screens-element.html"><code>&lt;compatible-screens&gt;</code></a>
element in your app.</p>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/tabletscreens"
@@ -689,7 +689,7 @@ element in your app.</p>
</li>
</ul>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/showcase"
@@ -799,7 +799,7 @@ appropriate.</p>
recommended.
</p>
-<h3 class="clearfloat">Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/essentials/tabletguidelines/googleplay"
data-sortOrder="-timestamp"
diff --git a/docs/html/distribute/googleplay/edu/about.jd b/docs/html/distribute/googleplay/edu/about.jd
index 1c003cf..e73356e 100644
--- a/docs/html/distribute/googleplay/edu/about.jd
+++ b/docs/html/distribute/googleplay/edu/about.jd
@@ -109,7 +109,7 @@ Xnonavpage=true
<p style="clear:both">
</p>
<div class="headerLine">
-<h2>Related Resources</h2>
+<h2 id="related-resources">Related Resources</h2>
</div>
<div class="dynamic-grid">
diff --git a/docs/html/distribute/tools/launch-checklist.jd b/docs/html/distribute/tools/launch-checklist.jd
index 3f6b1a6..f310800 100644
--- a/docs/html/distribute/tools/launch-checklist.jd
+++ b/docs/html/distribute/tools/launch-checklist.jd
@@ -85,9 +85,7 @@ src="{@docRoot}distribute/images/launch-checklist.jpg"></div>
Play.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/understanding"
@@ -110,9 +108,7 @@ data-maxresults="6">
repeated violations, termination of your developer account.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/policies" data-sortorder=
@@ -154,9 +150,7 @@ data-maxresults="6">
should exhibit.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/quality" data-sortorder=
@@ -212,9 +206,7 @@ data-maxresults="6">
no changes are required in your app binary.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/rating" data-sortorder=
@@ -280,9 +272,7 @@ data-maxresults="6">
Checklist</a> for key steps and considerations in the localization process.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/country" data-sortorder=
@@ -335,9 +325,7 @@ data-maxresults="6">
on your code when building your release-ready APK.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/size" data-sortorder=
@@ -387,9 +375,7 @@ data-maxresults="6">
<a href="{@docRoot}about/dashboards/index.html">Device Dashboard</a> charts.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/platform" data-sortorder=
@@ -450,9 +436,7 @@ data-maxresults="6">
set up a Google Wallet Merchant Account</a> before you can publish.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/price" data-sortorder=
@@ -485,9 +469,7 @@ data-maxresults="6">
complete and test your implementation before creating your release-ready APK.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/purchasemethod"
@@ -517,9 +499,7 @@ data-maxresults="6">
available currencies through the Developer Console.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/setprice" data-sortorder=
@@ -599,9 +579,7 @@ data-maxresults="6">
listing.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/localization"
@@ -659,9 +637,7 @@ data-maxresults="6">
publishing date.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/graphics" data-sortorder=
@@ -701,7 +677,7 @@ data-maxresults="6">
Developer Console. If necessary, you can replace an APK with a more recent
version before publishing.
</p>
-<!--<h3>Related resources</h3>
+<!--<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/toolsreference/launchchecklist/build"
@@ -815,9 +791,7 @@ See how you can facilitate testing with Google Play.</td>
elsewhere.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/productdetails"
@@ -853,9 +827,7 @@ data-maxresults="6">
available.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/badges" data-sortorder=
@@ -959,9 +931,7 @@ data-maxresults="6">
linking from your promotional campaigns.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/launchchecklist/finalchecks"
@@ -1063,7 +1033,7 @@ data-maxresults="6">
</ul>
</ul>
-<h3>Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/toolsreference/launchchecklist/afterlaunch"
diff --git a/docs/html/distribute/tools/localization-checklist.jd b/docs/html/distribute/tools/localization-checklist.jd
index 569ed02..08a8143 100644
--- a/docs/html/distribute/tools/localization-checklist.jd
+++ b/docs/html/distribute/tools/localization-checklist.jd
@@ -84,9 +84,7 @@ page.image=/distribute/images/localization-checklist.jpg
development, translation, testing, and marketing efforts to these markets.
</p>
-<h3 id="related-resources">
- Related Resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/identifylocales"
@@ -224,9 +222,7 @@ data-sortorder="-timestamp" data-cardsizes="9x3," data-maxresults="6">
directories, without language or locale qualifiers.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/tools/loc/designforloc" data-sortorder="-timestamp"
@@ -399,9 +395,7 @@ data-cardsizes="9x3" data-maxresults="6">
&lt;/resources&gt;
</pre>
-<h3 class="clearfloat">
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/managestrings"
@@ -570,9 +564,7 @@ data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
<img src="{@docRoot}images/gp-localization-trans-0.png" class="border-img">
</div>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/translatestrings"
@@ -690,7 +682,7 @@ data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
your localized apps. One way to do that is through beta testing with regional
users &mdash; Google Play can help you do this. <!-- </p>
-<h3 class="clearfloat">Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/toolsreference/localizationchecklist/test"
@@ -887,9 +879,7 @@ data-sortorder="-timestamp" data-cardsizes="9x3" data-maxresults="6">
helpful reminders for a successful localized launch.
</p>
-<h3>
- Related resources
-</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13" data-query=
"collection:distribute/toolsreference/localizationchecklist/preplaunch"
@@ -968,7 +958,7 @@ data-maxresults="6">
"{@docRoot}distribute/tools/launch-checklist.html">Launch Checklist</a> to
learn more about how to plan, build, and launch your app on Google Play.
</p>
-<h3 class="clearfloat">Related resources</h3>
+<h3 class="rel-resources clearfloat">Related resources</h3>
<div class="resource-widget resource-flow-layout col-13"
data-query="collection:distribute/toolsreference/localizationchecklist/supportlaunch"
diff --git a/docs/html/distribute/tools/promote/badge-files.jd b/docs/html/distribute/tools/promote/badge-files.jd
index b481802..e65e698 100644
--- a/docs/html/distribute/tools/promote/badge-files.jd
+++ b/docs/html/distribute/tools/promote/badge-files.jd
@@ -21,9 +21,10 @@ two Google Play badges.</p>
<a href="{@docRoot}downloads/brand/v2/english_get.ai">English (English)</a><br/>
+ <a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
+
<a href="{@docRoot}downloads/brand/v2/amharic_get.ai">ኣማርኛ (Amharic)</a><br/>
- <a href="{@docRoot}downloads/brand/af_generic_rgb_wo.ai">Afrikaans (Afrikaans)</a><br/>
<!--
<a href="{@docRoot}downloads/brand/ar_generic_rgb_wo.ai">العربية (Arabic)</a><br/>
-->
@@ -286,6 +287,3 @@ Guidelines</a>.
<p>To quickly create a badge that links to your apps on Google Play,
use the <a
href="{@docRoot}distribute/tools/promote/badges.html">Googe Play badge generator</a>.</p>
-
-
- \ No newline at end of file
diff --git a/docs/html/guide/components/fundamentals.jd b/docs/html/guide/components/fundamentals.jd
index 9ac063e..fd1a7a8 100644
--- a/docs/html/guide/components/fundamentals.jd
+++ b/docs/html/guide/components/fundamentals.jd
@@ -335,8 +335,8 @@ documentation. </p>
{@link android.content.Intent} to start activities, services, and broadcast receivers. You can do so
by explicitly naming the target component (using the component class name) in the intent. However,
the real power of intents lies in the concept of <em>implicit intents</em>. An implicit intent
-simply describe the type of action to perform (and optionally, the data upon which you’d like to
-perform the action) and allow the system to find a component on the device that can perform the
+simply describes the type of action to perform (and, optionally, the data upon which you’d like to
+perform the action) and allows the system to find a component on the device that can perform the
action and start it. If there are multiple components that can perform the action described by the
intent, then the user selects which one to use.</p>
diff --git a/docs/html/images/training/volley-request.png b/docs/html/images/training/volley-request.png
new file mode 100644
index 0000000..85f0681
--- /dev/null
+++ b/docs/html/images/training/volley-request.png
Binary files differ
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 9b06a9d..f490053 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -28,6 +28,39 @@ href="http://tools.android.com/knownissues">http://tools.android.com/knownissues
<div class="toggle-content opened">
<p><a href="#" onclick="return toggleContent(this)">
<img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+ alt=""/>SDK Tools, Revision 22.6.4</a> <em>(June 2014)</em>
+ </p>
+
+ <div class="toggle-content-toggleme">
+
+ <dl>
+ <dt>Dependencies:</dt>
+
+ <dd>
+ <ul>
+ <li>Android SDK Platform-tools revision 18 or later.</li>
+ <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+ designed for use with ADT 22.6.3 and later. If you haven't already, update your
+ <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.6.3.</li>
+ <li>If you are developing outside Eclipse, you must have
+ <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+ </ul>
+ </dd>
+
+ <dt>General Notes:</dt>
+ <dd>
+ <ul>
+ <li>Fixed an issue with the x86 emulator that caused Google Maps to crash.
+ (<a href="http://b.android.com/69385">Issue 69385</a>)</li>
+ <li>Fixed minor OpenGL issues.</li>
+ </ul>
+ </dd>
+ </div>
+</div>
+
+<div class="toggle-content closed">
+ <p><a href="#" onclick="return toggleContent(this)">
+ <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
alt=""/>SDK Tools, Revision 22.6.3</a> <em>(April 2014)</em>
</p>
diff --git a/docs/html/training/basics/network-ops/connecting.jd b/docs/html/training/basics/network-ops/connecting.jd
index 50a9e1b..1452ded 100644
--- a/docs/html/training/basics/network-ops/connecting.jd
+++ b/docs/html/training/basics/network-ops/connecting.jd
@@ -25,6 +25,7 @@ next.link=managing.html
<h2>You should also read</h2>
<ul>
+ <li><a href="{@docRoot}training/volley/index.html">Transmitting Network Data Using Volley</a></li>
<li><a href="{@docRoot}training/monitoring-device-state/index.html">Optimizing Battery Life</a></li>
<li><a href="{@docRoot}training/efficient-downloads/index.html">Transferring Data Without Draining the Battery</a></li>
<li><a href="{@docRoot}guide/webapps/index.html">Web Apps Overview</a></li>
diff --git a/docs/html/training/basics/network-ops/index.jd b/docs/html/training/basics/network-ops/index.jd
index 89ab539..1f6493f 100644
--- a/docs/html/training/basics/network-ops/index.jd
+++ b/docs/html/training/basics/network-ops/index.jd
@@ -24,6 +24,7 @@ next.link=connecting.html
<li><a href="{@docRoot}training/monitoring-device-state/index.html">Optimizing Battery Life</a></li>
<li><a href="{@docRoot}training/efficient-downloads/index.html">Transferring Data Without Draining the Battery</a></li>
<li><a href="{@docRoot}guide/webapps/index.html">Web Apps Overview</a></li>
+ <li><a href="{@docRoot}training/volley/index.html">Transmitting Network Data Using Volley</a></li>
</ul>
@@ -51,6 +52,14 @@ as a source of reusable code for your own application.</p>
fundamental building blocks for creating Android applications that download
content and parse data efficiently, while minimizing network traffic.</p>
+<p class="note"><strong>Note:</strong> See the class <a href="{@docRoot}
+training/volley/index.html">Transmitting Network Data Using Volley</a>
+for information on Volley, an HTTP library that makes networking for Android apps
+easier and faster. Volley is available through the open
+<a href="https://android.googlesource.com/platform/frameworks/volley">AOSP</a>
+repository. Volley may be able to help you streamline and improve the performance
+of your app's network operations.</p>
+
<h2>Lessons</h2>
diff --git a/docs/html/training/contacts-provider/retrieve-names.jd b/docs/html/training/contacts-provider/retrieve-names.jd
index b034a6a..7106889 100644
--- a/docs/html/training/contacts-provider/retrieve-names.jd
+++ b/docs/html/training/contacts-provider/retrieve-names.jd
@@ -102,9 +102,9 @@ trainingnavtop=true
<p>
To display the search results in a {@link android.widget.ListView}, you need a main layout file
that defines the entire UI including the {@link android.widget.ListView}, and an item layout
- file that defines one line of the {@link android.widget.ListView}. For example, you can define
- the main layout file <code>res/layout/contacts_list_view.xml</code> that contains the
- following XML:
+ file that defines one line of the {@link android.widget.ListView}. For example, you could create
+ the main layout file <code>res/layout/contacts_list_view.xml</code> with
+ the following XML:
</p>
<pre>
&lt;?xml version="1.0" encoding="utf-8"?&gt;
@@ -250,7 +250,8 @@ public class ContactsFragment extends Fragment implements
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the fragment layout
- return inflater.inflate(R.layout.contacts_list_layout, container, false);
+ return inflater.inflate(R.layout.contact_list_fragment,
+ container, false);
}
</pre>
<h3 id="DefineAdapter">Set up the CursorAdapter for the ListView</h3>
@@ -268,7 +269,8 @@ public class ContactsFragment extends Fragment implements
super.onActivityCreated(savedInstanceState);
...
// Gets the ListView from the View list of the parent activity
- mContactsList = (ListView) getActivity().findViewById(R.layout.contact_list_view);
+ mContactsList =
+ (ListView) getActivity().findViewById(R.layout.contact_list_view);
// Gets a CursorAdapter
mCursorAdapter = new SimpleCursorAdapter(
getActivity(),
diff --git a/docs/html/training/training_toc.cs b/docs/html/training/training_toc.cs
index 0616b62..c5dc3c5 100644
--- a/docs/html/training/training_toc.cs
+++ b/docs/html/training/training_toc.cs
@@ -609,6 +609,35 @@ include the action bar on devices running Android 2.1 or higher."
</li>
</ul>
</li>
+ <li class="nav-section">
+ <div class="nav-section-header">
+ <a href="<?cs var:toroot ?>training/volley/index.html"
+ description="How to perform fast, scalable UI operations over the network using Volley"
+ >Transmitting Network Data Using Volley</a>
+ </div>
+ <ul>
+ <li>
+ <a href="<?cs var:toroot ?>training/volley/simple.html">
+ Sending a Simple Request
+ </a>
+ </li>
+ <li>
+ <a href="<?cs var:toroot ?>training/volley/requestqueue.html">
+ Setting Up a RequestQueue
+ </a>
+ </li>
+ <li>
+ <a href="<?cs var:toroot ?>training/volley/request.html">
+ Making a Standard Request
+ </a>
+ </li>
+ <li>
+ <a href="<?cs var:toroot ?>training/volley/request-custom.html">
+ Implementing a Custom Request
+ </a>
+ </li>
+ </ul>
+ </li>
</ul>
</li>
diff --git a/docs/html/training/volley/index.jd b/docs/html/training/volley/index.jd
new file mode 100644
index 0000000..ba5b09f
--- /dev/null
+++ b/docs/html/training/volley/index.jd
@@ -0,0 +1,133 @@
+page.title=Transmitting Network Data Using Volley
+page.tags=""
+
+trainingnavtop=true
+startpage=true
+
+
+@jd:body
+
+
+
+<div id="tb-wrapper">
+<div id="tb">
+
+
+<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
+<h2>Dependencies and prerequisites</h2>
+
+<ul>
+ <li>Android 1.6 (API Level 4) or higher</li>
+</ul>
+
+<h2>You should also see</h2>
+<ul>
+ <li>For a production quality app that uses Volley, see the 2013 Google I/O
+ <a href="https://github.com/google/iosched">schedule app</a>. In particular, see:
+ <ul>
+ <li><a
+ href="https://github.com/google/iosched/blob/master/android/src/main/java/com/google/android/apps/iosched/util/ImageLoader.java">
+ ImageLoader</a></li>
+ <li><a
+ href="https://github.com/google/iosched/blob/master/android/src/main/java/com/google/android/apps/iosched/util/BitmapCache.java">
+ BitmapCache</a></li>
+ </ul>
+ </li>
+</ul>
+
+</div>
+</div>
+
+<a class="notice-developers-video wide" href="https://developers.google.com/events/io/sessions/325304728">
+<div>
+ <h3>Video</h3>
+ <p>Volley: Easy, Fast Networking for Android</p>
+</div>
+</a>
+
+
+<p>Volley is an HTTP library that makes networking for Android apps easier and most importantly,
+faster. Volley is available through the open
+<a href="https://android.googlesource.com/platform/frameworks/volley">AOSP</a> repository.</p>
+
+<p>Volley offers the following benefits:</p>
+
+<ul>
+
+<li>Automatic scheduling of network requests.</li>
+<li>Multiple concurrent network connections.</li>
+<li>Transparent disk and memory response caching with standard HTTP
+<a href=http://en.wikipedia.org/wiki/Cache_coherence">cache coherence</a>.</li>
+<li>Support for request prioritization.</li>
+<li>Cancellation request API. You can cancel a single request, or you can set blocks or
+scopes of requests to cancel.</li>
+<li>Ease of customization, for example, for retry and backoff.</li>
+<li>Strong ordering that makes it easy to correctly populate your UI with data fetched
+asynchronously from the network.</li>
+<li>Debugging and tracing tools.</li>
+
+</ul>
+
+<p>Volley excels at RPC-type operations used to populate a UI, such as fetching a page of
+search results as structured data. It integrates easily with any protocol and comes out of
+the box with support for raw strings, images, and JSON. By providing built-in support for
+the features you need, Volley frees you from writing boilerplate code and allows you to
+concentrate on the logic that is specific to your app.</p>
+<p>Volley is not suitable for large download or streaming operations, since Volley holds
+all responses in memory during parsing. For large download operations, consider using an
+alternative like {@link android.app.DownloadManager}.</p>
+
+<p>The core Volley library is developed in the open
+<a href="https://android.googlesource.com/platform/frameworks/volley">AOSP</a>
+repository at {@code frameworks/volley} and contains the main request dispatch pipeline
+as well as a set of commonly applicable utilities, available in the Volley "toolbox." The
+easiest way to add Volley to your project is to clone the Volley repository and set it as
+a library project:</p>
+
+<ol>
+<li>Git clone the repository by typing the following at the command line:
+
+<pre>
+git clone https://android.googlesource.com/platform/frameworks/volley
+</pre>
+</li>
+
+<li>Import the downloaded source into your app project as an Android library project
+(as described in <a href="{@docRoot}tools/projects/projects-eclipse.html">
+Managing Projects from Eclipse with ADT</a>, if you're using Eclipse) or make a
+<a href="{@docRoot}guide/faq/commontasks.html#addexternallibrary"><code>.jar</code> file</a>.</li>
+</ol>
+
+<h2>Lessons</h2>
+
+<dl>
+ <dt>
+ <strong><a href="simple.html">Sending a Simple Request</a></strong>
+ </dt>
+ <dd>
+ Learn how to send a simple request using the default behaviors of Volley, and how
+ to cancel a request.
+
+ </dd>
+ <dt>
+ <strong><a href="requestqueue.html">Setting Up a RequestQueue</a></strong>
+ </dt>
+ <dd>
+ Learn how to set up a {@code RequestQueue}, and how to implement a singleton
+ pattern to create a {@code RequestQueue} that lasts the lifetime of your app.
+ </dd>
+ <dt>
+ <strong><a href="request.html">Making a Standard Request</a></strong>
+ </dt>
+ <dd>
+ Learn how to send a request using one of Volley's out-of-the-box request types
+ (raw strings, images, and JSON).
+ </dd>
+ <dt>
+ <strong><a href="request-custom.html">Implementing a Custom Request</a></strong>
+ </dt>
+ <dd>
+ Learn how to implement a custom request.
+ </dd>
+
+</dl>
diff --git a/docs/html/training/volley/request-custom.jd b/docs/html/training/volley/request-custom.jd
new file mode 100644
index 0000000..7b669b9
--- /dev/null
+++ b/docs/html/training/volley/request-custom.jd
@@ -0,0 +1,163 @@
+page.title=Implementing a Custom Request
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- table of contents -->
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#custom-request">Write a Custom Request</a></li>
+</ol>
+
+</div>
+</div>
+
+<a class="notice-developers-video wide" href="https://developers.google.com/events/io/sessions/325304728">
+<div>
+ <h3>Video</h3>
+ <p>Volley: Easy, Fast Networking for Android</p>
+</div>
+</a>
+
+<p>This lesson describes how to implement your own custom request types, for types that
+don't have out-of-the-box Volley support.</p>
+
+<h2 id="custom-request">Write a Custom Request</h2>
+
+Most requests have ready-to-use implementations in the toolbox; if your response is a string,
+image, or JSON, you probably won't need to implement a custom {@code Request}.</p>
+
+<p>For cases where you do need to implement a custom request, this is all you need
+to do:</p>
+
+<ul>
+
+<li>Extend the {@code Request&lt;T&gt;} class, where
+{@code &lt;T&gt;} represents the type of parsed response
+the request expects. So if your parsed response is a string, for example,
+create your custom request by extending {@code Request&lt;String&gt;}. See the Volley
+toolbox classes {@code StringRequest} and {@code ImageRequest} for examples of
+extending {@code Request&lt;T&gt;}.</li>
+
+<li>Implement the abstract methods {@code parseNetworkResponse()}
+and {@code deliverResponse()}, described in more detail below.</li>
+
+</ul>
+
+<h3>parseNetworkResponse</h3>
+
+<p>A {@code Response} encapsulates a parsed response for delivery, for a given type
+(such as string, image, or JSON). Here is a sample implementation of
+{@code parseNetworkResponse()}:</p>
+
+<pre>
+&#64;Override
+protected Response&lt;T&gt; parseNetworkResponse(
+ NetworkResponse response) {
+ try {
+ String json = new String(response.data,
+ HttpHeaderParser.parseCharset(response.headers));
+ return Response.success(gson.fromJson(json, clazz),
+ HttpHeaderParser.parseCacheHeaders(response));
+ }
+ // handle errors
+...
+}
+</pre>
+
+<p>Note the following:</p>
+
+<ul>
+<li>{@code parseNetworkResponse()} takes as its parameter a {@code NetworkResponse}, which
+contains the response payload as a byte[], HTTP status code, and response headers.</li>
+<li>Your implementation must return a {@code Response&lt;T&gt;}, which contains your typed
+response object and cache metadata or an error, such as in the case of a parse failure.</li>
+</ul>
+
+<p>If your protocol has non-standard cache semantics, you can build a {@code Cache.Entry}
+yourself, but most requests are fine with something like this:
+</p>
+<pre>return Response.success(myDecodedObject,
+ HttpHeaderParser.parseCacheHeaders(response));</pre>
+<p>
+Volley calls {@code parseNetworkResponse()} from a worker thread. This ensures that
+expensive parsing operations, such as decoding a JPEG into a Bitmap, don't block the UI
+thread.</p>
+
+<h3>deliverResponse</h3>
+
+<p>Volley calls you back on the main thread with the object you returned in
+{@code parseNetworkResponse()}. Most requests invoke a callback interface here,
+for example:
+</p>
+
+<pre>
+protected void deliverResponse(T response) {
+ listener.onResponse(response);
+</pre>
+
+<h3>Example: GsonRequest</h3>
+
+<p><a href="http://code.google.com/p/google-gson/">Gson</a> is a library for converting
+Java objects to and from JSON using reflection. You can define Java objects that have the
+same names as their corresponding JSON keys, pass Gson the class object, and Gson will fill
+in the fields for you. Here's a complete implementation of a Volley request that uses
+Gson for parsing:</p>
+
+<pre>
+public class GsonRequest&lt;T&gt; extends Request&lt;T&gt; {
+ private final Gson gson = new Gson();
+ private final Class&lt;T&gt; clazz;
+ private final Map&lt;String, String&gt; headers;
+ private final Listener&lt;T&gt; listener;
+
+ /**
+ * Make a GET request and return a parsed object from JSON.
+ *
+ * &#64;param url URL of the request to make
+ * &#64;param clazz Relevant class object, for Gson's reflection
+ * &#64;param headers Map of request headers
+ */
+ public GsonRequest(String url, Class&lt;T&gt; clazz, Map&lt;String, String&gt; headers,
+ Listener&lt;T&gt; listener, ErrorListener errorListener) {
+ super(Method.GET, url, errorListener);
+ this.clazz = clazz;
+ this.headers = headers;
+ this.listener = listener;
+ }
+
+ &#64;Override
+ public Map&lt;String, String&gt; getHeaders() throws AuthFailureError {
+ return headers != null ? headers : super.getHeaders();
+ }
+
+ &#64;Override
+ protected void deliverResponse(T response) {
+ listener.onResponse(response);
+ }
+
+ &#64;Override
+ protected Response&lt;T&gt; parseNetworkResponse(NetworkResponse response) {
+ try {
+ String json = new String(
+ response.data,
+ HttpHeaderParser.parseCharset(response.headers));
+ return Response.success(
+ gson.fromJson(json, clazz),
+ HttpHeaderParser.parseCacheHeaders(response));
+ } catch (UnsupportedEncodingException e) {
+ return Response.error(new ParseError(e));
+ } catch (JsonSyntaxException e) {
+ return Response.error(new ParseError(e));
+ }
+ }
+}
+</pre>
+
+<p>Volley provides ready-to-use {@code JsonArrayRequest} and {@code JsonArrayObject} classes
+if you prefer to take that approach. See <a href="request.html">
+Using Standard Request Types</a> for more information.</p>
diff --git a/docs/html/training/volley/request.jd b/docs/html/training/volley/request.jd
new file mode 100644
index 0000000..d8ccab2
--- /dev/null
+++ b/docs/html/training/volley/request.jd
@@ -0,0 +1,281 @@
+page.title=Making a Standard Request
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- table of contents -->
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#request-image">Request an Image</a></li>
+ <li><a href="#request-json">Request JSON</a></li>
+</ol>
+
+</div>
+</div>
+
+<a class="notice-developers-video wide" href="https://developers.google.com/events/io/sessions/325304728">
+<div>
+ <h3>Video</h3>
+ <p>Volley: Easy, Fast Networking for Android</p>
+</div>
+</a>
+
+<p>
+This lesson describes how to use the common request types that Volley supports:</p>
+
+<ul>
+ <li>{@code StringRequest}. Specify a URL and receive a raw string in response. See
+ <a href="requestqueue.html">Setting Up a Request Queue</a> for an example.</li>
+ <li>{@code ImageRequest}. Specify a URL and receive an image in response.</li>
+ <li>{@code JsonObjectRequest} and {@code JsonArrayRequest} (both subclasses of
+ {@code JsonRequest}). Specify a URL and get a JSON object or array (respectively) in
+ response.</li>
+</ul>
+
+<p>If your expected response is one of these types, you probably won't have to implement a
+custom request. This lesson describes how to use these standard request types. For
+information on how to implement your own custom request, see <a href="requests-custom.html">
+Implementing a Custom Request</a>.</p>
+
+
+<h2 id="request-image">Request an Image</h2>
+
+<p>Volley offers the following classes for requesting images. These classes layer on top
+of each other to offer different levels of support for processing images:</p>
+
+<ul>
+ <li>{@code ImageRequest}&mdash;a canned request for getting an image at a given URL and
+ calling back with a decoded bitmap. It also provides convenience features like specifying
+ a size to resize to. Its main benefit is that Volley's thread scheduling ensures that
+ expensive image operations (decoding, resizing) automatically happen on a worker thread.</li>
+
+ <li>{@code ImageLoader}&mdash;a helper class that handles loading and caching images from
+ remote URLs. {@code ImageLoader} is a an orchestrator for large numbers of {@code ImageRequest}s,
+ for example when putting multiple thumbnails in a {@link android.widget.ListView}.
+ {@code ImageLoader} provides an in-memory cache to sit in front of the normal Volley
+ cache, which is important to prevent flickering. This makes it possible to achieve a
+ cache hit without blocking or deferring off the main thread, which is impossible when
+ using disk I/O. {@code ImageLoader} also does response coalescing, without which almost
+ every response handler would set a bitmap on a view and cause a layout pass per image.
+ Coalescing makes it possible to deliver multiple responses simultaneously, which improves
+ performance.</li>
+ <li>{@code NetworkImageView}&mdash;builds on {@code ImageLoader} and effectively replaces
+ {@link android.widget.ImageView} for situations where your image is being fetched over
+ the network via URL. {@code NetworkImageView} also manages canceling pending requests if
+ the view is detached from the hierarchy.</li>
+</ul>
+
+<h3>Use ImageRequest</h3>
+
+<p>Here is an example of using {@code ImageRequest}. It retrieves the image specified by
+the URL and displays it in the app. Note that this snippet interacts with the
+{@code RequestQueue} through a singleton class (see <a href="{@docRoot}
+training/volley/requestqueue.html#singleton">Setting Up a RequestQueue</a> for more discussion of
+this topic):</p>
+
+<pre>
+ImageView mImageView;
+String url = "http://i.imgur.com/7spzG.png";
+mImageView = (ImageView) findViewById(R.id.myImage);
+...
+
+// Retrieves an image specified by the URL, displays it in the UI.
+ImageRequest request = new ImageRequest(url,
+ new Response.Listener<Bitmap>() {
+ &#64;Override
+ public void onResponse(Bitmap bitmap) {
+ mImageView.setImageBitmap(bitmap);
+ }
+ }, 0, 0, null,
+ new Response.ErrorListener() {
+ public void onErrorResponse(VolleyError error) {
+ mImageView.setImageResource(R.drawable.image_load_error);
+ }
+ });
+// Access the RequestQueue through your singleton class.
+MySingleton.getInstance(this).addToRequestQueue(request);</pre>
+
+
+<h3>Use ImageLoader and NetworkImageView</h3>
+
+<p>You can use {@code ImageLoader} and {@code NetworkImageView} in concert to efficiently
+manage the display of multiple images, such as in a {@link android.widget.ListView}. In your
+layout XML file, you use {@code NetworkImageView} in much the same way you would use
+{@link android.widget.ImageView}, for example:</p>
+
+<pre>&lt;com.android.volley.toolbox.NetworkImageView
+ android:id=&quot;&#64;+id/networkImageView&quot;
+ android:layout_width=&quot;150dp&quot;
+ android:layout_height=&quot;170dp&quot;
+ android:layout_centerHorizontal=&quot;true&quot; /&gt;</pre>
+
+<p>You can use {@code ImageLoader} by itself to display an image, for example:</p>
+
+<pre>
+ImageLoader mImageLoader;
+ImageView mImageView;
+// The URL for the image that is being loaded.
+private static final String IMAGE_URL =
+ "http://developer.android.com/images/training/system-ui.png";
+...
+mImageView = (ImageView) findViewById(R.id.regularImageView);
+
+// Get the ImageLoader through your singleton class.
+mImageLoader = MySingleton.getInstance(this).getImageLoader();
+mImageLoader.get(IMAGE_URL, ImageLoader.getImageListener(mImageView,
+ R.drawable.def_image, R.drawable.err_image));
+</pre>
+
+<p>However, {@code NetworkImageView} can do this for you if all you're doing is populating
+an {@link android.widget.ImageView}. For example:</p>
+
+<pre>
+ImageLoader mImageLoader;
+NetworkImageView mNetworkImageView;
+private static final String IMAGE_URL =
+ "http://developer.android.com/images/training/system-ui.png";
+...
+
+// Get the NetworkImageView that will display the image.
+mNetworkImageView = (NetworkImageView) findViewById(R.id.networkImageView);
+
+// Get the ImageLoader through your singleton class.
+mImageLoader = MySingleton.getInstance(this).getImageLoader();
+
+// Set the URL of the image that should be loaded into this view, and
+// specify the ImageLoader that will be used to make the request.
+mNetworkImageView.setImageUrl(IMAGE_URL, mImageLoader);
+</pre>
+
+<p>The above snippets access the {@code RequestQueue} and the {@code ImageLoader}
+through a singleton class, as described in <a href="{@docRoot}training/volley/requestqueue.html#singleton">
+Setting Up a RequestQueue</a>. This approach ensures that your app creates single instances of
+these classes that last the lifetime of your app. The reason that this is important for
+{@code ImageLoader} (the helper class that handles loading and caching images) is that
+the main function of the in-memory cache is to allow for flickerless rotation. Using a
+singleton pattern allows the bitmap cache to outlive the activity. If instead you create the
+{@code ImageLoader} in an activity, the {@code ImageLoader} would be recreated along with
+the activity every time the user rotates the device. This would cause flickering.</p>
+
+<h4 id="lru-cache">Example LRU cache</h4>
+
+<p>The Volley toolbox provides a standard cache implementation via the
+{@code DiskBasedCache} class. This class caches files directly onto the hard disk in the
+specified directory. But to use {@code ImageLoader}, you should provide a custom
+in-memory LRU bitmap cache that implements the {@code ImageLoader.ImageCache} interface.
+You may want to set up your cache as a singleton; for more discussion of this topic, see
+<a href="{@docRoot}training/volley/requestqueue.html#singleton">
+Setting Up a RequestQueue</a>.</p>
+
+<p>Here is a sample implementation for an in-memory {@code LruBitmapCache} class.
+It extends the {@link android.support.v4.util.LruCache} class and implements the
+{@code ImageLoader.ImageCache} interface:</p>
+
+<pre>
+import android.graphics.Bitmap;
+import android.support.v4.util.LruCache;
+import android.util.DisplayMetrics;
+import com.android.volley.toolbox.ImageLoader.ImageCache;
+
+public class LruBitmapCache extends LruCache&lt;String, Bitmap&gt;
+ implements ImageCache {
+
+ public LruBitmapCache(int maxSize) {
+ super(maxSize);
+ }
+
+ public LruBitmapCache(Context ctx) {
+ this(getCacheSize(ctx));
+ }
+
+ &#64;Override
+ protected int sizeOf(String key, Bitmap value) {
+ return value.getRowBytes() * value.getHeight();
+ }
+
+ &#64;Override
+ public Bitmap getBitmap(String url) {
+ return get(url);
+ }
+
+ &#64;Override
+ public void putBitmap(String url, Bitmap bitmap) {
+ put(url, bitmap);
+ }
+
+ // Returns a cache size equal to approximately three screens worth of images.
+ public static int getCacheSize(Context ctx) {
+ final DisplayMetrics displayMetrics = ctx.getResources().
+ getDisplayMetrics();
+ final int screenWidth = displayMetrics.widthPixels;
+ final int screenHeight = displayMetrics.heightPixels;
+ // 4 bytes per pixel
+ final int screenBytes = screenWidth * screenHeight * 4;
+
+ return screenBytes * 3;
+ }
+}
+</pre>
+
+<p>Here is an example of how to instantiate an {@code ImageLoader} to use this
+cache:</p>
+
+<pre>
+RequestQueue mRequestQueue; // assume this exists.
+ImageLoader mImageLoader = new ImageLoader(mRequestQueue, new LruBitmapCache(
+ LruBitmapCache.getCacheSize()));
+</pre>
+
+
+<h2 id="request-json">Request JSON</h2>
+
+<p>Volley provides the following classes for JSON requests:</p>
+
+<ul>
+ <li>{@code JsonArrayRequest}&mdash;A request for retrieving a
+ {@link org.json.JSONArray}
+ response body at a given URL.</li>
+ <li>{@code JsonObjectRequest}&mdash;A request for retrieving a
+ {@link org.json.JSONObject}
+ response body at a given URL, allowing for an optional
+ {@link org.json.JSONObject}
+ to be passed in as part of the request body.</li>
+</ul>
+
+<p>Both classes are based on the common base class {@code JsonRequest}. You use them
+following the same basic pattern you use for other types of requests. For example, this
+snippet fetches a JSON feed and displays it as text in the UI:</p>
+
+<pre>
+TextView mTxtDisplay;
+ImageView mImageView;
+mTxtDisplay = (TextView) findViewById(R.id.txtDisplay);
+String url = "http://my-json-feed";
+
+JsonObjectRequest jsObjRequest = new JsonObjectRequest
+ (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {
+
+ &#64;Override
+ public void onResponse(JSONObject response) {
+ mTxtDisplay.setText("Response: " + response.toString());
+ }
+}, new Response.ErrorListener() {
+
+ &#64;Override
+ public void onErrorResponse(VolleyError error) {
+ // TODO Auto-generated method stub
+
+ }
+});
+
+// Access the RequestQueue through your singleton class.
+MySingleton.getInstance(this).addToRequestQueue(jsObjRequest);
+</pre>
+
+For an example of implementing a custom JSON request based on
+<a href="http://code.google.com/p/google-gson/">Gson</a>, see the next lesson,
+<a href="request-custom.html">Implementing a Custom Request</a>.
diff --git a/docs/html/training/volley/requestqueue.jd b/docs/html/training/volley/requestqueue.jd
new file mode 100644
index 0000000..6858d91
--- /dev/null
+++ b/docs/html/training/volley/requestqueue.jd
@@ -0,0 +1,204 @@
+page.title=Setting Up a RequestQueue
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- table of contents -->
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#network">Set Up a Network and Cache</a></li>
+ <li><a href="#singleton">Use a Singleton Pattern</a></li>
+</ol>
+
+</div>
+</div>
+
+<a class="notice-developers-video wide" href="https://developers.google.com/events/io/sessions/325304728">
+<div>
+ <h3>Video</h3>
+ <p>Volley: Easy, Fast Networking for Android</p>
+</div>
+</a>
+
+
+<p>The previous lesson showed you how to use the convenience method
+<code>Volley.newRequestQueue</code> to set up a {@code RequestQueue}, taking advantage of
+Volley's default behaviors. This lesson walks you through the explicit steps of creating a
+{@code RequestQueue}, to allow you to supply your own custom behavior.</p>
+
+<p>This lesson also describes the recommended practice of creating a {@code RequestQueue}
+as a singleton, which makes the {@code RequestQueue} last the lifetime of your app.</p>
+
+<h2 id="network">Set Up a Network and Cache</h2>
+
+<p>A {@code RequestQueue} needs two things to do its job: a network to perform transport
+of the requests, and a cache to handle caching. There are standard implementations of these
+available in the Volley toolbox: {@code DiskBasedCache} provides a one-file-per-response
+cache with an in-memory index, and {@code BasicNetwork} provides a network transport based
+on your choice of {@link android.net.http.AndroidHttpClient} or {@link java.net.HttpURLConnection}.</p>
+
+<p>{@code BasicNetwork} is Volley's default network implementation. A {@code BasicNetwork}
+must be initialized with the HTTP client your app is using to connect to the network.
+Typically this is {@link android.net.http.AndroidHttpClient} or
+{@link java.net.HttpURLConnection}:</p>
+<ul>
+<li>Use {@link android.net.http.AndroidHttpClient} for apps targeting Android API levels
+lower than API Level 9 (Gingerbread). Prior to Gingerbread, {@link java.net.HttpURLConnection}
+was unreliable. For more discussion of this topic, see
+<a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">
+Android's HTTP Clients</a>. </li>
+
+<li>Use {@link java.net.HttpURLConnection} for apps targeting Android API Level 9
+(Gingerbread) and higher.</li>
+</ul>
+<p>To create an app that runs on all versions of Android, you can check the version of
+Android the device is running and choose the appropriate HTTP client, for example:</p>
+
+<pre>
+HttpStack stack;
+...
+// If the device is running a version >= Gingerbread...
+if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
+ // ...use HttpURLConnection for stack.
+} else {
+ // ...use AndroidHttpClient for stack.
+}
+Network network = new BasicNetwork(stack);
+</pre>
+
+<p>This snippet shows you the steps involved in setting up a
+{@code RequestQueue}:</p>
+
+<pre>
+RequestQueue mRequestQueue;
+
+// Instantiate the cache
+Cache cache = new DiskBasedCache(getCacheDir(), 1024 * 1024); // 1MB cap
+
+// Set up the network to use HttpURLConnection as the HTTP client.
+Network network = new BasicNetwork(new HurlStack());
+
+// Instantiate the RequestQueue with the cache and network.
+mRequestQueue = new RequestQueue(cache, network);
+
+// Start the queue
+mRequestQueue.start();
+
+String url ="http://www.myurl.com";
+
+// Formulate the request and handle the response.
+StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
+ new Response.Listener&lt;String&gt;() {
+ &#64;Override
+ public void onResponse(String response) {
+ // Do something with the response
+ }
+},
+ new Response.ErrorListener() {
+ &#64;Override
+ public void onErrorResponse(VolleyError error) {
+ // Handle error
+ }
+});
+
+// Add the request to the RequestQueue.
+mRequestQueue.add(stringRequest);
+...
+</pre>
+
+<p>If you just need to make a one-time request and don't want to leave the thread pool
+around, you can create the {@code RequestQueue} wherever you need it and call {@code stop()} on the
+{@code RequestQueue} once your response or error has come back, using the
+{@code Volley.newRequestQueue()} method described in <a href="simple.html">Sending a Simple
+Request</a>. But the more common use case is to create the {@code RequestQueue} as a
+singleton to keep it running for the lifetime of your app, as described in the next section.</p>
+
+
+<h2 id="singleton">Use a Singleton Pattern</h2>
+
+<p>If your application makes constant use of the network, it's probably most efficient to
+set up a single instance of {@code RequestQueue} that will last the lifetime of your app.
+You can achieve this in various ways. The recommended approach is to implement a singleton
+class that encapsulates {@code RequestQueue} and other Volley
+functionality. Another approach is to subclass {@link android.app.Application} and set up the
+{@code RequestQueue} in {@link android.app.Application#onCreate Application.onCreate()}.
+But this approach is <a href="{@docRoot}reference/android/app/Application.html">
+discouraged</a>; a static singleton can provide the same functionality in a more modular
+way. </p>
+
+<p>A key concept is that the {@code RequestQueue} must be instantiated with the
+{@link android.app.Application} context, not an {@link android.app.Activity} context. This
+ensures that the {@code RequestQueue} will last for the lifetime of your app, instead of
+being recreated every time the activity is recreated (for example, when the user
+rotates the device).
+
+<p>Here is an example of a singleton class that provides {@code RequestQueue} and
+{@code ImageLoader} functionality:</p>
+
+<pre>private static MySingleton mInstance;
+ private RequestQueue mRequestQueue;
+ private ImageLoader mImageLoader;
+ private static Context mCtx;
+
+ private MySingleton(Context context) {
+ mCtx = context;
+ mRequestQueue = getRequestQueue();
+
+ mImageLoader = new ImageLoader(mRequestQueue,
+ new ImageLoader.ImageCache() {
+ private final LruCache&lt;String, Bitmap&gt;
+ cache = new LruCache&lt;String, Bitmap&gt;(20);
+
+ &#64;Override
+ public Bitmap getBitmap(String url) {
+ return cache.get(url);
+ }
+
+ &#64;Override
+ public void putBitmap(String url, Bitmap bitmap) {
+ cache.put(url, bitmap);
+ }
+ });
+ }
+
+ public static synchronized MySingleton getInstance(Context context) {
+ if (mInstance == null) {
+ mInstance = new MySingleton(context);
+ }
+ return mInstance;
+ }
+
+ public RequestQueue getRequestQueue() {
+ if (mRequestQueue == null) {
+ // getApplicationContext() is key, it keeps you from leaking the
+ // Activity or BroadcastReceiver if someone passes one in.
+ mRequestQueue = Volley.newRequestQueue(mCtx.getApplicationContext());
+ }
+ return mRequestQueue;
+ }
+
+ public &lt;T&gt; void addToRequestQueue(Request&lt;T&gt; req) {
+ getRequestQueue().add(req);
+ }
+
+ public ImageLoader getImageLoader() {
+ return mImageLoader;
+ }
+}</pre>
+
+<p>Here are some examples of performing {@code RequestQueue} operations using the singleton
+class:</p>
+
+<pre>
+// Get a RequestQueue
+RequestQueue queue = MySingleton.getInstance(this.getApplicationContext()).
+ getRequestQueue();
+...
+
+// Add a request (in this example, called stringRequest) to your RequestQueue.
+MySingleton.getInstance(this).addToRequestQueue(stringRequest);
+</pre>
diff --git a/docs/html/training/volley/simple.jd b/docs/html/training/volley/simple.jd
new file mode 100644
index 0000000..942c57f
--- /dev/null
+++ b/docs/html/training/volley/simple.jd
@@ -0,0 +1,169 @@
+page.title=Sending a Simple Request
+
+trainingnavtop=true
+
+@jd:body
+
+<div id="tb-wrapper">
+<div id="tb">
+
+<!-- table of contents -->
+<h2>This lesson teaches you to</h2>
+<ol>
+ <li><a href="#manifest">Add the INTERNET Permission</a></li>
+ <li><a href="#simple">Use newRequestQueue</a></li>
+ <li><a href="#send">Send a Request</a></li>
+ <li><a href="#cancel">Cancel a Request</a></li>
+</ol>
+
+</div>
+</div>
+
+<a class="notice-developers-video wide" href="https://developers.google.com/events/io/sessions/325304728">
+<div>
+ <h3>Video</h3>
+ <p>Volley: Easy, Fast Networking for Android</p>
+</div>
+</a>
+
+<p>At a high level, you use Volley by creating a {@code RequestQueue} and passing it
+{@code Request} objects. The {@code RequestQueue} manages worker threads for running the
+network operations, reading from and writing to the cache, and parsing responses. Requests
+do the parsing of raw responses and Volley takes care of dispatching the parsed response
+back to the main thread for delivery.</p>
+
+<p> This lesson describes how to send a request using the <code>Volley.newRequestQueue</code>
+convenience method, which sets up a {@code RequestQueue} for you.
+See the next lesson,
+<a href="requestqueue.html">Setting Up a RequestQueue</a>, for information on how to set
+up a {@code RequestQueue} yourself.</p>
+
+<p>This lesson also describes how to add a request to a {@code RequestQueue} and cancel a
+request.</p>
+
+<h2 id="manifest">Add the INTERNET Permission</h2>
+
+<p>To use Volley, you must add the
+{@link android.Manifest.permission#INTERNET android.permission.INTERNET} permission
+to your app's manifest. Without this, your app won't be able to connect to the network.</p>
+
+
+<h2 id="simple">Use newRequestQueue</h2>
+
+<p>Volley provides a convenience method <code>Volley.newRequestQueue</code> that sets up a
+{@code RequestQueue} for you, using default values, and starts the queue. For example:</p>
+
+<pre>
+final TextView mTextView = (TextView) findViewById(R.id.text);
+...
+
+// Instantiate the RequestQueue.
+RequestQueue queue = Volley.newRequestQueue(this);
+String url ="http://www.google.com";
+
+// Request a string response from the provided URL.
+StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
+ new Response.Listener<String>() {
+ &#64;Override
+ public void onResponse(String response) {
+ // Display the first 500 characters of the response string.
+ mTextView.setText("Response is: "+ response.substring(0,500));
+ }
+}, new Response.ErrorListener() {
+ &#64;Override
+ public void onErrorResponse(VolleyError error) {
+ mTextView.setText("That didn't work!");
+ }
+});
+// Add the request to the RequestQueue.
+queue.add(stringRequest);
+</pre>
+
+<p>Volley always delivers parsed responses on the main thread. Running on the main thread
+is convenient for populating UI controls with received data, as you can freely modify UI
+controls directly from your response handler, but it's especially critical to many of the
+important semantics provided by the library, particularly related to canceling requests.
+</p>
+
+<p>See <a href="requestqueue.html">Setting Up a RequestQueue</a> for a
+description of how to set up a {@code RequestQueue} yourself, instead of using the
+<code>Volley.newRequestQueue</code> convenience method.</p>
+
+<h2 id="send">Send a Request</h2>
+
+<p>To send a request, you simply construct one and add it to the {@code RequestQueue} with
+{@code add()}, as shown above. Once you add the request it moves through the pipeline,
+gets serviced, and has its raw response parsed and delivered.</p>
+
+<p>When you call {@code add()}, Volley runs one cache processing thread and a pool of
+network dispatch threads. When you add a request to the queue, it is picked up by the cache
+thread and triaged: if the request can be serviced from cache, the cached response is
+parsed on the cache thread and the parsed response is delivered on the main thread. If the
+request cannot be serviced from cache, it is placed on the network queue. The first
+available network thread takes the request from the queue, performs the HTTP transaction,
+parsse the response on the worker thread, writes the response to cache, and posts the parsed
+response back to the main thread for delivery.</p>
+
+<p>Note that expensive operations like blocking I/O and parsing/decoding are done on worker
+threads. You can add a request from any thread, but responses are always delivered on the
+main thread.</p>
+
+<p>Figure 1 illustrates the life of a request:</p>
+
+ <img src="{@docRoot}images/training/volley-request.png"
+ alt="system bars">
+<p class="img-caption"><strong>Figure 1.</strong> Life of a request.</p>
+
+
+<h2 id="cancel">Cancel a Request</h2>
+
+<p>To cancel a request, call {@code cancel()} on your {@code Request} object. Once cancelled,
+Volley guarantees that your response handler will never be called. What this means in
+practice is that you can cancel all of your pending requests in your activity's
+{@link android.app.Activity#onStop onStop()} method and you don't have to litter your
+response handlers with checks for {@code getActivity() == null},
+whether {@code onSaveInstanceState()} has been called already, or other defensive
+boilerplate.</p>
+
+<p>To take advantage of this behavior, you would typically have to
+track all in-flight requests in order to be able to cancel them at the
+appropriate time. There is an easier way: you can associate a tag object with each
+request. You can then use this tag to provide a scope of requests to cancel. For
+example, you can tag all of your requests with the {@link android.app.Activity} they
+are being made on behalf of, and call {@code requestQueue.cancelAll(this)} from
+{@link android.app.Activity#onStop onStop()}.
+Similarly, you could tag all thumbnail image requests in a
+{@link android.support.v4.view.ViewPager} tab with their respective tabs and cancel on swipe
+to make sure that the new tab isn't being held up by requests from another one.</p>
+
+<p>Here is an example that uses a string value for the tag:</p>
+
+<ol>
+<li>Define your tag and add it to your requests.
+<pre>
+public static final String TAG = "MyTag";
+StringRequest stringRequest; // Assume this exists.
+RequestQueue mRequestQueue; // Assume this exists.
+
+// Set the tag on the request.
+stringRequest.setTag(TAG);
+
+// Add the request to the RequestQueue.
+mRequestQueue.add(stringRequest);</pre>
+</li>
+
+<li>In your activity's {@link android.app.Activity#onStop onStop()} method, cancel all requests that have this tag.
+<pre>
+&#64;Override
+protected void onStop () {
+ super.onStop();
+ if (mRequestQueue != null) {
+ mRequestQueue.cancelAll(TAG);
+ }
+}
+</pre></li></ol>
+
+<p>Take care when canceling requests. If you are depending on your response handler to
+advance a state or kick off another process, you need to account for this. Again, the
+response handler will not be called.
+</p>
diff --git a/docs/image_sources/training/volley/volley-request.graffle b/docs/image_sources/training/volley/volley-request.graffle
new file mode 100644
index 0000000..1d79b3d
--- /dev/null
+++ b/docs/image_sources/training/volley/volley-request.graffle
@@ -0,0 +1,2259 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>ActiveLayerIndex</key>
+ <integer>0</integer>
+ <key>ApplicationVersion</key>
+ <array>
+ <string>com.omnigroup.OmniGrafflePro</string>
+ <string>139.18.0.187838</string>
+ </array>
+ <key>AutoAdjust</key>
+ <true/>
+ <key>BackgroundGraphic</key>
+ <dict>
+ <key>Bounds</key>
+ <string>{{0, 0}, {576, 733}}</string>
+ <key>Class</key>
+ <string>SolidGraphic</string>
+ <key>ID</key>
+ <integer>2</integer>
+ <key>Style</key>
+ <dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ </dict>
+ <key>BaseZoom</key>
+ <integer>0</integer>
+ <key>CanvasOrigin</key>
+ <string>{0, 0}</string>
+ <key>ColumnAlign</key>
+ <integer>1</integer>
+ <key>ColumnSpacing</key>
+ <real>36</real>
+ <key>CreationDate</key>
+ <string>2014-03-24 22:38:51 +0000</string>
+ <key>Creator</key>
+ <string>Katie McCormick</string>
+ <key>DisplayScale</key>
+ <string>1 0/72 in = 1 0/72 in</string>
+ <key>GraphDocumentVersion</key>
+ <integer>8</integer>
+ <key>GraphicsList</key>
+ <array>
+ <dict>
+ <key>Bounds</key>
+ <string>{{68.798424333456921, 309.90064645900816}, {70.999998092651367, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>Vertical</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>1990</integer>
+ <key>Rotation</key>
+ <real>88.863800048828125</real>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Align</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
+
+\f0\fs24 \cf0 cache miss}</string>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{164.31081962585449, 233}, {59, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>1989</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Align</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
+
+\f0\fs24 \cf0 cache hit}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{109, 567.5}, {72, 24}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FitText</key>
+ <string>YES</string>
+ <key>Flow</key>
+ <string>Resize</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Helvetica</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>1987</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Align</key>
+ <integer>0</integer>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
+
+\f0\fs24 \cf0 round-robin}</string>
+ </dict>
+ <key>Wrap</key>
+ <string>NO</string>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>209</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1986</integer>
+ <key>Points</key>
+ <array>
+ <string>{362.483096786499, 520.41741752624512}</string>
+ <string>{439.59458923339844, 165.16970062255859}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>213</integer>
+ <key>Info</key>
+ <integer>7</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>209</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1985</integer>
+ <key>Points</key>
+ <array>
+ <string>{362.483096786499, 461.33483529090881}</string>
+ <string>{439.59458923339844, 165.16970062255859}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>204</integer>
+ <key>Info</key>
+ <integer>7</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>209</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1984</integer>
+ <key>Points</key>
+ <array>
+ <string>{362.48308152770994, 402.2522608306885}</string>
+ <string>{439.59458923339844, 165.16970062255859}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>203</integer>
+ <key>Info</key>
+ <integer>7</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>209</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1983</integer>
+ <key>Points</key>
+ <array>
+ <string>{294.65540856933592, 227.99996948242188}</string>
+ <string>{381.3049268594778, 164.77353614247437}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>210</integer>
+ <key>Info</key>
+ <integer>6</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>4</integer>
+ <key>Info</key>
+ <integer>6</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1982</integer>
+ <key>Points</key>
+ <array>
+ <string>{94.216227905273399, 165.16970062255859}</string>
+ <string>{92.966230102539043, 227.99999237060547}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>157</integer>
+ <key>Info</key>
+ <integer>5</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>213</integer>
+ <key>Info</key>
+ <integer>9</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1980</integer>
+ <key>Points</key>
+ <array>
+ <string>{179.26087951660151, 462.43391850741568}</string>
+ <string>{224.48312730407713, 514.92974541704564}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>1973</integer>
+ <key>Info</key>
+ <integer>3</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>204</integer>
+ <key>Info</key>
+ <integer>8</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1979</integer>
+ <key>Points</key>
+ <array>
+ <string>{179.76073189455099, 462.42177007636207}</string>
+ <string>{224.48312730407716, 461.33483529090881}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>1973</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>203</integer>
+ <key>Info</key>
+ <integer>8</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1978</integer>
+ <key>Points</key>
+ <array>
+ <string>{179.26087951660151, 462.43391850741568}</string>
+ <string>{224.48311204528804, 402.2522608306885}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>1973</integer>
+ <key>Info</key>
+ <integer>3</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>1973</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1975</integer>
+ <key>Points</key>
+ <array>
+ <string>{92.966230102539043, 286.16969299316406}</string>
+ <string>{92.966239929199205, 356.41910654608148}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>4</integer>
+ <key>Info</key>
+ <integer>5</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>LineGraphic</string>
+ <key>Head</key>
+ <dict>
+ <key>ID</key>
+ <integer>210</integer>
+ <key>Info</key>
+ <integer>8</integer>
+ </dict>
+ <key>ID</key>
+ <integer>1974</integer>
+ <key>Points</key>
+ <array>
+ <string>{150.81081933593748, 257.08484268188477}</string>
+ <string>{236.81081933593748, 257.08481979370117}</string>
+ </array>
+ <key>Style</key>
+ <dict>
+ <key>stroke</key>
+ <dict>
+ <key>HeadArrow</key>
+ <string>FilledArrow</string>
+ <key>Legacy</key>
+ <true/>
+ <key>TailArrow</key>
+ <string>0</string>
+ </dict>
+ </dict>
+ <key>Tail</key>
+ <dict>
+ <key>ID</key>
+ <integer>4</integer>
+ <key>Info</key>
+ <integer>7</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{391, 540.66744232177734}, {137.99996948242188, 23.499996185302734}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>214</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.2</string>
+ <key>g</key>
+ <string>0.733333</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.131021</string>
+ <key>g</key>
+ <string>0.363196</string>
+ <key>r</key>
+ <string>0.725948</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 network threads}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{224.48312730407713, 508.66741943359375}, {137.99996948242188, 23.499996185302734}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>213</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.2</string>
+ <key>g</key>
+ <string>0.733333</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.131021</string>
+ <key>g</key>
+ <string>0.363196</string>
+ <key>r</key>
+ <string>0.725948</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 HTTP...}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{23.966230102539043, 498}, {137.99998474121094, 58.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>212</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.2</string>
+ <key>g</key>
+ <string>0.733333</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.131021</string>
+ <key>g</key>
+ <string>0.363196</string>
+ <key>r</key>
+ <string>0.725948</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 Request dequeued by NetworkDispatcher}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{23.966245361328106, 432.24999237060547}, {137.99998474121094, 58.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>211</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.2</string>
+ <key>g</key>
+ <string>0.733333</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.131021</string>
+ <key>g</key>
+ <string>0.363196</string>
+ <key>r</key>
+ <string>0.725948</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 Request dequeued by NetworkDispatcher}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{236.81081933593748, 227.99996948242188}, {115.68917846679688, 58.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>10</real>
+ </dict>
+ <key>ID</key>
+ <integer>210</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.8</string>
+ <key>r</key>
+ <string>0.6</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.6</string>
+ <key>r</key>
+ <string>0.4</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 Request read from cache and parsed}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{380.5, 107}, {118.18917846679688, 58.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>209</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.898039</string>
+ <key>g</key>
+ <string>0.709804</string>
+ <key>r</key>
+ <string>0.2</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.93512</string>
+ <key>g</key>
+ <string>0.472602</string>
+ <key>r</key>
+ <string>0.333854</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 Parsed response delivered on main thread}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{391, 508.66740417480469}, {137.99996948242188, 23.499996185302734}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>10</real>
+ </dict>
+ <key>ID</key>
+ <integer>207</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.8</string>
+ <key>r</key>
+ <string>0.6</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.6</string>
+ <key>r</key>
+ <string>0.4</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 cache thread}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{391, 476.6673583984375}, {137.99996948242188, 23.499980926513672}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>206</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.898039</string>
+ <key>g</key>
+ <string>0.709804</string>
+ <key>r</key>
+ <string>0.2</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.93512</string>
+ <key>g</key>
+ <string>0.472602</string>
+ <key>r</key>
+ <string>0.333854</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 main thread}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{224.48312730407713, 421.74998497962952}, {137.99996948242188, 79.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>204</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.2</string>
+ <key>g</key>
+ <string>0.733333</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.131021</string>
+ <key>g</key>
+ <string>0.363196</string>
+ <key>r</key>
+ <string>0.725948</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 HTTP transaction, response parse, cache write (if applicable)}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{224.48311204528807, 390.50226273803713}, {137.99996948242188, 23.499996185302734}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>203</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.2</string>
+ <key>g</key>
+ <string>0.733333</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.131021</string>
+ <key>g</key>
+ <string>0.363196</string>
+ <key>r</key>
+ <string>0.725948</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 HTTP...}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{23.966245361328106, 366.5}, {137.99998474121094, 58.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>200</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.2</string>
+ <key>g</key>
+ <string>0.733333</string>
+ <key>r</key>
+ <string>1</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.131021</string>
+ <key>g</key>
+ <string>0.363196</string>
+ <key>r</key>
+ <string>0.725948</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 Request dequeued by NetworkDispatcher}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{35.121640869140606, 227.99999237060547}, {115.68917846679688, 58.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>10</real>
+ </dict>
+ <key>ID</key>
+ <integer>4</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.8</string>
+ <key>r</key>
+ <string>0.6</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0.6</string>
+ <key>r</key>
+ <string>0.4</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 Request dequeued by CacheDispatcher}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{35.121638671874962, 107}, {118.18917846679688, 58.169700622558594}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>157</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{1, 1}</string>
+ <string>{1, -1}</string>
+ <string>{-1, -1}</string>
+ <string>{-1, 1}</string>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ <string>{-0.5, -0.233518}</string>
+ <string>{-0.49144199999999999, 0.26006299999999999}</string>
+ <string>{0.50711799999999996, -0.22408600000000001}</string>
+ <string>{0.50711799999999996, 0.267179}</string>
+ <string>{-0.27431, -0.474028}</string>
+ <string>{0.27977999999999997, -0.47847800000000001}</string>
+ <string>{0.29393799999999998, 0.54304399999999997}</string>
+ <string>{-0.28623199999999999, 0.55380399999999996}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.898039</string>
+ <key>g</key>
+ <string>0.709804</string>
+ <key>r</key>
+ <string>0.2</string>
+ </dict>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.35</string>
+ <key>b</key>
+ <string>0.328823</string>
+ <key>g</key>
+ <string>0.328823</string>
+ <key>r</key>
+ <string>0.328823</string>
+ </dict>
+ <key>Fuzziness</key>
+ <real>1.5349206924438477</real>
+ <key>ShadowVector</key>
+ <string>{0, 1}</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.93512</string>
+ <key>g</key>
+ <string>0.472602</string>
+ <key>r</key>
+ <string>0.333854</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>2</real>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Text</key>
+ <string>{\rtf1\ansi\ansicpg1252\cocoartf1265\cocoasubrtf190
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc
+
+\f0\b\fs24 \cf0 Request added to queue in priority order}</string>
+ <key>VerticalPad</key>
+ <integer>0</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Class</key>
+ <string>Group</string>
+ <key>Graphics</key>
+ <array>
+ <dict>
+ <key>Bounds</key>
+ <string>{{20.00199264625337, 331.00000000000006}, {145.92853034472586, 25.419100784950434}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.65</string>
+ <key>b</key>
+ <string>0</string>
+ <key>g</key>
+ <string>0</string>
+ <key>r</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-Condensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>1972</integer>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>Pad</key>
+ <integer>2</integer>
+ </dict>
+ </dict>
+ <dict>
+ <key>Bounds</key>
+ <string>{{6.671600341796875, 356.41910654608148}, {172.58927917480466, 212.02962392266838}}</string>
+ <key>Class</key>
+ <string>ShapedGraphic</string>
+ <key>FontInfo</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>a</key>
+ <string>0.65</string>
+ <key>w</key>
+ <string>0</string>
+ </dict>
+ <key>Font</key>
+ <string>Roboto-BoldCondensed</string>
+ <key>Size</key>
+ <real>12</real>
+ </dict>
+ <key>ID</key>
+ <integer>1973</integer>
+ <key>Magnets</key>
+ <array>
+ <string>{0, 1}</string>
+ <string>{0, -1}</string>
+ <string>{1, 0}</string>
+ <string>{-1, 0}</string>
+ </array>
+ <key>Shape</key>
+ <string>Rectangle</string>
+ <key>Style</key>
+ <dict>
+ <key>fill</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>shadow</key>
+ <dict>
+ <key>Draws</key>
+ <string>NO</string>
+ </dict>
+ <key>stroke</key>
+ <dict>
+ <key>Color</key>
+ <dict>
+ <key>b</key>
+ <string>0.578326</string>
+ <key>g</key>
+ <string>0.578615</string>
+ <key>r</key>
+ <string>0.578453</string>
+ </dict>
+ <key>CornerRadius</key>
+ <real>5</real>
+ <key>Pattern</key>
+ <integer>1</integer>
+ </dict>
+ </dict>
+ <key>Text</key>
+ <dict>
+ <key>VerticalPad</key>
+ <integer>10</integer>
+ </dict>
+ <key>TextPlacement</key>
+ <integer>0</integer>
+ </dict>
+ </array>
+ <key>ID</key>
+ <integer>1971</integer>
+ </dict>
+ </array>
+ <key>GridInfo</key>
+ <dict/>
+ <key>GuidesLocked</key>
+ <string>NO</string>
+ <key>GuidesVisible</key>
+ <string>YES</string>
+ <key>HPages</key>
+ <integer>1</integer>
+ <key>ImageCounter</key>
+ <integer>1</integer>
+ <key>KeepToScale</key>
+ <false/>
+ <key>Layers</key>
+ <array>
+ <dict>
+ <key>Lock</key>
+ <string>NO</string>
+ <key>Name</key>
+ <string>Layer 1</string>
+ <key>Print</key>
+ <string>YES</string>
+ <key>View</key>
+ <string>YES</string>
+ </dict>
+ </array>
+ <key>LayoutInfo</key>
+ <dict>
+ <key>Animate</key>
+ <string>NO</string>
+ <key>circoMinDist</key>
+ <real>18</real>
+ <key>circoSeparation</key>
+ <real>0.0</real>
+ <key>layoutEngine</key>
+ <string>dot</string>
+ <key>neatoSeparation</key>
+ <real>0.0</real>
+ <key>twopiSeparation</key>
+ <real>0.0</real>
+ </dict>
+ <key>LinksVisible</key>
+ <string>NO</string>
+ <key>MagnetsVisible</key>
+ <string>NO</string>
+ <key>MasterSheets</key>
+ <array/>
+ <key>ModificationDate</key>
+ <string>2014-03-24 23:38:43 +0000</string>
+ <key>Modifier</key>
+ <string>Katie McCormick</string>
+ <key>NotesVisible</key>
+ <string>NO</string>
+ <key>Orientation</key>
+ <integer>2</integer>
+ <key>OriginVisible</key>
+ <string>NO</string>
+ <key>PageBreaks</key>
+ <string>YES</string>
+ <key>PrintInfo</key>
+ <dict>
+ <key>NSBottomMargin</key>
+ <array>
+ <string>float</string>
+ <string>41</string>
+ </array>
+ <key>NSHorizonalPagination</key>
+ <array>
+ <string>coded</string>
+ <string>BAtzdHJlYW10eXBlZIHoA4QBQISEhAhOU051bWJlcgCEhAdOU1ZhbHVlAISECE5TT2JqZWN0AIWEASqEhAFxlwCG</string>
+ </array>
+ <key>NSLeftMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSPaperSize</key>
+ <array>
+ <string>size</string>
+ <string>{612, 792}</string>
+ </array>
+ <key>NSPrintReverseOrientation</key>
+ <array>
+ <string>int</string>
+ <string>0</string>
+ </array>
+ <key>NSRightMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ <key>NSTopMargin</key>
+ <array>
+ <string>float</string>
+ <string>18</string>
+ </array>
+ </dict>
+ <key>PrintOnePage</key>
+ <false/>
+ <key>ReadOnly</key>
+ <string>NO</string>
+ <key>RowAlign</key>
+ <integer>1</integer>
+ <key>RowSpacing</key>
+ <real>36</real>
+ <key>SheetTitle</key>
+ <string>Canvas 1</string>
+ <key>SmartAlignmentGuidesActive</key>
+ <string>YES</string>
+ <key>SmartDistanceGuidesActive</key>
+ <string>YES</string>
+ <key>UniqueID</key>
+ <integer>1</integer>
+ <key>UseEntirePage</key>
+ <false/>
+ <key>VPages</key>
+ <integer>1</integer>
+ <key>WindowInfo</key>
+ <dict>
+ <key>CurrentSheet</key>
+ <integer>0</integer>
+ <key>ExpandedCanvases</key>
+ <array>
+ <dict>
+ <key>name</key>
+ <string>Canvas 1</string>
+ </dict>
+ </array>
+ <key>Frame</key>
+ <string>{{159, 135}, {899, 874}}</string>
+ <key>ListView</key>
+ <true/>
+ <key>OutlineWidth</key>
+ <integer>142</integer>
+ <key>RightSidebar</key>
+ <false/>
+ <key>ShowRuler</key>
+ <true/>
+ <key>Sidebar</key>
+ <true/>
+ <key>SidebarWidth</key>
+ <integer>120</integer>
+ <key>VisibleRegion</key>
+ <string>{{-94, -1}, {764, 735}}</string>
+ <key>Zoom</key>
+ <real>1</real>
+ <key>ZoomValues</key>
+ <array>
+ <array>
+ <string>Canvas 1</string>
+ <real>1</real>
+ <real>1</real>
+ </array>
+ </array>
+ </dict>
+</dict>
+</plist>
diff --git a/graphics/java/android/graphics/BitmapFactory.java b/graphics/java/android/graphics/BitmapFactory.java
index c20502f..bc20ea5 100644
--- a/graphics/java/android/graphics/BitmapFactory.java
+++ b/graphics/java/android/graphics/BitmapFactory.java
@@ -260,7 +260,11 @@ public class BitmapFactory {
public boolean inScaled;
/**
- * If this is set to true, then the resulting bitmap will allocate its
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#L}, this is
+ * ignored.
+ *
+ * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, if this
+ * is set to true, then the resulting bitmap will allocate its
* pixels such that they can be purged if the system needs to reclaim
* memory. In that instance, when the pixels need to be accessed again
* (e.g. the bitmap is drawn, getPixels() is called), they will be
@@ -287,14 +291,20 @@ public class BitmapFactory {
* android.graphics.BitmapFactory.Options)} or {@link #decodeFile(String,
* android.graphics.BitmapFactory.Options)}.</p>
*/
+ @Deprecated
public boolean inPurgeable;
/**
- * This field works in conjuction with inPurgeable. If inPurgeable is
- * false, then this field is ignored. If inPurgeable is true, then this
- * field determines whether the bitmap can share a reference to the
- * input data (inputstream, array, etc.) or if it must make a deep copy.
+ * @deprecated As of {@link android.os.Build.VERSION_CODES#L}, this is
+ * ignored.
+ *
+ * In {@link android.os.Build.VERSION_CODES#KITKAT} and below, this
+ * field works in conjuction with inPurgeable. If inPurgeable is false,
+ * then this field is ignored. If inPurgeable is true, then this field
+ * determines whether the bitmap can share a reference to the input
+ * data (inputstream, array, etc.) or if it must make a deep copy.
*/
+ @Deprecated
public boolean inInputShareable;
/**
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index bd868f2..12877de 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -242,21 +242,27 @@ public class Canvas {
*
* @return true if the device that the current layer draws into is opaque
*/
- public native boolean isOpaque();
+ public boolean isOpaque() {
+ return native_isOpaque(mNativeCanvasWrapper);
+ }
/**
* Returns the width of the current drawing layer
*
* @return the width of the current drawing layer
*/
- public native int getWidth();
+ public int getWidth() {
+ return native_getWidth(mNativeCanvasWrapper);
+ }
/**
* Returns the height of the current drawing layer
*
* @return the height of the current drawing layer
*/
- public native int getHeight();
+ public int getHeight() {
+ return native_getHeight(mNativeCanvasWrapper);
+ }
/**
* <p>Returns the target density of the canvas. The default density is
@@ -343,7 +349,9 @@ public class Canvas {
*
* @return The value to pass to restoreToCount() to balance this save()
*/
- public native int save();
+ public int save() {
+ return native_save(mNativeCanvasWrapper, MATRIX_SAVE_FLAG | CLIP_SAVE_FLAG);
+ }
/**
* Based on saveFlags, can save the current matrix and clip onto a private
@@ -356,7 +364,9 @@ public class Canvas {
* to save/restore
* @return The value to pass to restoreToCount() to balance this save()
*/
- public native int save(int saveFlags);
+ public int save(int saveFlags) {
+ return native_save(mNativeCanvasWrapper, saveFlags);
+ }
/**
* This behaves the same as save(), but in addition it allocates an
@@ -375,7 +385,8 @@ public class Canvas {
* @return value to pass to restoreToCount() to balance this save()
*/
public int saveLayer(RectF bounds, Paint paint, int saveFlags) {
- return native_saveLayer(mNativeCanvasWrapper, bounds,
+ return native_saveLayer(mNativeCanvasWrapper,
+ bounds.left, bounds.top, bounds.right, bounds.bottom,
paint != null ? paint.mNativePaint : 0,
saveFlags);
}
@@ -422,7 +433,9 @@ public class Canvas {
*/
public int saveLayerAlpha(RectF bounds, int alpha, int saveFlags) {
alpha = Math.min(255, Math.max(0, alpha));
- return native_saveLayerAlpha(mNativeCanvasWrapper, bounds, alpha, saveFlags);
+ return native_saveLayerAlpha(mNativeCanvasWrapper,
+ bounds.left, bounds.top, bounds.right, bounds.bottom,
+ alpha, saveFlags);
}
/**
@@ -453,13 +466,17 @@ public class Canvas {
* modifications to the matrix/clip state since the last save call. It is
* an error to call restore() more times than save() was called.
*/
- public native void restore();
+ public void restore() {
+ native_restore(mNativeCanvasWrapper);
+ }
/**
* Returns the number of matrix/clip states on the Canvas' private stack.
* This will equal # save() calls - # restore() calls.
*/
- public native int getSaveCount();
+ public int getSaveCount() {
+ return native_getSaveCount(mNativeCanvasWrapper);
+ }
/**
* Efficient way to pop any calls to save() that happened after the save
@@ -474,7 +491,9 @@ public class Canvas {
*
* @param saveCount The save level to restore to.
*/
- public native void restoreToCount(int saveCount);
+ public void restoreToCount(int saveCount) {
+ native_restoreToCount(mNativeCanvasWrapper, saveCount);
+ }
/**
* Preconcat the current matrix with the specified translation
@@ -482,7 +501,9 @@ public class Canvas {
* @param dx The distance to translate in X
* @param dy The distance to translate in Y
*/
- public native void translate(float dx, float dy);
+ public void translate(float dx, float dy) {
+ native_translate(mNativeCanvasWrapper, dx, dy);
+ }
/**
* Preconcat the current matrix with the specified scale.
@@ -490,7 +511,9 @@ public class Canvas {
* @param sx The amount to scale in X
* @param sy The amount to scale in Y
*/
- public native void scale(float sx, float sy);
+ public void scale(float sx, float sy) {
+ native_scale(mNativeCanvasWrapper, sx, sy);
+ }
/**
* Preconcat the current matrix with the specified scale.
@@ -511,7 +534,9 @@ public class Canvas {
*
* @param degrees The amount to rotate, in degrees
*/
- public native void rotate(float degrees);
+ public void rotate(float degrees) {
+ native_rotate(mNativeCanvasWrapper, degrees);
+ }
/**
* Preconcat the current matrix with the specified rotation.
@@ -532,7 +557,9 @@ public class Canvas {
* @param sx The amount to skew in X
* @param sy The amount to skew in Y
*/
- public native void skew(float sx, float sy);
+ public void skew(float sx, float sy) {
+ native_skew(mNativeCanvasWrapper, sx, sy);
+ }
/**
* Preconcat the current matrix with the specified matrix. If the specified
@@ -615,8 +642,11 @@ public class Canvas {
* @param rect The rectangle to intersect with the current clip.
* @return true if the resulting clip is non-empty
*/
- public native boolean clipRect(RectF rect);
-
+ public boolean clipRect(RectF rect) {
+ return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+ Region.Op.INTERSECT.nativeInt);
+ }
+
/**
* Intersect the current clip with the specified rectangle, which is
* expressed in local coordinates.
@@ -624,7 +654,10 @@ public class Canvas {
* @param rect The rectangle to intersect with the current clip.
* @return true if the resulting clip is non-empty
*/
- public native boolean clipRect(Rect rect);
+ public boolean clipRect(Rect rect) {
+ return native_clipRect(mNativeCanvasWrapper, rect.left, rect.top, rect.right, rect.bottom,
+ Region.Op.INTERSECT.nativeInt);
+ }
/**
* Modify the current clip with the specified rectangle, which is
@@ -658,7 +691,10 @@ public class Canvas {
* clip
* @return true if the resulting clip is non-empty
*/
- public native boolean clipRect(float left, float top, float right, float bottom);
+ public boolean clipRect(float left, float top, float right, float bottom) {
+ return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom,
+ Region.Op.INTERSECT.nativeInt);
+ }
/**
* Intersect the current clip with the specified rectangle, which is
@@ -673,7 +709,10 @@ public class Canvas {
* clip
* @return true if the resulting clip is non-empty
*/
- public native boolean clipRect(int left, int top, int right, int bottom);
+ public boolean clipRect(int left, int top, int right, int bottom) {
+ return native_clipRect(mNativeCanvasWrapper, left, top, right, bottom,
+ Region.Op.INTERSECT.nativeInt);
+ }
/**
* Modify the current clip with the specified path.
@@ -780,7 +819,8 @@ public class Canvas {
* does not intersect with the canvas' clip
*/
public boolean quickReject(RectF rect, EdgeType type) {
- return native_quickReject(mNativeCanvasWrapper, rect);
+ return native_quickReject(mNativeCanvasWrapper,
+ rect.left, rect.top, rect.right, rect.bottom);
}
/**
@@ -925,7 +965,9 @@ public class Canvas {
* "points" that are drawn is really (count >> 1).
* @param paint The paint used to draw the points
*/
- public native void drawPoints(float[] pts, int offset, int count, Paint paint);
+ public void drawPoints(float[] pts, int offset, int count, Paint paint) {
+ native_drawPoints(mNativeCanvasWrapper, pts, offset, count, paint.mNativePaint);
+ }
/**
* Helper for drawPoints() that assumes you want to draw the entire array
@@ -937,7 +979,9 @@ public class Canvas {
/**
* Helper for drawPoints() for drawing a single point.
*/
- public native void drawPoint(float x, float y, Paint paint);
+ public void drawPoint(float x, float y, Paint paint) {
+ native_drawPoint(mNativeCanvasWrapper, x, y, paint.mNativePaint);
+ }
/**
* Draw a line segment with the specified start and stop x,y coordinates,
@@ -970,7 +1014,9 @@ public class Canvas {
* (count >> 2).
* @param paint The paint used to draw the points
*/
- public native void drawLines(float[] pts, int offset, int count, Paint paint);
+ public void drawLines(float[] pts, int offset, int count, Paint paint) {
+ native_drawLines(mNativeCanvasWrapper, pts, offset, count, paint.mNativePaint);
+ }
public void drawLines(float[] pts, Paint paint) {
drawLines(pts, 0, pts.length, paint);
@@ -984,7 +1030,8 @@ public class Canvas {
* @param paint The paint used to draw the rect
*/
public void drawRect(RectF rect, Paint paint) {
- native_drawRect(mNativeCanvasWrapper, rect, paint.mNativePaint);
+ native_drawRect(mNativeCanvasWrapper,
+ rect.left, rect.top, rect.right, rect.bottom, paint.mNativePaint);
}
/**
@@ -1764,21 +1811,30 @@ public class Canvas {
private static native void native_setBitmap(long canvasHandle,
long bitmapHandle,
boolean copyState);
- private static native int native_saveLayer(long nativeCanvas,
- RectF bounds,
- long nativePaint,
- int layerFlags);
+ private static native boolean native_isOpaque(long canvasHandle);
+ private static native int native_getWidth(long canvasHandle);
+ private static native int native_getHeight(long canvasHandle);
+
+ private static native int native_save(long canvasHandle, int saveFlags);
private static native int native_saveLayer(long nativeCanvas, float l,
float t, float r, float b,
long nativePaint,
int layerFlags);
- private static native int native_saveLayerAlpha(long nativeCanvas,
- RectF bounds, int alpha,
- int layerFlags);
private static native int native_saveLayerAlpha(long nativeCanvas, float l,
float t, float r, float b,
int alpha, int layerFlags);
-
+ private static native void native_restore(long canvasHandle);
+ private static native void native_restoreToCount(long canvasHandle,
+ int saveCount);
+ private static native int native_getSaveCount(long canvasHandle);
+
+ private static native void native_translate(long canvasHandle,
+ float dx, float dy);
+ private static native void native_scale(long canvasHandle,
+ float sx, float sy);
+ private static native void native_rotate(long canvasHandle, float degrees);
+ private static native void native_skew(long canvasHandle,
+ float sx, float sy);
private static native void native_concat(long nativeCanvas,
long nativeMatrix);
private static native void native_setMatrix(long nativeCanvas,
@@ -1800,8 +1856,6 @@ public class Canvas {
private static native void native_getCTM(long nativeCanvas,
long nativeMatrix);
private static native boolean native_quickReject(long nativeCanvas,
- RectF rect);
- private static native boolean native_quickReject(long nativeCanvas,
long nativePath);
private static native boolean native_quickReject(long nativeCanvas,
float left, float top,
@@ -1815,11 +1869,17 @@ public class Canvas {
int mode);
private static native void native_drawPaint(long nativeCanvas,
long nativePaint);
+ private static native void native_drawPoint(long canvasHandle, float x, float y,
+ long paintHandle);
+ private static native void native_drawPoints(long canvasHandle, float[] pts,
+ int offset, int count,
+ long paintHandle);
private static native void native_drawLine(long nativeCanvas, float startX,
float startY, float stopX,
float stopY, long nativePaint);
- private static native void native_drawRect(long nativeCanvas, RectF rect,
- long nativePaint);
+ private static native void native_drawLines(long canvasHandle, float[] pts,
+ int offset, int count,
+ long paintHandle);
private static native void native_drawRect(long nativeCanvas, float left,
float top, float right,
float bottom,
diff --git a/graphics/java/android/graphics/FontFamily.java b/graphics/java/android/graphics/FontFamily.java
index 6802b9a..11d3165 100644
--- a/graphics/java/android/graphics/FontFamily.java
+++ b/graphics/java/android/graphics/FontFamily.java
@@ -16,6 +16,8 @@
package android.graphics;
+import android.content.res.AssetManager;
+
import java.io.File;
/**
@@ -58,11 +60,17 @@ public class FontFamily {
}
}
- public boolean addFont(File path) {
- return nAddFont(mNativePtr, path.getAbsolutePath());
+ public boolean addFont(String path) {
+ return nAddFont(mNativePtr, path);
+ }
+
+ public boolean addFontFromAsset(AssetManager mgr, String path) {
+ return nAddFontFromAsset(mNativePtr, mgr, path);
}
- static native long nCreateFamily(String lang, int variant);
- static native void nUnrefFamily(long nativePtr);
- static native boolean nAddFont(long nativeFamily, String path);
+ private static native long nCreateFamily(String lang, int variant);
+ private static native void nUnrefFamily(long nativePtr);
+ private static native boolean nAddFont(long nativeFamily, String path);
+ private static native boolean nAddFontFromAsset(long nativeFamily, AssetManager mgr,
+ String path);
}
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 92cfd6b..4268a24 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -2131,7 +2131,7 @@ public class Paint {
if ((index | count) < 0 || index + count > text.length) {
throw new ArrayIndexOutOfBoundsException();
}
- native_getTextPath(mNativePaint, mBidiFlags, text, index, count, x, y,
+ native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, index, count, x, y,
path.ni());
}
@@ -2153,7 +2153,7 @@ public class Paint {
if ((start | end | (end - start) | (text.length() - end)) < 0) {
throw new IndexOutOfBoundsException();
}
- native_getTextPath(mNativePaint, mBidiFlags, text, start, end, x, y,
+ native_getTextPath(mNativePaint, mNativeTypeface, mBidiFlags, text, start, end, x, y,
path.ni());
}
@@ -2174,7 +2174,7 @@ public class Paint {
if (bounds == null) {
throw new NullPointerException("need bounds Rect");
}
- nativeGetStringBounds(mNativePaint, text, start, end, mBidiFlags, bounds);
+ nativeGetStringBounds(mNativePaint, mNativeTypeface, text, start, end, mBidiFlags, bounds);
}
/**
@@ -2194,7 +2194,8 @@ public class Paint {
if (bounds == null) {
throw new NullPointerException("need bounds Rect");
}
- nativeGetCharArrayBounds(mNativePaint, text, index, count, mBidiFlags, bounds);
+ nativeGetCharArrayBounds(mNativePaint, mNativeTypeface, text, index, count, mBidiFlags,
+ bounds);
}
@Override
@@ -2261,13 +2262,13 @@ public class Paint {
private native int native_getTextRunCursor(long native_object, String text,
int contextStart, int contextEnd, int flags, int offset, int cursorOpt);
- private static native void native_getTextPath(long native_object, int bidiFlags,
- char[] text, int index, int count, float x, float y, long path);
- private static native void native_getTextPath(long native_object, int bidiFlags,
- String text, int start, int end, float x, float y, long path);
- private static native void nativeGetStringBounds(long nativePaint,
+ private static native void native_getTextPath(long native_object, long native_typeface,
+ int bidiFlags, char[] text, int index, int count, float x, float y, long path);
+ private static native void native_getTextPath(long native_object, long native_typeface,
+ int bidiFlags, String text, int start, int end, float x, float y, long path);
+ private static native void nativeGetStringBounds(long nativePaint, long native_typeface,
String text, int start, int end, int bidiFlags, Rect bounds);
- private static native void nativeGetCharArrayBounds(long nativePaint,
+ private static native void nativeGetCharArrayBounds(long nativePaint, long native_typeface,
char[] text, int index, int count, int bidiFlags, Rect bounds);
private static native void finalizer(long nativePaint);
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index 2b07c3f..cb48de2 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -178,6 +178,15 @@ public class Typeface {
* @return The new typeface.
*/
public static Typeface createFromAsset(AssetManager mgr, String path) {
+ if (sFallbackFonts != null) {
+ FontFamily fontFamily = new FontFamily();
+ if (fontFamily.addFontFromAsset(mgr, path)) {
+ FontFamily[] families = { fontFamily };
+ return createFromFamiliesWithDefault(families);
+ } else {
+ return null;
+ }
+ }
return new Typeface(nativeCreateFromAsset(mgr, path));
}
@@ -188,7 +197,7 @@ public class Typeface {
* @return The new typeface.
*/
public static Typeface createFromFile(File path) {
- return new Typeface(nativeCreateFromFile(path.getAbsolutePath()));
+ return createFromFile(path.getAbsolutePath());
}
/**
@@ -198,6 +207,15 @@ public class Typeface {
* @return The new typeface.
*/
public static Typeface createFromFile(String path) {
+ if (sFallbackFonts != null) {
+ FontFamily fontFamily = new FontFamily();
+ if (fontFamily.addFont(path)) {
+ FontFamily[] families = { fontFamily };
+ return createFromFamiliesWithDefault(families);
+ } else {
+ return null;
+ }
+ }
return new Typeface(nativeCreateFromFile(path));
}
@@ -247,7 +265,7 @@ public class Typeface {
// TODO: expand to handle attributes like lang and variant
FontFamily fontFamily = new FontFamily(family.lang, family.variant);
for (String fontFile : family.fontFiles) {
- fontFamily.addFont(new File(fontFile));
+ fontFamily.addFont(fontFile);
}
return fontFamily;
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index a37ceef..e8024f7 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -260,7 +260,7 @@ public class AnimatedRotateDrawable extends Drawable implements Drawable.Callbac
continue;
}
- if ((drawable = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme)) == null) {
+ if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
Log.w("drawable", "Bad element under <animated-rotate>: "
+ parser .getName());
}
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 42872e9..a5a074c 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -301,7 +301,7 @@ public class AnimatedStateListDrawable extends StateListDrawable {
+ ": <item> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
final AnimationDrawable anim;
@@ -355,7 +355,7 @@ public class AnimatedStateListDrawable extends StateListDrawable {
+ ": <item> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
return mState.addStateSet(states, dr, keyframeId);
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index da4bc10..0ee253a 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -293,7 +293,7 @@ public class AnimationDrawable extends DrawableContainer implements Runnable, An
": <item> tag requires a 'drawable' attribute or child tag" +
" defining a drawable");
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
mAnimationState.addFrame(dr, duration);
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 3dbd235..3ac9972 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -95,7 +95,7 @@ public class ClipDrawable extends Drawable implements Drawable.Callback {
if (type != XmlPullParser.START_TAG) {
continue;
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
if (dr == null) {
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index cc2a595..3a32e80 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -892,13 +892,9 @@ public abstract class Drawable {
* Create a drawable from an inputstream
*/
public static Drawable createFromStream(InputStream is, String srcName) {
- return createFromStreamThemed(is, srcName, null);
- }
-
- public static Drawable createFromStreamThemed(InputStream is, String srcName, Theme theme) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
try {
- return createFromResourceStreamThemed(null, null, is, srcName, theme);
+ return createFromResourceStream(null, null, is, srcName);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
@@ -910,14 +906,9 @@ public abstract class Drawable {
*/
public static Drawable createFromResourceStream(Resources res, TypedValue value,
InputStream is, String srcName) {
- return createFromResourceStreamThemed(res, value, is, srcName, null);
- }
-
- public static Drawable createFromResourceStreamThemed(Resources res, TypedValue value,
- InputStream is, String srcName, Theme theme) {
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, srcName != null ? srcName : "Unknown drawable");
try {
- return createFromResourceStreamThemed(res, value, is, srcName, null, theme);
+ return createFromResourceStream(res, value, is, srcName, null);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
@@ -929,11 +920,6 @@ public abstract class Drawable {
*/
public static Drawable createFromResourceStream(Resources res, TypedValue value,
InputStream is, String srcName, BitmapFactory.Options opts) {
- return createFromResourceStreamThemed(res, value, is, srcName, opts, null);
- }
-
- public static Drawable createFromResourceStreamThemed(Resources res, TypedValue value,
- InputStream is, String srcName, BitmapFactory.Options opts, Theme theme) {
if (is == null) {
return null;
}
@@ -981,15 +967,15 @@ public abstract class Drawable {
*/
public static Drawable createFromXml(Resources r, XmlPullParser parser)
throws XmlPullParserException, IOException {
- return createFromXmlThemed(r, parser, null);
+ return createFromXml(r, parser, null);
}
/**
- * Create a themed drawable from an XML document. For more information on
- * how to create resources in XML, see
+ * Create a drawable from an XML document using an optional {@link Theme}.
+ * For more information on how to create resources in XML, see
* <a href="{@docRoot}guide/topics/resources/drawable-resource.html">Drawable Resources</a>.
*/
- public static Drawable createFromXmlThemed(Resources r, XmlPullParser parser, Theme theme)
+ public static Drawable createFromXml(Resources r, XmlPullParser parser, Theme theme)
throws XmlPullParserException, IOException {
AttributeSet attrs = Xml.asAttributeSet(parser);
@@ -1003,7 +989,7 @@ public abstract class Drawable {
throw new XmlPullParserException("No start tag found");
}
- Drawable drawable = createFromXmlInnerThemed(r, parser, attrs, theme);
+ Drawable drawable = createFromXmlInner(r, parser, attrs, theme);
if (drawable == null) {
throw new RuntimeException("Unknown initial tag: " + parser.getName());
@@ -1019,16 +1005,17 @@ public abstract class Drawable {
*/
public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs)
throws XmlPullParserException, IOException {
- return createFromXmlInnerThemed(r, parser, attrs, null);
+ return createFromXmlInner(r, parser, attrs, null);
}
/**
- * Create a themed drawable from inside an XML document. Called on a parser
- * positioned at a tag in an XML document, tries to create a Drawable from
- * that tag. Returns null if the tag is not a valid drawable.
+ * Create a drawable from inside an XML document using an optional
+ * {@link Theme}. Called on a parser positioned at a tag in an XML
+ * document, tries to create a Drawable from that tag. Returns {@code null}
+ * if the tag is not a valid drawable.
*/
- public static Drawable createFromXmlInnerThemed(Resources r, XmlPullParser parser,
- AttributeSet attrs, Theme theme) throws XmlPullParserException, IOException {
+ public static Drawable createFromXmlInner(Resources r, XmlPullParser parser, AttributeSet attrs,
+ Theme theme) throws XmlPullParserException, IOException {
final Drawable drawable;
final String name = parser.getName();
@@ -1036,6 +1023,9 @@ public abstract class Drawable {
drawable = new StateListDrawable();
} else if (name.equals("animated-selector")) {
drawable = new AnimatedStateListDrawable();
+ } else if (name.equals("quantum-progress")) {
+ // TODO: Replace this with something less ridiculous.
+ drawable = new QuantumProgressDrawable();
} else if (name.equals("level-list")) {
drawable = new LevelListDrawable();
} else if (name.equals("layer-list")) {
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 2fa5929..9e0ab86 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -111,7 +111,7 @@ public class InsetDrawable extends Drawable implements Drawable.Callback
+ ": <inset> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
if (dr == null) {
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 75cb0a0..27f0a9d 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -211,7 +211,7 @@ public class LayerDrawable extends Drawable implements Drawable.Callback {
+ ": <item> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
addLayer(dr, themeAttrs, id, left, top, right, bottom);
diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java
index 9f6c0ad..7271b0e 100644
--- a/graphics/java/android/graphics/drawable/LevelListDrawable.java
+++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java
@@ -134,7 +134,7 @@ public class LevelListDrawable extends DrawableContainer {
+ ": <item> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
mLevelListState.addLevel(low, high, dr);
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 0a07332..77ed29a 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -23,10 +23,12 @@ import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Insets;
import android.graphics.NinePatch;
import android.graphics.Paint;
+import android.graphics.Paint.Style;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff;
import android.graphics.PorterDuff.Mode;
@@ -236,7 +238,6 @@ public class NinePatchDrawable extends Drawable {
final boolean needsMirroring = needsMirroring();
if (needsMirroring) {
- canvas.save();
// Mirror the 9patch
canvas.translate(bounds.right - bounds.left, 0);
canvas.scale(-1.0f, 1.0f);
@@ -253,10 +254,6 @@ public class NinePatchDrawable extends Drawable {
mNinePatch.draw(canvas, bounds, mPaint);
- if (needsMirroring) {
- canvas.restore();
- }
-
if (clearColorFilter) {
mPaint.setColorFilter(null);
}
diff --git a/graphics/java/android/graphics/drawable/QuantumProgressDrawable.java b/graphics/java/android/graphics/drawable/QuantumProgressDrawable.java
new file mode 100644
index 0000000..675355c
--- /dev/null
+++ b/graphics/java/android/graphics/drawable/QuantumProgressDrawable.java
@@ -0,0 +1,520 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.graphics.drawable;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.content.res.ColorStateList;
+import android.content.res.Resources;
+import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Paint.Cap;
+import android.graphics.Paint.Style;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.AttributeSet;
+import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.LinearInterpolator;
+
+import com.android.internal.R;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+/**
+ * Fancy progress indicator for Quantum theme.
+ *
+ * TODO: Replace this class with something less ridiculous.
+ */
+class QuantumProgressDrawable extends Drawable implements Animatable {
+ private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
+ private static final TimeInterpolator END_CURVE_INTERPOLATOR = new EndCurveInterpolator();
+ private static final TimeInterpolator START_CURVE_INTERPOLATOR = new StartCurveInterpolator();
+
+ /** The duration of a single progress spin in milliseconds. */
+ private static final int ANIMATION_DURATION = 1000 * 80 / 60;
+
+ /** The number of points in the progress "star". */
+ private static final int NUM_POINTS = 5;
+
+ /** The list of animators operating on this drawable. */
+ private final ArrayList<Animator> mAnimators = new ArrayList<Animator>();
+
+ /** The indicator ring, used to manage animation state. */
+ private final Ring mRing;
+
+ private QuantumProgressState mState;
+
+ /** Canvas rotation in degrees. */
+ private float mRotation;
+
+ private boolean mMutated;
+
+ public QuantumProgressDrawable() {
+ this(new QuantumProgressState(null), null);
+ }
+
+ private QuantumProgressDrawable(QuantumProgressState state, Theme theme) {
+ mState = state;
+ if (theme != null && state.canApplyTheme()) {
+ applyTheme(theme);
+ }
+
+ mRing = new Ring(mCallback);
+ mMutated = false;
+
+ initializeFromState();
+ setupAnimators();
+ }
+
+ private void initializeFromState() {
+ final QuantumProgressState state = mState;
+
+ final Ring ring = mRing;
+ ring.setStrokeWidth(state.mStrokeWidth);
+
+ final int color = state.mColor.getColorForState(getState(), Color.TRANSPARENT);
+ ring.setColor(color);
+
+ final float minEdge = Math.min(state.mWidth, state.mHeight);
+ if (state.mInnerRadius <= 0 || minEdge < 0) {
+ ring.setInsets((int) Math.ceil(state.mStrokeWidth / 2.0f));
+ } else {
+ float insets = minEdge / 2.0f - state.mInnerRadius;
+ ring.setInsets(insets);
+ }
+ }
+
+ @Override
+ public Drawable mutate() {
+ if (!mMutated && super.mutate() == this) {
+ mState = new QuantumProgressState(mState);
+ mMutated = true;
+ }
+ return this;
+ }
+
+ @Override
+ protected boolean onStateChange(int[] state) {
+ boolean changed = super.onStateChange(state);
+
+ final int color = mState.mColor.getColorForState(state, Color.TRANSPARENT);
+ if (color != mRing.getColor()) {
+ mRing.setColor(color);
+ changed = true;
+ }
+
+ return changed;
+ }
+
+ @Override
+ public boolean isStateful() {
+ return super.isStateful() || mState.mColor.isStateful();
+ }
+
+ @Override
+ public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+ throws XmlPullParserException, IOException {
+ final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.QuantumProgressDrawable);
+ super.inflateWithAttributes(r, parser, a, R.styleable.QuantumProgressDrawable_visible);
+ updateStateFromTypedArray(a);
+ a.recycle();
+
+ initializeFromState();
+ }
+
+ @Override
+ public void applyTheme(Theme t) {
+ final TypedArray a = t.resolveAttributes(mState.mThemeAttrs,
+ R.styleable.QuantumProgressDrawable);
+ updateStateFromTypedArray(a);
+ a.recycle();
+ }
+
+ private void updateStateFromTypedArray(TypedArray a) {
+ final QuantumProgressState state = mState;
+ state.mThemeAttrs = a.extractThemeAttrs();
+ state.mWidth = a.getDimensionPixelSize(
+ R.styleable.QuantumProgressDrawable_width, state.mWidth);
+ state.mHeight = a.getDimensionPixelSize(
+ R.styleable.QuantumProgressDrawable_height, state.mHeight);
+ state.mInnerRadius = a.getDimension(
+ R.styleable.QuantumProgressDrawable_innerRadius, state.mInnerRadius);
+ state.mStrokeWidth = a.getDimension(
+ R.styleable.QuantumProgressDrawable_thickness, state.mStrokeWidth);
+
+ if (a.hasValue(R.styleable.QuantumProgressDrawable_color)) {
+ state.mColor = a.getColorStateList(R.styleable.QuantumProgressDrawable_color);
+ }
+ }
+
+ @Override
+ public boolean setVisible(boolean visible, boolean restart) {
+ boolean changed = super.setVisible(visible, restart);
+ if (visible) {
+ if (changed || restart) {
+ start();
+ }
+ } else {
+ stop();
+ }
+ return changed;
+ }
+
+ @Override
+ public int getIntrinsicHeight() {
+ return mState.mHeight;
+ }
+
+ @Override
+ public int getIntrinsicWidth() {
+ return mState.mWidth;
+ }
+
+ @Override
+ public void draw(Canvas c) {
+ final Rect bounds = getBounds();
+ final int saveCount = c.save();
+ c.rotate(mRotation, bounds.exactCenterX(), bounds.exactCenterY());
+ mRing.draw(c, bounds);
+ c.restoreToCount(saveCount);
+ }
+
+ @Override
+ public void setAlpha(int alpha) {
+ mRing.setAlpha(alpha);
+ }
+
+ @Override
+ public int getAlpha() {
+ return mRing.getAlpha();
+ }
+
+ @Override
+ public void setColorFilter(ColorFilter colorFilter) {
+ mRing.setColorFilter(colorFilter);
+ }
+
+ @Override
+ public ColorFilter getColorFilter() {
+ return mRing.getColorFilter();
+ }
+
+ private void setRotation(float rotation) {
+ mRotation = rotation;
+ invalidateSelf();
+ }
+
+ private float getRotation() {
+ return mRotation;
+ }
+
+ @Override
+ public int getOpacity() {
+ return PixelFormat.TRANSLUCENT;
+ }
+
+ @Override
+ public boolean isRunning() {
+ final ArrayList<Animator> animators = mAnimators;
+ final int N = animators.size();
+ for (int i = 0; i < N; i++) {
+ final Animator animator = animators.get(i);
+ if (animator.isRunning()) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void start() {
+ final ArrayList<Animator> animators = mAnimators;
+ final int N = animators.size();
+ for (int i = 0; i < N; i++) {
+ final Animator animator = animators.get(i);
+ if (animator.isPaused()) {
+ animator.resume();
+ } else if (!animator.isRunning()){
+ animator.start();
+ }
+ }
+ }
+
+ @Override
+ public void stop() {
+ final ArrayList<Animator> animators = mAnimators;
+ final int N = animators.size();
+ for (int i = 0; i < N; i++) {
+ final Animator animator = animators.get(i);
+ animator.pause();
+ }
+ }
+
+ private void setupAnimators() {
+ final Ring ring = mRing;
+
+ final ObjectAnimator endTrim = ObjectAnimator.ofFloat(ring, "endTrim", 0, 0.75f);
+ endTrim.setDuration(ANIMATION_DURATION);
+ endTrim.setInterpolator(START_CURVE_INTERPOLATOR);
+ endTrim.setRepeatCount(ObjectAnimator.INFINITE);
+ endTrim.setRepeatMode(ObjectAnimator.RESTART);
+
+ final ObjectAnimator startTrim = ObjectAnimator.ofFloat(ring, "startTrim", 0.0f, 0.75f);
+ startTrim.setDuration(ANIMATION_DURATION);
+ startTrim.setInterpolator(END_CURVE_INTERPOLATOR);
+ startTrim.setRepeatCount(ObjectAnimator.INFINITE);
+ startTrim.setRepeatMode(ObjectAnimator.RESTART);
+
+ final ObjectAnimator rotation = ObjectAnimator.ofFloat(ring, "rotation", 0.0f, 0.25f);
+ rotation.setDuration(ANIMATION_DURATION);
+ rotation.setInterpolator(LINEAR_INTERPOLATOR);
+ rotation.setRepeatCount(ObjectAnimator.INFINITE);
+ rotation.setRepeatMode(ObjectAnimator.RESTART);
+
+ final ObjectAnimator groupRotation = ObjectAnimator.ofFloat(this, "rotation", 0.0f, 360.0f);
+ groupRotation.setDuration(NUM_POINTS * ANIMATION_DURATION);
+ groupRotation.setInterpolator(LINEAR_INTERPOLATOR);
+ groupRotation.setRepeatCount(ObjectAnimator.INFINITE);
+ groupRotation.setRepeatMode(ObjectAnimator.RESTART);
+
+ mAnimators.add(endTrim);
+ mAnimators.add(startTrim);
+ mAnimators.add(rotation);
+ mAnimators.add(groupRotation);
+ }
+
+ private final Callback mCallback = new Callback() {
+ @Override
+ public void invalidateDrawable(Drawable d) {
+ invalidateSelf();
+ }
+
+ @Override
+ public void scheduleDrawable(Drawable d, Runnable what, long when) {
+ scheduleSelf(what, when);
+ }
+
+ @Override
+ public void unscheduleDrawable(Drawable d, Runnable what) {
+ unscheduleSelf(what);
+ }
+ };
+
+ private static class QuantumProgressState extends ConstantState {
+ private int[] mThemeAttrs = null;
+ private float mStrokeWidth = 5.0f;
+ private float mInnerRadius = -1.0f;
+ private int mWidth = -1;
+ private int mHeight = -1;
+ private ColorStateList mColor = ColorStateList.valueOf(Color.TRANSPARENT);
+
+ public QuantumProgressState(QuantumProgressState orig) {
+ if (orig != null) {
+ mThemeAttrs = orig.mThemeAttrs;
+ mStrokeWidth = orig.mStrokeWidth;
+ mInnerRadius = orig.mInnerRadius;
+ mWidth = orig.mWidth;
+ mHeight = orig.mHeight;
+ mColor = orig.mColor;
+ }
+ }
+
+ @Override
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null;
+ }
+
+ @Override
+ public Drawable newDrawable() {
+ return newDrawable(null, null);
+ }
+
+ @Override
+ public Drawable newDrawable(Resources res) {
+ return newDrawable(res, null);
+ }
+
+ @Override
+ public Drawable newDrawable(Resources res, Theme theme) {
+ return new QuantumProgressDrawable(this, theme);
+ }
+
+ @Override
+ public int getChangingConfigurations() {
+ return 0;
+ }
+ }
+
+ private static class Ring {
+ private final RectF mTempBounds = new RectF();
+ private final Paint mPaint = new Paint();
+
+ private final Callback mCallback;
+
+ private float mStartTrim = 0.0f;
+ private float mEndTrim = 0.0f;
+ private float mRotation = 0.0f;
+ private float mStrokeWidth = 5.0f;
+ private float mStrokeInset = 2.5f;
+
+ private int mAlpha = 0xFF;
+ private int mColor = Color.BLACK;
+
+ public Ring(Callback callback) {
+ mCallback = callback;
+
+ mPaint.setStrokeCap(Cap.ROUND);
+ mPaint.setAntiAlias(true);
+ mPaint.setStyle(Style.STROKE);
+ }
+
+ public void draw(Canvas c, Rect bounds) {
+ final RectF arcBounds = mTempBounds;
+ arcBounds.set(bounds);
+ arcBounds.inset(mStrokeInset, mStrokeInset);
+
+ final float startAngle = (mStartTrim + mRotation) * 360;
+ final float endAngle = (mEndTrim + mRotation) * 360;
+ float sweepAngle = endAngle - startAngle;
+
+ // Ensure the sweep angle isn't too small to draw.
+ final float diameter = Math.min(arcBounds.width(), arcBounds.height());
+ final float minAngle = (float) (360.0 / (diameter * Math.PI));
+ if (sweepAngle < minAngle && sweepAngle > -minAngle) {
+ sweepAngle = Math.signum(sweepAngle) * minAngle;
+ }
+
+ c.drawArc(arcBounds, startAngle, sweepAngle, false, mPaint);
+ }
+
+ public void setColorFilter(ColorFilter filter) {
+ mPaint.setColorFilter(filter);
+ invalidateSelf();
+ }
+
+ public ColorFilter getColorFilter() {
+ return mPaint.getColorFilter();
+ }
+
+ public void setAlpha(int alpha) {
+ mAlpha = alpha;
+ mPaint.setColor(mColor & 0xFFFFFF | alpha << 24);
+ invalidateSelf();
+ }
+
+ public int getAlpha() {
+ return mAlpha;
+ }
+
+ public void setColor(int color) {
+ mColor = color;
+ mPaint.setColor(color & 0xFFFFFF | mAlpha << 24);
+ invalidateSelf();
+ }
+
+ public int getColor() {
+ return mColor;
+ }
+
+ public void setStrokeWidth(float strokeWidth) {
+ mStrokeWidth = strokeWidth;
+ mPaint.setStrokeWidth(strokeWidth);
+ invalidateSelf();
+ }
+
+ @SuppressWarnings("unused")
+ public float getStrokeWidth() {
+ return mStrokeWidth;
+ }
+
+ @SuppressWarnings("unused")
+ public void setStartTrim(float startTrim) {
+ mStartTrim = startTrim;
+ invalidateSelf();
+ }
+
+ @SuppressWarnings("unused")
+ public float getStartTrim() {
+ return mStartTrim;
+ }
+
+ @SuppressWarnings("unused")
+ public void setEndTrim(float endTrim) {
+ mEndTrim = endTrim;
+ invalidateSelf();
+ }
+
+ @SuppressWarnings("unused")
+ public float getEndTrim() {
+ return mEndTrim;
+ }
+
+ @SuppressWarnings("unused")
+ public void setRotation(float rotation) {
+ mRotation = rotation;
+ invalidateSelf();
+ }
+
+ @SuppressWarnings("unused")
+ public float getRotation() {
+ return mRotation;
+ }
+
+ public void setInsets(float insets) {
+ mStrokeInset = insets;
+ }
+
+ @SuppressWarnings("unused")
+ public float getInsets() {
+ return mStrokeInset;
+ }
+
+ private void invalidateSelf() {
+ mCallback.invalidateDrawable(null);
+ }
+ }
+
+ /**
+ * Squishes the interpolation curve into the second half of the animation.
+ */
+ private static class EndCurveInterpolator extends AccelerateDecelerateInterpolator {
+ @Override
+ public float getInterpolation(float input) {
+ return super.getInterpolation(Math.max(0, (input - 0.5f) * 2.0f));
+ }
+ }
+
+ /**
+ * Squishes the interpolation curve into the first half of the animation.
+ */
+ private static class StartCurveInterpolator extends AccelerateDecelerateInterpolator {
+ @Override
+ public float getInterpolation(float input) {
+ return super.getInterpolation(Math.min(1, input * 2.0f));
+ }
+ }
+}
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index ada741b..096e554 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -28,6 +28,7 @@ import android.graphics.Rect;
import android.util.MathUtils;
import android.view.HardwareCanvas;
import android.view.RenderNodeAnimator;
+import android.view.animation.DecelerateInterpolator;
import android.view.animation.LinearInterpolator;
import java.util.ArrayList;
@@ -37,13 +38,16 @@ import java.util.ArrayList;
*/
class Ripple {
private static final TimeInterpolator LINEAR_INTERPOLATOR = new LinearInterpolator();
+ private static final TimeInterpolator DECEL_INTERPOLATOR = new DecelerateInterpolator(4);
private static final float GLOBAL_SPEED = 1.0f;
- private static final float WAVE_TOUCH_DOWN_ACCELERATION = 512.0f * GLOBAL_SPEED;
- private static final float WAVE_TOUCH_UP_ACCELERATION = 1024.0f * GLOBAL_SPEED;
- private static final float WAVE_OPACITY_DECAY_VELOCITY = 1.6f / GLOBAL_SPEED;
+ private static final float WAVE_TOUCH_DOWN_ACCELERATION = 1024.0f * GLOBAL_SPEED;
+ private static final float WAVE_TOUCH_UP_ACCELERATION = 3096.0f * GLOBAL_SPEED;
+ private static final float WAVE_OPACITY_DECAY_VELOCITY = 1.9f / GLOBAL_SPEED;
private static final float WAVE_OUTER_OPACITY_VELOCITY = 1.2f * GLOBAL_SPEED;
+ private static final long RIPPLE_ENTER_DELAY = 100;
+
// Hardware animators.
private final ArrayList<RenderNodeAnimator> mRunningAnimations = new ArrayList<>();
private final ArrayList<RenderNodeAnimator> mPendingAnimations = new ArrayList<>();
@@ -287,14 +291,19 @@ class Ripple {
radius.setAutoCancel(true);
radius.setDuration(radiusDuration);
radius.setInterpolator(LINEAR_INTERPOLATOR);
+ radius.setStartDelay(RIPPLE_ENTER_DELAY);
final ObjectAnimator cX = ObjectAnimator.ofFloat(this, "xGravity", 1);
cX.setAutoCancel(true);
cX.setDuration(radiusDuration);
+ cX.setInterpolator(LINEAR_INTERPOLATOR);
+ cX.setStartDelay(RIPPLE_ENTER_DELAY);
final ObjectAnimator cY = ObjectAnimator.ofFloat(this, "yGravity", 1);
cY.setAutoCancel(true);
cY.setDuration(radiusDuration);
+ cY.setInterpolator(LINEAR_INTERPOLATOR);
+ cY.setStartDelay(RIPPLE_ENTER_DELAY);
final ObjectAnimator outer = ObjectAnimator.ofFloat(this, "outerOpacity", 0, 1);
outer.setAutoCancel(true);
@@ -377,15 +386,15 @@ class Ripple {
final RenderNodeAnimator radiusAnim = new RenderNodeAnimator(mPropRadius, mOuterRadius);
radiusAnim.setDuration(radiusDuration);
- radiusAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
final RenderNodeAnimator xAnim = new RenderNodeAnimator(mPropX, mOuterX);
xAnim.setDuration(radiusDuration);
- xAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ xAnim.setInterpolator(DECEL_INTERPOLATOR);
final RenderNodeAnimator yAnim = new RenderNodeAnimator(mPropY, mOuterY);
yAnim.setDuration(radiusDuration);
- yAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ yAnim.setInterpolator(DECEL_INTERPOLATOR);
final RenderNodeAnimator opacityAnim = new RenderNodeAnimator(mPropPaint,
RenderNodeAnimator.PAINT_ALPHA, 0);
@@ -408,6 +417,7 @@ class Ripple {
outerFadeOutAnim.setDuration(outerDuration);
outerFadeOutAnim.setInterpolator(LINEAR_INTERPOLATOR);
outerFadeOutAnim.setStartDelay(outerInflection);
+ outerFadeOutAnim.setStartValue(inflectionOpacity);
outerFadeOutAnim.addListener(mAnimationListener);
mPendingAnimations.add(outerFadeOutAnim);
@@ -438,17 +448,17 @@ class Ripple {
final ObjectAnimator radiusAnim = ObjectAnimator.ofFloat(this, "radiusGravity", 1);
radiusAnim.setAutoCancel(true);
radiusAnim.setDuration(radiusDuration);
- radiusAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ radiusAnim.setInterpolator(DECEL_INTERPOLATOR);
final ObjectAnimator xAnim = ObjectAnimator.ofFloat(this, "xGravity", 1);
xAnim.setAutoCancel(true);
xAnim.setDuration(radiusDuration);
- xAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ xAnim.setInterpolator(DECEL_INTERPOLATOR);
final ObjectAnimator yAnim = ObjectAnimator.ofFloat(this, "yGravity", 1);
yAnim.setAutoCancel(true);
yAnim.setDuration(radiusDuration);
- yAnim.setInterpolator(LINEAR_INTERPOLATOR);
+ yAnim.setInterpolator(DECEL_INTERPOLATOR);
final ObjectAnimator opacityAnim = ObjectAnimator.ofFloat(this, "opacity", 0);
opacityAnim.setAutoCancel(true);
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 9d7a8b6..58f6eaa 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -95,6 +95,9 @@ public class RippleDrawable extends LayerDrawable {
private final RippleState mState;
+ /** The masking layer, e.g. the layer with id R.id.mask. */
+ private Drawable mMask;
+
/** The current hotspot. May be actively animating or pending entry. */
private Ripple mHotspot;
@@ -261,21 +264,14 @@ public class RippleDrawable extends LayerDrawable {
super.inflate(r, parser, attrs, theme);
setTargetDensity(r.getDisplayMetrics());
-
- // Find the mask
- final int N = getNumberOfLayers();
- for (int i = 0; i < N; i++) {
- if (mLayerState.mChildren[i].mId == R.id.mask) {
- mState.mMask = mLayerState.mChildren[i].mDrawable;
- }
- }
+ initializeFromState();
}
@Override
public boolean setDrawableByLayerId(int id, Drawable drawable) {
if (super.setDrawableByLayerId(id, drawable)) {
if (id == R.id.mask) {
- mState.mMask = drawable;
+ mMask = drawable;
}
return true;
@@ -361,6 +357,8 @@ public class RippleDrawable extends LayerDrawable {
} finally {
a.recycle();
}
+
+ initializeFromState();
}
@Override
@@ -441,8 +439,11 @@ public class RippleDrawable extends LayerDrawable {
final int count = mAnimatingRipplesCount;
final Ripple[] ripples = mAnimatingRipples;
for (int i = 0; i < count; i++) {
- ripples[i].cancel();
+ // Calling cancel may remove the ripple from the animating ripple
+ // array, so cache the reference before nulling it out.
+ final Ripple ripple = ripples[i];
ripples[i] = null;
+ ripple.cancel();
}
mAnimatingRipplesCount = 0;
@@ -524,7 +525,7 @@ public class RippleDrawable extends LayerDrawable {
private int drawContentLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
final int count = mLayerState.mNum;
- if (count == 0 || (mState.mMask != null && count == 1)) {
+ if (count == 0 || (mMask != null && count == 1)) {
return -1;
}
@@ -608,7 +609,7 @@ public class RippleDrawable extends LayerDrawable {
}
private int drawMaskingLayer(Canvas canvas, Rect bounds, PorterDuffXfermode mode) {
- final Drawable mask = mState.mMask;
+ final Drawable mask = mMask;
if (mask == null) {
return -1;
}
@@ -616,6 +617,9 @@ public class RippleDrawable extends LayerDrawable {
final int restoreToCount = canvas.saveLayer(bounds.left, bounds.top,
bounds.right, bounds.bottom, getMaskingPaint(mode));
+ // Ensure that DST_IN blends using the entire layer.
+ canvas.drawColor(Color.TRANSPARENT);
+
mask.draw(canvas);
return restoreToCount;
@@ -661,7 +665,6 @@ public class RippleDrawable extends LayerDrawable {
int[] mTouchThemeAttrs;
ColorStateList mTint = null;
PorterDuffXfermode mTintXfermode = SRC_ATOP;
- Drawable mMask;
int mMaxRadius = RADIUS_AUTO;
boolean mPinned = false;
@@ -757,8 +760,6 @@ public class RippleDrawable extends LayerDrawable {
}
mState = ns;
- mState.mMask = findDrawableByLayerId(R.id.mask);
-
mLayerState = ns;
if (ns.mNum > 0) {
@@ -768,5 +769,12 @@ public class RippleDrawable extends LayerDrawable {
if (needsTheme) {
applyTheme(theme);
}
+
+ initializeFromState();
+ }
+
+ private void initializeFromState() {
+ // Initialize from constant state.
+ mMask = findDrawableByLayerId(R.id.mask);
}
}
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 5f9d1cd..06aeb98 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -438,7 +438,7 @@ public class RotateDrawable extends Drawable implements Drawable.Callback {
continue;
}
- if ((drawable = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme)) == null) {
+ if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
Log.w("drawable", "Bad element under <rotate>: "
+ parser .getName());
}
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 4c4d9af..f090c11 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -108,7 +108,7 @@ public class ScaleDrawable extends Drawable implements Drawable.Callback {
if (type != XmlPullParser.START_TAG) {
continue;
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
if (dr == null) {
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 99ab4dd..024f77c 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -291,41 +291,10 @@ public class ShapeDrawable extends Drawable {
return mShapeState.mAlpha;
}
- /**
- * Specifies a tint for this drawable.
- * <p>
- * Setting a color filter via {@link #setColorFilter(ColorFilter)} overrides
- * tint.
- *
- * @param tint Color state list to use for tinting this drawable, or null to
- * clear the tint
- */
- public void setTint(ColorStateList tint) {
- if (mShapeState.mTint != tint) {
+ @Override
+ public void setTint(ColorStateList tint, Mode tintMode) {
+ if (mShapeState.mTint != tint || mShapeState.mTintMode != tintMode) {
mShapeState.mTint = tint;
- updateTintFilter();
- invalidateSelf();
- }
- }
-
- /**
- * Returns the tint color for this drawable.
- *
- * @return Color state list to use for tinting this drawable, or null if
- * none set
- */
- public ColorStateList getTint() {
- return mShapeState.mTint;
- }
-
- /**
- * Specifies the blending mode used to apply tint.
- *
- * @param tintMode A Porter-Duff blending mode
- * @hide Pending finalization of supported Modes
- */
- public void setTintMode(Mode tintMode) {
- if (mShapeState.mTintMode != tintMode) {
mShapeState.mTintMode = tintMode;
updateTintFilter();
invalidateSelf();
@@ -350,16 +319,6 @@ public class ShapeDrawable extends Drawable {
}
}
- /**
- * Returns the blending mode used to apply tint.
- *
- * @return The Porter-Duff blending mode used to apply tint.
- * @hide Pending finalization of supported Modes
- */
- public Mode getTintMode() {
- return mShapeState.mTintMode;
- }
-
@Override
public void setColorFilter(ColorFilter cf) {
mShapeState.mPaint.setColorFilter(cf);
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index f22a063..b2fac9b 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -185,7 +185,7 @@ public class StateListDrawable extends DrawableContainer {
+ ": <item> tag requires a 'drawable' attribute or "
+ "child tag defining a drawable");
}
- dr = Drawable.createFromXmlInnerThemed(r, parser, attrs, theme);
+ dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
}
mStateListState.addStateSet(states, dr);
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index afd529c..c6c5b31 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -18,6 +18,7 @@ import android.content.res.Resources;
import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Canvas;
+import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Matrix;
import android.graphics.Paint;
@@ -40,6 +41,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
+import java.util.Stack;
/**
* This lets you create a drawable based on an XML vector graphic It can be
@@ -129,9 +131,9 @@ public class VectorDrawable extends Drawable {
private static final int LINEJOIN_ROUND = 1;
private static final int LINEJOIN_BEVEL = 2;
- private final VectorDrawableState mVectorState;
+ private static final boolean DBG_VECTOR_DRAWABLE = false;
- private int mAlpha = 0xFF;
+ private final VectorDrawableState mVectorState;
public VectorDrawable() {
mVectorState = new VectorDrawableState(null);
@@ -161,9 +163,8 @@ public class VectorDrawable extends Drawable {
@Override
public void setAlpha(int alpha) {
- // TODO correct handling of transparent
- if (mAlpha != alpha) {
- mAlpha = alpha;
+ if (mVectorState.mVPathRenderer.getRootAlpha() != alpha) {
+ mVectorState.mVPathRenderer.setRootAlpha(alpha);
invalidateSelf();
}
}
@@ -270,6 +271,13 @@ public class VectorDrawable extends Drawable {
return null;
}
+ private static int applyAlpha(int color, float alpha) {
+ int alphaBytes = Color.alpha(color);
+ color &= 0x00FFFFFF;
+ color |= ((int) (alphaBytes * alpha)) << 24;
+ return color;
+ }
+
private VPathRenderer inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
Theme theme) throws XmlPullParserException, IOException {
final VPathRenderer pathRenderer = new VPathRenderer();
@@ -279,12 +287,17 @@ public class VectorDrawable extends Drawable {
boolean noGroupTag = true;
boolean noPathTag = true;
- VGroup currentGroup = new VGroup();
+ // Use a stack to help to build the group tree.
+ // The top of the stack is always the current group.
+ final Stack<VGroup> groupStack = new Stack<VGroup>();
+ groupStack.push(pathRenderer.mRootGroup);
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
final String tagName = parser.getName();
+ final VGroup currentGroup = groupStack.peek();
+
if (SHAPE_PATH.equals(tagName)) {
final VPath path = new VPath();
path.inflate(res, attrs, theme);
@@ -297,18 +310,24 @@ public class VectorDrawable extends Drawable {
pathRenderer.parseViewport(res, attrs);
noViewportTag = false;
} else if (SHAPE_GROUP.equals(tagName)) {
- currentGroup = new VGroup();
- currentGroup.inflate(res, attrs, theme);
- pathRenderer.mGroupList.add(currentGroup);
+ VGroup newChildGroup = new VGroup();
+ newChildGroup.inflate(res, attrs, theme);
+ currentGroup.mChildGroupList.add(newChildGroup);
+ groupStack.push(newChildGroup);
noGroupTag = false;
}
+ } else if (eventType == XmlPullParser.END_TAG) {
+ final String tagName = parser.getName();
+ if (SHAPE_GROUP.equals(tagName)) {
+ groupStack.pop();
+ }
}
-
eventType = parser.next();
}
- if (noGroupTag && !noPathTag) {
- pathRenderer.mGroupList.add(currentGroup);
+ // Print the tree out for debug.
+ if (DBG_VECTOR_DRAWABLE) {
+ printGroupTree(pathRenderer.mRootGroup, 0);
}
if (noSizeTag || noViewportTag || noPathTag) {
@@ -338,6 +357,21 @@ public class VectorDrawable extends Drawable {
return pathRenderer;
}
+ private void printGroupTree(VGroup currentGroup, int level) {
+ String indent = "";
+ for (int i = 0 ; i < level ; i++) {
+ indent += " ";
+ }
+ // Print the current node
+ Log.v(LOGTAG, indent + "current group is :" + currentGroup.getName()
+ + " rotation is " + currentGroup.mRotate);
+ Log.v(LOGTAG, indent + "matrix is :" + currentGroup.getLocalMatrix().toString());
+ // Then print all the children
+ for (int i = 0 ; i < currentGroup.mChildGroupList.size(); i++) {
+ printGroupTree(currentGroup.mChildGroupList.get(i), level + 1);
+ }
+ }
+
private void setPathRenderer(VPathRenderer pathRenderer) {
mVectorState.mVPathRenderer = pathRenderer;
}
@@ -350,6 +384,7 @@ public class VectorDrawable extends Drawable {
public VectorDrawableState(VectorDrawableState copy) {
if (copy != null) {
mChangingConfigurations = copy.mChangingConfigurations;
+ // TODO: Make sure the constant state are handled correctly.
mVPathRenderer = new VPathRenderer(copy.mVPathRenderer);
mPadding = new Rect(copy.mPadding);
}
@@ -377,28 +412,51 @@ public class VectorDrawable extends Drawable {
}
private static class VPathRenderer {
+ /* Right now the internal data structure is organized as a tree.
+ * Each node can be a group node, or a path.
+ * A group node can have groups or paths as children, but a path node has
+ * no children.
+ * One example can be:
+ * Root Group
+ * / | \
+ * Group Path Group
+ * / \ |
+ * Path Path Path
+ *
+ */
+ private final VGroup mRootGroup;
+
private final Path mPath = new Path();
private final Path mRenderPath = new Path();
- private final Matrix mMatrix = new Matrix();
+ private static final Matrix IDENTITY_MATRIX = new Matrix();
private Paint mStrokePaint;
private Paint mFillPaint;
private ColorFilter mColorFilter;
private PathMeasure mPathMeasure;
- final ArrayList<VGroup> mGroupList = new ArrayList<VGroup>();
+ private float mBaseWidth = 0;
+ private float mBaseHeight = 0;
+ private float mViewportWidth = 0;
+ private float mViewportHeight = 0;
+ private int mRootAlpha = 0xFF;
- float mBaseWidth = 0;
- float mBaseHeight = 0;
- float mViewportWidth = 0;
- float mViewportHeight = 0;
+ private final Matrix mFinalPathMatrix = new Matrix();
public VPathRenderer() {
+ mRootGroup = new VGroup();
}
- public VPathRenderer(VPathRenderer copy) {
- mGroupList.addAll(copy.mGroupList);
+ public void setRootAlpha(int alpha) {
+ mRootAlpha = alpha;
+ }
+
+ public int getRootAlpha() {
+ return mRootAlpha;
+ }
+ public VPathRenderer(VPathRenderer copy) {
+ mRootGroup = copy.mRootGroup;
mBaseWidth = copy.mBaseWidth;
mBaseHeight = copy.mBaseHeight;
mViewportWidth = copy.mViewportHeight;
@@ -406,33 +464,59 @@ public class VectorDrawable extends Drawable {
}
public boolean canApplyTheme() {
- final ArrayList<VGroup> groups = mGroupList;
- for (int i = groups.size() - 1; i >= 0; i--) {
- final ArrayList<VPath> paths = groups.get(i).mVGList;
- for (int j = paths.size() - 1; j >= 0; j--) {
- final VPath path = paths.get(j);
- if (path.canApplyTheme()) {
- return true;
- }
+ // If one of the paths can apply theme, then return true;
+ return recursiveCanApplyTheme(mRootGroup);
+ }
+
+ private boolean recursiveCanApplyTheme(VGroup currentGroup) {
+ // We can do a tree traverse here, if there is one path return true,
+ // then we return true for the whole tree.
+ final ArrayList<VPath> paths = currentGroup.mPathList;
+ for (int j = paths.size() - 1; j >= 0; j--) {
+ final VPath path = paths.get(j);
+ if (path.canApplyTheme()) {
+ return true;
}
}
+ final ArrayList<VGroup> childGroups = currentGroup.mChildGroupList;
+
+ for (int i = 0; i < childGroups.size(); i++) {
+ VGroup childGroup = childGroups.get(i);
+ if (childGroup.canApplyTheme()
+ || recursiveCanApplyTheme(childGroup)) {
+ return true;
+ }
+ }
return false;
}
public void applyTheme(Theme t) {
- final ArrayList<VGroup> groups = mGroupList;
- for (int i = groups.size() - 1; i >= 0; i--) {
- VGroup currentGroup = groups.get(i);
- currentGroup.applyTheme(t);
- final ArrayList<VPath> paths = currentGroup.mVGList;
- for (int j = paths.size() - 1; j >= 0; j--) {
- final VPath path = paths.get(j);
- if (path.canApplyTheme()) {
- path.applyTheme(t);
- }
+ // Apply theme to every path of the tree.
+ recursiveApplyTheme(mRootGroup, t);
+ }
+
+ private void recursiveApplyTheme(VGroup currentGroup, Theme t) {
+ // We can do a tree traverse here, apply theme to all paths which
+ // can apply theme.
+ final ArrayList<VPath> paths = currentGroup.mPathList;
+ for (int j = paths.size() - 1; j >= 0; j--) {
+ final VPath path = paths.get(j);
+ if (path.canApplyTheme()) {
+ path.applyTheme(t);
}
}
+
+ final ArrayList<VGroup> childGroups = currentGroup.mChildGroupList;
+
+ for (int i = 0; i < childGroups.size(); i++) {
+ VGroup childGroup = childGroups.get(i);
+ if (childGroup.canApplyTheme()) {
+ childGroup.applyTheme(t);
+ }
+ recursiveApplyTheme(childGroup, t);
+ }
+
}
public void setColorFilter(ColorFilter colorFilter) {
@@ -448,34 +532,36 @@ public class VectorDrawable extends Drawable {
}
- public void draw(Canvas canvas, int w, int h) {
- if (mGroupList == null || mGroupList.size() == 0) {
- Log.e(LOGTAG,"There is no group to draw");
- return;
+ private void drawGroupTree(VGroup currentGroup, Matrix currentMatrix,
+ float currentAlpha, Canvas canvas, int w, int h) {
+ // Calculate current group's matrix by preConcat the parent's and
+ // and the current one on the top of the stack.
+ // Basically the Mfinal = Mviewport * M0 * M1 * M2;
+ // Mi the local matrix at level i of the group tree.
+ currentGroup.mStackedMatrix.set(currentMatrix);
+
+ currentGroup.mStackedMatrix.preConcat(currentGroup.mLocalMatrix);
+
+ float stackedAlpha = currentAlpha * currentGroup.mGroupAlpha;
+ drawPath(currentGroup, stackedAlpha, canvas, w, h);
+ // Draw the group tree in post order.
+ for (int i = 0 ; i < currentGroup.mChildGroupList.size(); i++) {
+ drawGroupTree(currentGroup.mChildGroupList.get(i),
+ currentGroup.mStackedMatrix, stackedAlpha, canvas, w, h);
}
+ }
- for (int i = 0; i < mGroupList.size(); i++) {
- VGroup currentGroup = mGroupList.get(i);
- if (currentGroup != null) {
- drawPath(currentGroup, canvas, w, h);
- }
- }
+ public void draw(Canvas canvas, int w, int h) {
+ // Travese the tree in pre-order to draw.
+ drawGroupTree(mRootGroup, IDENTITY_MATRIX, ((float) mRootAlpha) / 0xFF, canvas, w, h);
}
- private void drawPath(VGroup vGroup, Canvas canvas, int w, int h) {
+ private void drawPath(VGroup vGroup, float stackedAlpha, Canvas canvas, int w, int h) {
final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
- mMatrix.reset();
-
- // The order we apply is the same as the
- // RenderNode.cpp::applyViewPropertyTransforms().
- mMatrix.postTranslate(-vGroup.mPivotX, -vGroup.mPivotY);
- mMatrix.postScale(vGroup.mScaleX, vGroup.mScaleY);
- mMatrix.postRotate(vGroup.mRotate, 0, 0);
- mMatrix.postTranslate(vGroup.mTranslateX + vGroup.mPivotX, vGroup.mTranslateY + vGroup.mPivotY);
-
- mMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
- mMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
+ mFinalPathMatrix.set(vGroup.mStackedMatrix);
+ mFinalPathMatrix.postScale(scale, scale, mViewportWidth / 2f, mViewportHeight / 2f);
+ mFinalPathMatrix.postTranslate(w / 2f - mViewportWidth / 2f, h / 2f - mViewportHeight / 2f);
ArrayList<VPath> paths = vGroup.getPaths();
for (int i = 0; i < paths.size(); i++) {
@@ -507,45 +593,45 @@ public class VectorDrawable extends Drawable {
mRenderPath.reset();
- mRenderPath.addPath(path, mMatrix);
+ mRenderPath.addPath(path, mFinalPathMatrix);
if (vPath.mClip) {
canvas.clipPath(mRenderPath, Region.Op.REPLACE);
- }
-
- if (vPath.mFillColor != 0) {
- if (mFillPaint == null) {
- mFillPaint = new Paint();
- mFillPaint.setColorFilter(mColorFilter);
- mFillPaint.setStyle(Paint.Style.FILL);
- mFillPaint.setAntiAlias(true);
+ } else {
+ if (vPath.mFillColor != 0) {
+ if (mFillPaint == null) {
+ mFillPaint = new Paint();
+ mFillPaint.setColorFilter(mColorFilter);
+ mFillPaint.setStyle(Paint.Style.FILL);
+ mFillPaint.setAntiAlias(true);
+ }
+ mFillPaint.setColor(applyAlpha(vPath.mFillColor, stackedAlpha));
+ canvas.drawPath(mRenderPath, mFillPaint);
}
- mFillPaint.setColor(vPath.mFillColor);
- canvas.drawPath(mRenderPath, mFillPaint);
- }
+ if (vPath.mStrokeColor != 0) {
+ if (mStrokePaint == null) {
+ mStrokePaint = new Paint();
+ mStrokePaint.setColorFilter(mColorFilter);
+ mStrokePaint.setStyle(Paint.Style.STROKE);
+ mStrokePaint.setAntiAlias(true);
+ }
- if (vPath.mStrokeColor != 0) {
- if (mStrokePaint == null) {
- mStrokePaint = new Paint();
- mStrokePaint.setColorFilter(mColorFilter);
- mStrokePaint.setStyle(Paint.Style.STROKE);
- mStrokePaint.setAntiAlias(true);
- }
+ final Paint strokePaint = mStrokePaint;
+ if (vPath.mStrokeLineJoin != null) {
+ strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
+ }
- final Paint strokePaint = mStrokePaint;
- if (vPath.mStrokeLineJoin != null) {
- strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
- }
+ if (vPath.mStrokeLineCap != null) {
+ strokePaint.setStrokeCap(vPath.mStrokeLineCap);
+ }
- if (vPath.mStrokeLineCap != null) {
- strokePaint.setStrokeCap(vPath.mStrokeLineCap);
- }
+ strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
- strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
- strokePaint.setColor(vPath.mStrokeColor);
- strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
- canvas.drawPath(mRenderPath, strokePaint);
+ strokePaint.setColor(applyAlpha(vPath.mStrokeColor, stackedAlpha));
+ strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+ canvas.drawPath(mRenderPath, strokePaint);
+ }
}
}
}
@@ -588,7 +674,8 @@ public class VectorDrawable extends Drawable {
private static class VGroup {
private final HashMap<String, VPath> mVGPathMap = new HashMap<String, VPath>();
- private final ArrayList<VPath> mVGList = new ArrayList<VPath>();
+ private final ArrayList<VPath> mPathList = new ArrayList<VPath>();
+ private final ArrayList<VGroup> mChildGroupList = new ArrayList<VGroup>();
private float mRotate = 0;
private float mPivotX = 0;
@@ -597,15 +684,36 @@ public class VectorDrawable extends Drawable {
private float mScaleY = 1;
private float mTranslateX = 0;
private float mTranslateY = 0;
+ private float mGroupAlpha = 1;
+
+ // mLocalMatrix is parsed from the XML.
+ private final Matrix mLocalMatrix = new Matrix();
+ // mStackedMatrix is only used when drawing, it combines all the
+ // parents' local matrices with the current one.
+ private final Matrix mStackedMatrix = new Matrix();
private int[] mThemeAttrs;
+ private String mName = null;
+
+ public String getName() {
+ return mName;
+ }
+
+ public Matrix getLocalMatrix() {
+ return mLocalMatrix;
+ }
+
public void add(VPath path) {
String id = path.getID();
mVGPathMap.put(id, path);
- mVGList.add(path);
+ mPathList.add(path);
}
+ public boolean canApplyTheme() {
+ return mThemeAttrs != null;
+ }
+
public void applyTheme(Theme t) {
if (mThemeAttrs == null) {
return;
@@ -621,6 +729,11 @@ public class VectorDrawable extends Drawable {
mScaleY = a.getFloat(R.styleable.VectorDrawableGroup_scaleY, mScaleY);
mTranslateX = a.getFloat(R.styleable.VectorDrawableGroup_translateX, mTranslateX);
mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
+ mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
+ updateLocalMatrix();
+ if (a.hasValue(R.styleable.VectorDrawableGroup_name)) {
+ mName = a.getString(R.styleable.VectorDrawableGroup_name);
+ }
a.recycle();
}
@@ -660,15 +773,34 @@ public class VectorDrawable extends Drawable {
mTranslateY = a.getFloat(R.styleable.VectorDrawableGroup_translateY, mTranslateY);
}
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_name] == 0) {
+ mName = a.getString(R.styleable.VectorDrawableGroup_name);
+ }
+
+ if (themeAttrs == null || themeAttrs[R.styleable.VectorDrawableGroup_alpha] == 0) {
+ mGroupAlpha = a.getFloat(R.styleable.VectorDrawableGroup_alpha, mGroupAlpha);
+ }
+
+ updateLocalMatrix();
a.recycle();
}
+ private void updateLocalMatrix() {
+ // The order we apply is the same as the
+ // RenderNode.cpp::applyViewPropertyTransforms().
+ mLocalMatrix.reset();
+ mLocalMatrix.postTranslate(-mPivotX, -mPivotY);
+ mLocalMatrix.postScale(mScaleX, mScaleY);
+ mLocalMatrix.postRotate(mRotate, 0, 0);
+ mLocalMatrix.postTranslate(mTranslateX + mPivotX, mTranslateY + mPivotY);
+ }
+
/**
* Must return in order of adding
* @return ordered list of paths
*/
public ArrayList<VPath> getPaths() {
- return mVGList;
+ return mPathList;
}
}
@@ -682,7 +814,7 @@ public class VectorDrawable extends Drawable {
float mStrokeWidth = 0;
float mStrokeOpacity = Float.NaN;
- int mFillColor = 0;
+ int mFillColor = Color.BLACK;
int mFillRule;
float mFillOpacity = Float.NaN;
@@ -867,13 +999,11 @@ public class VectorDrawable extends Drawable {
private void updateColorAlphas() {
if (!Float.isNaN(mFillOpacity)) {
- mFillColor &= 0x00FFFFFF;
- mFillColor |= ((int) (0xFF * mFillOpacity)) << 24;
+ mFillColor = applyAlpha(mFillColor, mFillOpacity);
}
if (!Float.isNaN(mStrokeOpacity)) {
- mStrokeColor &= 0x00FFFFFF;
- mStrokeColor |= ((int) (0xFF * mStrokeOpacity)) << 24;
+ mStrokeColor = applyAlpha(mStrokeColor, mStrokeOpacity);
}
}
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 442f327..e5c8898 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -71,8 +71,6 @@ ifeq ($(USE_OPENGL_RENDERER),true)
$(LOCAL_PATH)/../../include/utils \
external/skia/src/core
- include external/stlport/libstlport.mk
-
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
LOCAL_CFLAGS += -Wno-unused-parameter
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
@@ -80,16 +78,15 @@ ifeq ($(USE_OPENGL_RENDERER),true)
LOCAL_MODULE := libhwui
LOCAL_MODULE_TAGS := optional
+ include external/stlport/libstlport.mk
+
ifneq (false,$(ANDROID_ENABLE_RENDERSCRIPT))
LOCAL_CFLAGS += -DANDROID_ENABLE_RENDERSCRIPT
- LOCAL_SHARED_LIBRARIES += libRS libRScpp libstlport
+ LOCAL_SHARED_LIBRARIES += libRS libRScpp
LOCAL_C_INCLUDES += \
$(intermediates) \
frameworks/rs/cpp \
- frameworks/rs \
- external/stlport/stlport \
- bionic/ \
- bionic/libstdc++/include
+ frameworks/rs
endif
ifndef HWUI_COMPILE_SYMBOLS
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 02f686f..9212b9d 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -788,7 +788,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw bitmap %p src="RECT_STRING", dst="RECT_STRING,
+ OP_LOG("Draw bitmap %p src=" RECT_STRING ", dst=" RECT_STRING,
mBitmap, RECT_ARGS(mSrc), RECT_ARGS(mLocalBounds));
}
@@ -978,7 +978,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw patch "RECT_STRING, RECT_ARGS(mLocalBounds));
+ OP_LOG("Draw patch " RECT_STRING, RECT_ARGS(mLocalBounds));
}
virtual const char* name() { return "DrawPatch"; }
@@ -1060,7 +1060,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw Rect "RECT_STRING, RECT_ARGS(mLocalBounds));
+ OP_LOG("Draw Rect " RECT_STRING, RECT_ARGS(mLocalBounds));
}
virtual void onDefer(OpenGLRenderer& renderer, DeferInfo& deferInfo,
@@ -1111,7 +1111,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw RoundRect "RECT_STRING", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
+ OP_LOG("Draw RoundRect " RECT_STRING ", rx %f, ry %f", RECT_ARGS(mLocalBounds), mRx, mRy);
}
virtual const char* name() { return "DrawRoundRect"; }
@@ -1175,7 +1175,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw Oval "RECT_STRING, RECT_ARGS(mLocalBounds));
+ OP_LOG("Draw Oval " RECT_STRING, RECT_ARGS(mLocalBounds));
}
virtual const char* name() { return "DrawOval"; }
@@ -1195,7 +1195,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw Arc "RECT_STRING", start %f, sweep %f, useCenter %d",
+ OP_LOG("Draw Arc " RECT_STRING ", start %f, sweep %f, useCenter %d",
RECT_ARGS(mLocalBounds), mStartAngle, mSweepAngle, mUseCenter);
}
@@ -1232,7 +1232,7 @@ public:
}
virtual void output(int level, uint32_t logFlags) const {
- OP_LOG("Draw Path %p in "RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
+ OP_LOG("Draw Path %p in " RECT_STRING, mPath, RECT_ARGS(mLocalBounds));
}
virtual const char* name() { return "DrawPath"; }
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index b07d2c5..4b4be1b 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -16,6 +16,11 @@
package android.media;
+import android.annotation.IntDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
/**
* The AudioFormat class is used to access a number of audio format and
* channel configuration constants. They are for instance used
@@ -162,4 +167,151 @@ public class AudioFormat {
throw new UnsupportedOperationException("There is no valid usage of this constructor");
}
+ /**
+ * Private constructor with an ignored argument to differentiate from the removed default ctor
+ * @param ignoredArgument
+ */
+ private AudioFormat(int ignoredArgument) {
+ }
+
+ /** @hide */
+ public final static int AUDIO_FORMAT_HAS_PROPERTY_NONE = 0x0;
+ /** @hide */
+ public final static int AUDIO_FORMAT_HAS_PROPERTY_ENCODING = 0x1 << 0;
+ /** @hide */
+ public final static int AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE = 0x1 << 1;
+ /** @hide */
+ public final static int AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK = 0x1 << 2;
+
+ private int mEncoding;
+ private int mSampleRate;
+ private int mChannelMask;
+ private int mPropertySetMask;
+
+ /**
+ * @hide CANDIDATE FOR PUBLIC API
+ * Builder class for {@link AudioFormat} objects.
+ */
+ public static class Builder {
+ private int mEncoding = ENCODING_DEFAULT;
+ private int mSampleRate = 0;
+ private int mChannelMask = CHANNEL_INVALID;
+ private int mPropertySetMask = AUDIO_FORMAT_HAS_PROPERTY_NONE;
+
+ /**
+ * Constructs a new Builder with the defaults.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Constructs a new Builder from a given {@link AudioFormat}.
+ * @param af the {@link AudioFormat} object whose data will be reused in the new Builder.
+ */
+ public Builder(AudioFormat af) {
+ mEncoding = af.mEncoding;
+ mSampleRate = af.mSampleRate;
+ mChannelMask = af.mChannelMask;
+ mPropertySetMask = af.mPropertySetMask;
+ }
+
+ /**
+ * Combines all of the format characteristics that have been set and return a new
+ * {@link AudioFormat} object.
+ * @return a new {@link AudioFormat} object
+ */
+ public AudioFormat build() {
+ AudioFormat af = new AudioFormat(1980/*ignored*/);
+ af.mEncoding = mEncoding;
+ af.mSampleRate = mSampleRate;
+ af.mChannelMask = mChannelMask;
+ af.mPropertySetMask = mPropertySetMask;
+ return af;
+ }
+
+ /**
+ * Sets the data encoding format.
+ * @param encoding one of {@link AudioFormat#ENCODING_DEFAULT},
+ * {@link AudioFormat#ENCODING_PCM_8BIT},
+ * {@link AudioFormat#ENCODING_PCM_16BIT},
+ * {@link AudioFormat#ENCODING_PCM_FLOAT}.
+ * @return the same Builder instance.
+ * @throws java.lang.IllegalArgumentException
+ */
+ public Builder setEncoding(@Encoding int encoding) throws IllegalArgumentException {
+ switch (encoding) {
+ case ENCODING_DEFAULT:
+ mEncoding = ENCODING_PCM_16BIT;
+ break;
+ case ENCODING_PCM_8BIT:
+ case ENCODING_PCM_16BIT:
+ case ENCODING_PCM_FLOAT:
+ mEncoding = encoding;
+ break;
+ case ENCODING_INVALID:
+ default:
+ throw new IllegalArgumentException("Invalid encoding " + encoding);
+ }
+ mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_ENCODING;
+ return this;
+ }
+
+ /**
+ * Sets the channel mask.
+ * @param channelMask describes the configuration of the audio channels.
+ * <p>For output, the mask should be a combination of
+ * {@link AudioFormat#CHANNEL_OUT_FRONT_LEFT},
+ * {@link AudioFormat#CHANNEL_OUT_FRONT_CENTER},
+ * {@link AudioFormat#CHANNEL_OUT_FRONT_RIGHT},
+ * {@link AudioFormat#CHANNEL_OUT_SIDE_LEFT},
+ * {@link AudioFormat#CHANNEL_OUT_SIDE_RIGHT},
+ * {@link AudioFormat#CHANNEL_OUT_BACK_LEFT},
+ * {@link AudioFormat#CHANNEL_OUT_BACK_RIGHT}.
+ * <p>for input, the mask should be {@link AudioFormat#CHANNEL_IN_MONO} or
+ * {@link AudioFormat#CHANNEL_IN_STEREO}. {@link AudioFormat#CHANNEL_IN_MONO} is
+ * guaranteed to work on all devices.
+ * @return the same Builder instance.
+ */
+ public Builder setChannelMask(int channelMask) {
+ // only validated when used, with input or output context
+ mChannelMask = channelMask;
+ mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_CHANNEL_MASK;
+ return this;
+ }
+
+ /**
+ * Sets the sample rate.
+ * @param sampleRate the sample rate expressed in Hz
+ * @return the same Builder instance.
+ * @throws java.lang.IllegalArgumentException
+ */
+ public Builder setSampleRate(int sampleRate) throws IllegalArgumentException {
+ if ((sampleRate <= 0) || (sampleRate > 192000)) {
+ throw new IllegalArgumentException("Invalid sample rate " + sampleRate);
+ }
+ mSampleRate = sampleRate;
+ mPropertySetMask |= AUDIO_FORMAT_HAS_PROPERTY_SAMPLE_RATE;
+ return this;
+ }
+ }
+
+ @Override
+ public String toString () {
+ return new String("AudioFormat:"
+ + " props=" + mPropertySetMask
+ + " enc=" + mEncoding
+ + " chan=0x" + Integer.toHexString(mChannelMask)
+ + " rate=" + mSampleRate);
+ }
+
+ /** @hide */
+ @IntDef({
+ ENCODING_DEFAULT,
+ ENCODING_PCM_8BIT,
+ ENCODING_PCM_16BIT,
+ ENCODING_PCM_FLOAT
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Encoding {}
+
}
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 84d4ab6..88756d7 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -3188,15 +3188,11 @@ public class AudioManager {
do {
newPorts.clear();
status = AudioSystem.listAudioPorts(newPorts, portGeneration);
- Log.i(TAG, "updateAudioPortCache AudioSystem.listAudioPorts() status: "+
- status+" num ports: "+ newPorts.size() +" portGeneration: "+portGeneration[0]);
if (status != SUCCESS) {
return status;
}
newPatches.clear();
status = AudioSystem.listAudioPatches(newPatches, patchGeneration);
- Log.i(TAG, "updateAudioPortCache AudioSystem.listAudioPatches() status: "+
- status+" num patches: "+ newPatches.size() +" patchGeneration: "+patchGeneration[0]);
if (status != SUCCESS) {
return status;
}
@@ -3204,14 +3200,16 @@ public class AudioManager {
for (int i = 0; i < newPatches.size(); i++) {
for (int j = 0; j < newPatches.get(i).sources().length; j++) {
- AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j], newPorts);
+ AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sources()[j],
+ newPorts);
if (portCfg == null) {
return ERROR;
}
newPatches.get(i).sources()[j] = portCfg;
}
for (int j = 0; j < newPatches.get(i).sinks().length; j++) {
- AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j], newPorts);
+ AudioPortConfig portCfg = updatePortConfig(newPatches.get(i).sinks()[j],
+ newPorts);
if (portCfg == null) {
return ERROR;
}
@@ -3242,8 +3240,6 @@ public class AudioManager {
// compare handles because the port returned by JNI is not of the correct
// subclass
if (ports.get(k).handle().equals(port.handle())) {
- Log.i(TAG, "updatePortConfig match found for port handle: "+
- port.handle().id()+" port: "+ k);
port = ports.get(k);
break;
}
diff --git a/media/java/android/media/AudioPort.java b/media/java/android/media/AudioPort.java
index fbd5022..8b74842 100644
--- a/media/java/android/media/AudioPort.java
+++ b/media/java/android/media/AudioPort.java
@@ -133,7 +133,7 @@ public class AudioPort {
* Get the gain descriptor at a given index
*/
AudioGain gain(int index) {
- if (index < mGains.length) {
+ if (index < 0 || index >= mGains.length) {
return null;
}
return mGains[index];
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 8eb83e4..cfd9c3b 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -816,6 +816,8 @@ public class AudioTrack
* 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.
+ * A timestamp may be temporarily unavailable while the audio clock is stabilizing,
+ * or during and immediately after a route change.
*/
// Add this text when the "on new timestamp" API is added:
// Use if you need to get the most recent timestamp outside of the event callback handler.
diff --git a/core/java/android/tv/ITvInputClient.aidl b/media/java/android/media/tv/ITvInputClient.aidl
index ef89c68..011da35 100644
--- a/core/java/android/tv/ITvInputClient.aidl
+++ b/media/java/android/media/tv/ITvInputClient.aidl
@@ -14,11 +14,11 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.content.ComponentName;
+import android.media.tv.ITvInputSession;
import android.os.Bundle;
-import android.tv.ITvInputSession;
import android.view.InputChannel;
/**
@@ -31,5 +31,7 @@ oneway interface ITvInputClient {
void onAvailabilityChanged(in String inputId, boolean isAvailable);
void onSessionReleased(int seq);
void onSessionEvent(in String name, in Bundle args, int seq);
- void onVideoSizeChanged(int width, int height, int seq);
+ void onVideoStreamChanged(int width, int height, boolean interlaced, int seq);
+ void onAudioStreamChanged(int channelCount, int seq);
+ void onClosedCaptionStreamChanged(boolean hasClosedCaption, int seq);
}
diff --git a/core/java/android/tv/ITvInputHardware.aidl b/media/java/android/media/tv/ITvInputHardware.aidl
index 7250453..f35e8f3 100644
--- a/core/java/android/tv/ITvInputHardware.aidl
+++ b/media/java/android/media/tv/ITvInputHardware.aidl
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
-import android.tv.TvStreamConfig;
+import android.media.tv.TvStreamConfig;
import android.view.KeyEvent;
import android.view.Surface;
diff --git a/core/java/android/tv/ITvInputHardwareCallback.aidl b/media/java/android/media/tv/ITvInputHardwareCallback.aidl
index 83041be..870883b 100644
--- a/core/java/android/tv/ITvInputHardwareCallback.aidl
+++ b/media/java/android/media/tv/ITvInputHardwareCallback.aidl
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
-import android.tv.TvStreamConfig;
+import android.media.tv.TvStreamConfig;
/**
* @hide
diff --git a/core/java/android/tv/ITvInputManager.aidl b/media/java/android/media/tv/ITvInputManager.aidl
index c6f8d79..6db5a18 100644
--- a/core/java/android/tv/ITvInputManager.aidl
+++ b/media/java/android/media/tv/ITvInputManager.aidl
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.content.ComponentName;
import android.graphics.Rect;
+import android.media.tv.ITvInputHardware;
+import android.media.tv.ITvInputHardwareCallback;
+import android.media.tv.ITvInputClient;
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvInputInfo;
import android.net.Uri;
-import android.tv.ITvInputHardware;
-import android.tv.ITvInputHardwareCallback;
-import android.tv.ITvInputClient;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvInputInfo;
import android.view.Surface;
/**
diff --git a/core/java/android/tv/ITvInputService.aidl b/media/java/android/media/tv/ITvInputService.aidl
index 4f1bc2b..992e424 100644
--- a/core/java/android/tv/ITvInputService.aidl
+++ b/media/java/android/media/tv/ITvInputService.aidl
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
-import android.tv.ITvInputServiceCallback;
-import android.tv.ITvInputSessionCallback;
+import android.media.tv.ITvInputServiceCallback;
+import android.media.tv.ITvInputSessionCallback;
import android.view.InputChannel;
/**
diff --git a/core/java/android/tv/ITvInputServiceCallback.aidl b/media/java/android/media/tv/ITvInputServiceCallback.aidl
index 71fc780..c9484dd 100644
--- a/core/java/android/tv/ITvInputServiceCallback.aidl
+++ b/media/java/android/media/tv/ITvInputServiceCallback.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.content.ComponentName;
diff --git a/core/java/android/tv/ITvInputSession.aidl b/media/java/android/media/tv/ITvInputSession.aidl
index 32fee4b..fb2e251 100644
--- a/core/java/android/tv/ITvInputSession.aidl
+++ b/media/java/android/media/tv/ITvInputSession.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.graphics.Rect;
import android.net.Uri;
diff --git a/core/java/android/tv/ITvInputSessionCallback.aidl b/media/java/android/media/tv/ITvInputSessionCallback.aidl
index e27b8bf..00f2922 100644
--- a/core/java/android/tv/ITvInputSessionCallback.aidl
+++ b/media/java/android/media/tv/ITvInputSessionCallback.aidl
@@ -14,10 +14,10 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
+import android.media.tv.ITvInputSession;
import android.os.Bundle;
-import android.tv.ITvInputSession;
/**
* Helper interface for ITvInputSession to allow the TV input to notify the system service when a
@@ -27,5 +27,7 @@ import android.tv.ITvInputSession;
oneway interface ITvInputSessionCallback {
void onSessionCreated(ITvInputSession session);
void onSessionEvent(in String name, in Bundle args);
- void onVideoSizeChanged(int width, int height);
+ void onVideoStreamChanged(int width, int height, boolean interlaced);
+ void onAudioStreamChanged(int channelCount);
+ void onClosedCaptionStreamChanged(boolean hasClosedCaption);
}
diff --git a/core/java/android/tv/ITvInputSessionWrapper.java b/media/java/android/media/tv/ITvInputSessionWrapper.java
index 3ccccf3..975e391 100644
--- a/core/java/android/tv/ITvInputSessionWrapper.java
+++ b/media/java/android/media/tv/ITvInputSessionWrapper.java
@@ -14,22 +14,20 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.content.Context;
import android.graphics.Rect;
+import android.media.tv.TvInputManager.Session;
+import android.media.tv.TvInputService.TvInputSessionImpl;
import android.net.Uri;
import android.os.IBinder;
import android.os.Looper;
import android.os.Message;
-import android.tv.TvInputManager.Session;
-import android.tv.TvInputService.TvInputSessionImpl;
import android.util.Log;
import android.view.InputChannel;
import android.view.InputEvent;
import android.view.InputEventReceiver;
-import android.view.KeyEvent;
-import android.view.MotionEvent;
import android.view.Surface;
import com.android.internal.os.HandlerCaller;
diff --git a/core/java/android/provider/TvContract.java b/media/java/android/media/tv/TvContract.java
index 0d90a16..6e0586e 100644
--- a/core/java/android/provider/TvContract.java
+++ b/media/java/android/media/tv/TvContract.java
@@ -14,13 +14,13 @@
* limitations under the License.
*/
-package android.provider;
+package android.media.tv;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.net.Uri;
-import android.tv.TvInputService;
+import android.provider.BaseColumns;
import java.util.List;
@@ -45,7 +45,7 @@ import java.util.List;
*/
public final class TvContract {
/** The authority for the TV provider. */
- public static final String AUTHORITY = "com.android.tv";
+ public static final String AUTHORITY = "android.media.tv";
private static final String PATH_CHANNEL = "channel";
private static final String PATH_PROGRAM = "program";
@@ -88,8 +88,8 @@ public final class TvContract {
/**
* Builds a URI that points to all browsable channels from a given TV input.
*
- * @param name {@link ComponentName} of the {@link android.tv.TvInputService} that implements
- * the given TV input.
+ * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
+ * implements the given TV input.
*/
public static final Uri buildChannelsUriForInput(ComponentName name) {
return buildChannelsUriForInput(name, true);
@@ -98,8 +98,8 @@ public final class TvContract {
/**
* Builds a URI that points to all or browsable-only channels from a given TV input.
*
- * @param name {@link ComponentName} of the {@link android.tv.TvInputService} that implements
- * the given TV input.
+ * @param name {@link ComponentName} of the {@link android.media.tv.TvInputService} that
+ * implements the given TV input.
* @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
* to {@code false} the URI points to all channels regardless of whether they are
* browsable or not.
@@ -243,12 +243,10 @@ public final class TvContract {
+ PATH_CHANNEL);
/** The MIME type of a directory of TV channels. */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/channel";
/** The MIME type of a single TV channel. */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/vnd.com.android.tv.channels";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/channel";
/** A generic channel type. */
public static final int TYPE_OTHER = 0x0;
@@ -319,11 +317,11 @@ public final class TvContract {
/** A generic service type. */
public static final int SERVICE_TYPE_OTHER = 0x0;
- /** The service type for regular TV channels. */
- public static final int SERVICE_TYPE_TV = 0x1;
+ /** The service type for regular TV channels that have both audio and video. */
+ public static final int SERVICE_TYPE_AUDIO_VIDEO = 0x1;
- /** The service type for radio channels. */
- public static final int SERVICE_TYPE_RADIO = 0x2;
+ /** The service type for radio channels that have audio only. */
+ public static final int SERVICE_TYPE_AUDIO = 0x2;
/**
* The name of the {@link TvInputService} subclass that provides this TV channel. This
@@ -363,7 +361,7 @@ public final class TvContract {
* a radio-like channel. Use the same coding for {@code service_type} in the underlying
* broadcast standard if it is defined there (e.g. ATSC A/53, ETSI EN 300 468 and ARIB
* STD-B10). Otherwise use one of the followings: {@link #SERVICE_TYPE_OTHER},
- * {@link #SERVICE_TYPE_TV}, {@link #SERVICE_TYPE_RADIO}
+ * {@link #SERVICE_TYPE_AUDIO_VIDEO}, {@link #SERVICE_TYPE_AUDIO}
* </p><p>
* This is a required field.
* </p><p>
@@ -376,7 +374,7 @@ public final class TvContract {
* The original network ID of this TV channel.
* <p>
* This is used to identify the originating delivery system, if applicable. Use the same
- * coding for {@code origianal_network_id} in the underlying broadcast standard if it is
+ * coding for {@code original_network_id} in the underlying broadcast standard if it is
* defined there (e.g. ETSI EN 300 468/TR 101 211 and ARIB STD-B10). If channels cannot be
* globally identified by 2-tuple {{@link #COLUMN_TRANSPORT_STREAM_ID},
* {@link #COLUMN_SERVICE_ID}}, one must carefully assign a value to this field to form a
@@ -496,17 +494,20 @@ public final class TvContract {
* </p><p>
* Type: INTEGER (boolean)
* </p>
+ * @hide
*/
public static final String COLUMN_LOCKED = "locked";
/**
- * Generic data used by individual TV input services.
+ * Internal data used by individual TV input services.
* <p>
+ * This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ * </p><p>
* Type: BLOB
* </p>
*/
- public static final String COLUMN_DATA = "data";
-
+ public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
/**
* The version number of this row entry used by TV input services.
@@ -532,12 +533,10 @@ public final class TvContract {
+ PATH_PROGRAM);
/** The MIME type of a directory of TV programs. */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/program";
/** The MIME type of a single TV program. */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/vnd.com.android.tv.programs";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/program";
/**
* The ID of the TV channel that contains this TV program.
@@ -578,44 +577,42 @@ public final class TvContract {
* <p>
* Use the same language appeared in the underlying broadcast standard, if applicable. (For
* example, one can refer to the genre strings used in Genre Descriptor of ATSC A/65 or
- * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, use one of the
- * following genres:
- * <ul>
- * <li>Family/Kids</li>
- * <li>Sports</li>
- * <li>Shopping</li>
- * <li>Movies</li>
- * <li>Comedy</li>
- * <li>Travel</li>
- * <li>Drama</li>
- * <li>Education</li>
- * <li>Animal/Wildlife</li>
- * <li>News</li>
- * <li>Gaming</li>
- * <li>Others</li>
- * </ul>
+ * Content Descriptor of ETSI EN 300 468, if appropriate.) Otherwise, leave empty.
* </p><p>
* Type: TEXT
* </p>
*/
- public static final String COLUMN_GENRE = "genre";
+ public static final String COLUMN_BROADCAST_GENRE = "broadcast_genre";
/**
- * The description of this TV program that is displayed to the user by default.
+ * The comma-separated canonical genre string of this TV program.
* <p>
- * The maximum length of this field is 256 characters.
+ * Canonical genres are defined in {@link Genres}. Use {@link Genres#encode Genres.encode()}
+ * to create a text that can be stored in this column. Use {@link Genres#decode
+ * Genres.decode()} to get the canonical genre strings from the text stored in this column.
* </p><p>
* Type: TEXT
* </p>
+ * @see Genres
*/
- public static final String COLUMN_DESCRIPTION = "description";
+ public static final String COLUMN_CANONICAL_GENRE = "canonical_genre";
+
+ /**
+ * The short description of this TV program that is displayed to the user by default.
+ * <p>
+ * It is recommended to limit the length of the descriptions to 256 characters.
+ * </p><p>
+ * Type: TEXT
+ * </p>
+ */
+ public static final String COLUMN_SHORT_DESCRIPTION = "short_description";
/**
* The detailed, lengthy description of this TV program that is displayed only when the user
* wants to see more information.
* <p>
- * TV input services should leave this field empty if they have no additional
- * details beyond {@link #COLUMN_DESCRIPTION}.
+ * TV input services should leave this field empty if they have no additional details beyond
+ * {@link #COLUMN_SHORT_DESCRIPTION}.
* </p><p>
* Type: TEXT
* </p>
@@ -634,12 +631,15 @@ public final class TvContract {
public static final String COLUMN_AUDIO_LANGUAGE = "audio_language";
/**
- * Generic data used by TV input services.
+ * Internal data used by individual TV input services.
* <p>
+ * This is internal to the provider that inserted it, and should not be decoded by other
+ * apps.
+ * </p><p>
* Type: BLOB
* </p>
*/
- public static final String COLUMN_DATA = "data";
+ public static final String COLUMN_INTERNAL_PROVIDER_DATA = "internal_provider_data";
/**
* The version number of this row entry used by TV input services.
@@ -655,6 +655,72 @@ public final class TvContract {
public static final String COLUMN_VERSION_NUMBER = "version_number";
private Programs() {}
+
+ /** Canonical genres for TV programs. */
+ public static final class Genres {
+ /** The genre for Family/Kids. */
+ public static final String FAMILY_KIDS = "Family/Kids";
+
+ /** The genre for Sports. */
+ public static final String SPORTS = "Sports";
+
+ /** The genre for Shopping. */
+ public static final String SHOPPING = "Shopping";
+
+ /** The genre for Movies. */
+ public static final String MOVIES = "Movies";
+
+ /** The genre for Comedy. */
+ public static final String COMEDY = "Comedy";
+
+ /** The genre for Travel. */
+ public static final String TRAVEL = "Travel";
+
+ /** The genre for Drama. */
+ public static final String DRAMA = "Drama";
+
+ /** The genre for Education. */
+ public static final String EDUCATION = "Education";
+
+ /** The genre for Animal/Wildlife. */
+ public static final String ANIMAL_WILDLIFE = "Animal/Wildlife";
+
+ /** The genre for News. */
+ public static final String NEWS = "News";
+
+ /** The genre for Gaming. */
+ public static final String GAMING = "Gaming";
+
+ private Genres() {}
+
+ /**
+ * Encodes canonical genre strings to a text that can be put into the database.
+ *
+ * @param genres Canonical genre strings. Use the strings defined in this class.
+ * @return an encoded genre string that can be inserted into the
+ * {@link #COLUMN_CANONICAL_GENRE} column.
+ */
+ public static String encode(String... genres) {
+ StringBuilder sb = new StringBuilder();
+ String separator = "";
+ for (String genre : genres) {
+ sb.append(separator).append(genre);
+ separator = ",";
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Decodes the canonical genre strings from the text stored in the database.
+ *
+ * @param genres The encoded genre string retrieved from the
+ * {@link #COLUMN_CANONICAL_GENRE} column.
+ * @return canonical genre strings.
+ */
+ public static String[] decode(String genres) {
+ return genres.split("\\s*,\\s*");
+ }
+ }
}
/**
@@ -670,12 +736,10 @@ public final class TvContract {
Uri.parse("content://" + AUTHORITY + "/watched_program");
/** The MIME type of a directory of watched programs. */
- public static final String CONTENT_TYPE =
- "vnd.android.cursor.dir/vnd.com.android.tv.watched_programs";
+ public static final String CONTENT_TYPE = "vnd.android.cursor.dir/watched_program";
/** The MIME type of a single item in this table. */
- public static final String CONTENT_ITEM_TYPE =
- "vnd.android.cursor.item/vnd.com.android.tv.watched_programs";
+ public static final String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/watched_program";
/**
* The UTC time that the user started watching this TV program, in milliseconds since the
diff --git a/core/java/android/tv/TvInputHardwareInfo.aidl b/media/java/android/media/tv/TvInputHardwareInfo.aidl
index 484ab60..a4c38bb 100644
--- a/core/java/android/tv/TvInputHardwareInfo.aidl
+++ b/media/java/android/media/tv/TvInputHardwareInfo.aidl
@@ -15,6 +15,6 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
parcelable TvInputHardwareInfo;
diff --git a/core/java/android/tv/TvInputHardwareInfo.java b/media/java/android/media/tv/TvInputHardwareInfo.java
index b0dc58e..4beb960 100644
--- a/core/java/android/tv/TvInputHardwareInfo.java
+++ b/media/java/android/media/tv/TvInputHardwareInfo.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/tv/TvInputInfo.aidl b/media/java/android/media/tv/TvInputInfo.aidl
index abc4b47..ba139a2 100644
--- a/core/java/android/tv/TvInputInfo.aidl
+++ b/media/java/android/media/tv/TvInputInfo.aidl
@@ -14,6 +14,6 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
parcelable TvInputInfo;
diff --git a/core/java/android/tv/TvInputInfo.java b/media/java/android/media/tv/TvInputInfo.java
index 217e4b7..ed599ed 100644
--- a/core/java/android/tv/TvInputInfo.java
+++ b/media/java/android/media/tv/TvInputInfo.java
@@ -14,29 +14,116 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
import android.os.Parcel;
import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
/**
* This class is used to specify meta information of a TV input.
*/
public final class TvInputInfo implements Parcelable {
+ private static final boolean DEBUG = false;
+ private static final String TAG = "TvInputInfo";
+
+ /**
+ * The name of the TV input service to provide to the setup activity and settings activity.
+ */
+ public static final String EXTRA_SERVICE_NAME = "serviceName";
+
+ private static final String XML_START_TAG_NAME = "tv-input";
+
private final ResolveInfo mService;
private final String mId;
+ // Attributes from XML meta data.
+ private String mSetupActivity;
+ private String mSettingsActivity;
+
+ /**
+ * Create a new instance of the TvInputInfo class,
+ * instantiating it from the given Context and ResolveInfo.
+ *
+ * @param service The ResolveInfo returned from the package manager about this TV input service.
+ * @hide */
+ public static TvInputInfo createTvInputInfo(Context context, ResolveInfo service)
+ throws XmlPullParserException, IOException {
+ ServiceInfo si = service.serviceInfo;
+ PackageManager pm = context.getPackageManager();
+ XmlResourceParser parser = null;
+ try {
+ parser = si.loadXmlMetaData(pm, TvInputService.SERVICE_META_DATA);
+ if (parser == null) {
+ throw new XmlPullParserException("No " + TvInputService.SERVICE_META_DATA
+ + " meta-data for " + si.name);
+ }
+
+ Resources res = pm.getResourcesForApplication(si.applicationInfo);
+ AttributeSet attrs = Xml.asAttributeSet(parser);
+
+ int type;
+ while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+ && type != XmlPullParser.START_TAG) {
+ }
+
+ String nodeName = parser.getName();
+ if (!XML_START_TAG_NAME.equals(nodeName)) {
+ throw new XmlPullParserException(
+ "Meta-data does not start with tv-input-service tag in " + si.name);
+ }
+
+ TvInputInfo input = new TvInputInfo(context, service);
+ TypedArray sa = res.obtainAttributes(attrs,
+ com.android.internal.R.styleable.TvInputService);
+ input.mSetupActivity = sa.getString(
+ com.android.internal.R.styleable.TvInputService_setupActivity);
+ if (DEBUG) {
+ Log.d(TAG, "Setup activity loaded. [" + input.mSetupActivity + "] for " + si.name);
+ }
+ input.mSettingsActivity = sa.getString(
+ com.android.internal.R.styleable.TvInputService_settingsActivity);
+ if (DEBUG) {
+ Log.d(TAG, "Settings activity loaded. [" + input.mSettingsActivity + "] for "
+ + si.name);
+ }
+ sa.recycle();
+
+ return input;
+ } catch (NameNotFoundException e) {
+ throw new XmlPullParserException("Unable to create context for: " + si.packageName);
+ } finally {
+ if (parser != null) {
+ parser.close();
+ }
+ }
+ }
+
/**
* Constructor.
*
* @param service The ResolveInfo returned from the package manager about this TV input service.
* @hide
*/
- public TvInputInfo(ResolveInfo service) {
+ private TvInputInfo(Context context, ResolveInfo service) {
mService = service;
ServiceInfo si = service.serviceInfo;
mId = generateInputIdForComponentName(new ComponentName(si.packageName, si.name));
@@ -72,6 +159,32 @@ public final class TvInputInfo implements Parcelable {
}
/**
+ * Returns an intent to start the setup activity for this TV input service.
+ */
+ public Intent getIntentForSetupActivity() {
+ if (!TextUtils.isEmpty(mSetupActivity)) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(getPackageName(), mSetupActivity);
+ intent.putExtra(EXTRA_SERVICE_NAME, getServiceName());
+ return intent;
+ }
+ return null;
+ }
+
+ /**
+ * Returns an intent to start the settings activity for this TV input service.
+ */
+ public Intent getIntentForSettingsActivity() {
+ if (!TextUtils.isEmpty(mSettingsActivity)) {
+ Intent intent = new Intent(Intent.ACTION_MAIN);
+ intent.setClassName(getPackageName(), mSettingsActivity);
+ intent.putExtra(EXTRA_SERVICE_NAME, getServiceName());
+ return intent;
+ }
+ return null;
+ }
+
+ /**
* Loads the user-displayed label for this TV input service.
*
* @param pm Supplies a PackageManager used to load the TV input's resources.
@@ -125,6 +238,8 @@ public final class TvInputInfo implements Parcelable {
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(mId);
mService.writeToParcel(dest, flags);
+ dest.writeString(mSetupActivity);
+ dest.writeString(mSettingsActivity);
}
/**
@@ -159,5 +274,7 @@ public final class TvInputInfo implements Parcelable {
private TvInputInfo(Parcel in) {
mId = in.readString();
mService = ResolveInfo.CREATOR.createFromParcel(in);
+ mSetupActivity = in.readString();
+ mSettingsActivity = in.readString();
}
}
diff --git a/core/java/android/tv/TvInputManager.java b/media/java/android/media/tv/TvInputManager.java
index d0c2ca6..698a861 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/media/java/android/media/tv/TvInputManager.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.graphics.Rect;
import android.net.Uri;
@@ -88,15 +88,39 @@ public final class TvInputManager {
}
/**
- * This is called at the beginning of the playback of a channel and later when the size of
- * the video has been changed.
+ * This is called at the beginning of the playback of a channel and later when the format of
+ * the video stream has been changed.
*
* @param session A {@link TvInputManager.Session} associated with this callback
- * @param width the width of the video
- * @param height the height of the video
+ * @param width The width of the video.
+ * @param height The height of the video.
+ * @param interlaced whether the video is interlaced mode or planer mode.
* @hide
*/
- public void onVideoSizeChanged(Session session, int width, int height) {
+ public void onVideoStreamChanged(Session session, int width, int height,
+ boolean interlaced) {
+ }
+
+ /**
+ * This is called at the beginning of the playback of a channel and later when the format of
+ * the audio stream has been changed.
+ *
+ * @param session A {@link TvInputManager.Session} associated with this callback
+ * @param channelCount The number of channels in the audio stream.
+ * @hide
+ */
+ public void onAudioStreamChanged(Session session, int channelCount) {
+ }
+
+ /**
+ * This is called at the beginning of the playback of a channel and later when the closed
+ * caption stream has been changed.
+ *
+ * @param session A {@link TvInputManager.Session} associated with this callback
+ * @param hasClosedCaption Whether the stream has closed caption or not.
+ * @hide
+ */
+ public void onClosedCaptionStreamChanged(Session session, boolean hasClosedCaption) {
}
/**
@@ -141,11 +165,30 @@ public final class TvInputManager {
});
}
- public void postVideoSizeChanged(final int width, final int height) {
+ public void postVideoStreamChanged(final int width, final int height,
+ final boolean interlaced) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onVideoStreamChanged(mSession, width, height, interlaced);
+ }
+ });
+ }
+
+ public void postAudioStreamChanged(final int channelCount) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ mSessionCallback.onAudioStreamChanged(mSession, channelCount);
+ }
+ });
+ }
+
+ public void postClosedCaptionStreamChanged(final boolean hasClosedCaption) {
mHandler.post(new Runnable() {
@Override
public void run() {
- mSessionCallback.onVideoSizeChanged(mSession, width, height);
+ mSessionCallback.onClosedCaptionStreamChanged(mSession, hasClosedCaption);
}
});
}
@@ -238,14 +281,38 @@ public final class TvInputManager {
}
@Override
- public void onVideoSizeChanged(int width, int height, int seq) {
+ public void onVideoStreamChanged(int width, int height, boolean interlaced, int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postVideoStreamChanged(width, height, interlaced);
+ }
+ }
+
+ @Override
+ public void onAudioStreamChanged(int channelCount, int seq) {
+ synchronized (mSessionCallbackRecordMap) {
+ SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
+ if (record == null) {
+ Log.e(TAG, "Callback not found for seq " + seq);
+ return;
+ }
+ record.postAudioStreamChanged(channelCount);
+ }
+ }
+
+ @Override
+ public void onClosedCaptionStreamChanged(boolean hasClosedCaption, int seq) {
synchronized (mSessionCallbackRecordMap) {
SessionCallbackRecord record = mSessionCallbackRecordMap.get(seq);
if (record == null) {
Log.e(TAG, "Callback not found for seq " + seq);
return;
}
- record.postVideoSizeChanged(width, height);
+ record.postClosedCaptionStreamChanged(hasClosedCaption);
}
}
diff --git a/core/java/android/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 03d24db..8ba0e20 100644
--- a/core/java/android/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.app.Service;
import android.content.ComponentName;
@@ -22,6 +22,8 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.PixelFormat;
import android.graphics.Rect;
+import android.media.tv.ITvInputService;
+import android.media.tv.TvInputManager.Session;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -29,7 +31,6 @@ import android.os.IBinder;
import android.os.Message;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
-import android.tv.TvInputManager.Session;
import android.util.Log;
import android.view.Gravity;
import android.view.InputChannel;
@@ -59,7 +60,15 @@ public abstract class TvInputService extends Service {
* must also require the {@link android.Manifest.permission#BIND_TV_INPUT} permission so that
* other applications cannot abuse it.
*/
- public static final String SERVICE_INTERFACE = "android.tv.TvInputService";
+ public static final String SERVICE_INTERFACE = "android.media.tv.TvInputService";
+
+ /**
+ * Name under which a TvInputService component publishes information about itself.
+ * This meta-data must reference an XML resource containing an
+ * <code>&lt;{@link android.R.styleable#TvInputService tv-input}&gt;</code>
+ * tag.
+ */
+ public static final String SERVICE_META_DATA = "android.media.tv.input";
private String mId;
private final Handler mHandler = new ServiceHandler();
@@ -214,20 +223,22 @@ public abstract class TvInputService extends Service {
}
/**
- * Sends the change on the size of the video. This is expected to be called at the
- * beginning of the playback and later when the size has been changed.
+ * Sends the change on the format of the video stream. This is expected to be called at the
+ * beginning of the playback and later when the format has been changed.
*
* @param width The width of the video.
* @param height The height of the video.
+ * @param interlaced Whether the video is interlaced mode or planer mode.
* @hide
*/
- public void dispatchVideoSizeChanged(final int width, final int height) {
+ public void dispatchVideoStreamChanged(final int width, final int height,
+ final boolean interlaced) {
mHandler.post(new Runnable() {
@Override
public void run() {
try {
if (DEBUG) Log.d(TAG, "dispatchVideoSizeChanged");
- mSessionCallback.onVideoSizeChanged(width, height);
+ mSessionCallback.onVideoStreamChanged(width, height, interlaced);
} catch (RemoteException e) {
Log.w(TAG, "error in dispatchVideoSizeChanged");
}
@@ -236,6 +247,48 @@ public abstract class TvInputService extends Service {
}
/**
+ * Sends the change on the format of the audio stream. This is expected to be called at the
+ * beginning of the playback and later when the format has been changed.
+ *
+ * @param channelNumber The number of channels in the audio stream.
+ * @hide
+ */
+ public void dispatchAudioStreamChanged(final int channelNumber) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) Log.d(TAG, "dispatchAudioStreamChanged");
+ mSessionCallback.onAudioStreamChanged(channelNumber);
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in dispatchAudioStreamChanged");
+ }
+ }
+ });
+ }
+
+ /**
+ * Sends the change on the closed caption stream. This is expected to be called at the
+ * beginning of the playback and later when the stream has been changed.
+ *
+ * @param hasClosedCaption Whether the stream has closed caption or not.
+ * @hide
+ */
+ public void dispatchClosedCaptionStreamChanged(final boolean hasClosedCaption) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ if (DEBUG) Log.d(TAG, "dispatchClosedCaptionStreamChanged");
+ mSessionCallback.onClosedCaptionStreamChanged(hasClosedCaption);
+ } catch (RemoteException e) {
+ Log.w(TAG, "error in dispatchClosedCaptionStreamChanged");
+ }
+ }
+ });
+ }
+
+ /**
* Called when the session is released.
*/
public abstract void onRelease();
diff --git a/core/java/android/tv/TvStreamConfig.aidl b/media/java/android/media/tv/TvStreamConfig.aidl
index 4d0add4..569fcc0 100644
--- a/core/java/android/tv/TvStreamConfig.aidl
+++ b/media/java/android/media/tv/TvStreamConfig.aidl
@@ -15,6 +15,6 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
parcelable TvStreamConfig; \ No newline at end of file
diff --git a/core/java/android/tv/TvStreamConfig.java b/media/java/android/media/tv/TvStreamConfig.java
index 03e63b1..7f0c92f 100644
--- a/core/java/android/tv/TvStreamConfig.java
+++ b/media/java/android/media/tv/TvStreamConfig.java
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.os.Parcel;
import android.os.Parcelable;
diff --git a/core/java/android/tv/TvView.java b/media/java/android/media/tv/TvView.java
index 2d31701..d8b362d 100644
--- a/core/java/android/tv/TvView.java
+++ b/media/java/android/media/tv/TvView.java
@@ -14,16 +14,16 @@
* limitations under the License.
*/
-package android.tv;
+package android.media.tv;
import android.content.Context;
import android.graphics.Rect;
+import android.media.tv.TvInputManager.Session;
+import android.media.tv.TvInputManager.Session.FinishedInputEventCallback;
+import android.media.tv.TvInputManager.SessionCallback;
import android.os.Bundle;
import android.os.Handler;
import android.text.TextUtils;
-import android.tv.TvInputManager.Session;
-import android.tv.TvInputManager.Session.FinishedInputEventCallback;
-import android.tv.TvInputManager.SessionCallback;
import android.util.AttributeSet;
import android.util.Log;
import android.view.InputEvent;
@@ -382,12 +382,33 @@ public class TvView extends SurfaceView {
}
@Override
- public void onVideoSizeChanged(Session session, int width, int height) {
+ public void onVideoStreamChanged(Session session, int width, int height,
+ boolean interlaced) {
if (DEBUG) {
Log.d(TAG, "onVideoSizeChanged(" + width + ", " + height + ")");
}
if (mExternalCallback != null) {
- mExternalCallback.onVideoSizeChanged(session, width, height);
+ mExternalCallback.onVideoStreamChanged(session, width, height, interlaced);
+ }
+ }
+
+ @Override
+ public void onAudioStreamChanged(Session session, int channelCount) {
+ if (DEBUG) {
+ Log.d(TAG, "onAudioStreamChanged(" + channelCount + ")");
+ }
+ if (mExternalCallback != null) {
+ mExternalCallback.onAudioStreamChanged(session, channelCount);
+ }
+ }
+
+ @Override
+ public void onClosedCaptionStreamChanged(Session session, boolean hasClosedCaption) {
+ if (DEBUG) {
+ Log.d(TAG, "onClosedCaptionStreamChanged(" + hasClosedCaption + ")");
+ }
+ if (mExternalCallback != null) {
+ mExternalCallback.onClosedCaptionStreamChanged(session, hasClosedCaption);
}
}
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index 36c1d5c..ec87c6e 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -88,7 +88,7 @@ public class DefaultContainerService extends IntentService {
private IMediaContainerService.Stub mBinder = new IMediaContainerService.Stub() {
/**
* Creates a new container and copies resource there.
- * @param paackageURI the uri of resource to be copied. Can be either
+ * @param packageURI the uri of resource to be copied. Can be either
* a content uri or a file uri
* @param cid the id of the secure container that should
* be used for creating a secure container into which the resource
@@ -101,13 +101,13 @@ public class DefaultContainerService extends IntentService {
*/
public String copyResourceToContainer(final Uri packageURI, final String cid,
final String key, final String resFileName, final String publicResFileName,
- boolean isExternal, boolean isForwardLocked) {
+ boolean isExternal, boolean isForwardLocked, String abiOverride) {
if (packageURI == null || cid == null) {
return null;
}
return copyResourceInner(packageURI, cid, key, resFileName, publicResFileName,
- isExternal, isForwardLocked);
+ isExternal, isForwardLocked, abiOverride);
}
/**
@@ -153,13 +153,12 @@ public class DefaultContainerService extends IntentService {
/**
* Determine the recommended install location for package
* specified by file uri location.
- * @param fileUri the uri of resource to be copied. Should be a
- * file uri
+ *
* @return Returns PackageInfoLite object containing
* the package info and recommended app location.
*/
public PackageInfoLite getMinimalPackageInfo(final String packagePath, int flags,
- long threshold) {
+ long threshold, String abiOverride) {
PackageInfoLite ret = new PackageInfoLite();
if (packagePath == null) {
@@ -191,7 +190,7 @@ public class DefaultContainerService extends IntentService {
ret.verifiers = pkg.verifiers;
ret.recommendedInstallLocation = recommendAppInstallLocation(pkg.installLocation,
- packagePath, flags, threshold);
+ packagePath, flags, threshold, abiOverride);
return ret;
}
@@ -208,11 +207,11 @@ public class DefaultContainerService extends IntentService {
}
@Override
- public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked)
- throws RemoteException {
+ public boolean checkExternalFreeStorage(Uri packageUri, boolean isForwardLocked,
+ String abiOverride) throws RemoteException {
final File apkFile = new File(packageUri.getPath());
try {
- return isUnderExternalThreshold(apkFile, isForwardLocked);
+ return isUnderExternalThreshold(apkFile, isForwardLocked, abiOverride);
} catch (IOException e) {
return true;
}
@@ -265,11 +264,11 @@ public class DefaultContainerService extends IntentService {
}
@Override
- public long calculateInstalledSize(String packagePath, boolean isForwardLocked)
- throws RemoteException {
+ public long calculateInstalledSize(String packagePath, boolean isForwardLocked,
+ String abiOverride) throws RemoteException {
final File packageFile = new File(packagePath);
try {
- return calculateContainerSize(packageFile, isForwardLocked) * 1024 * 1024;
+ return calculateContainerSize(packageFile, isForwardLocked, abiOverride) * 1024 * 1024;
} catch (IOException e) {
/*
* Okay, something failed, so let's just estimate it to be 2x
@@ -328,7 +327,8 @@ public class DefaultContainerService extends IntentService {
}
private String copyResourceInner(Uri packageURI, String newCid, String key, String resFileName,
- String publicResFileName, boolean isExternal, boolean isForwardLocked) {
+ String publicResFileName, boolean isExternal, boolean isForwardLocked,
+ String abiOverride) {
if (isExternal) {
// Make sure the sdcard is mounted.
@@ -343,7 +343,22 @@ public class DefaultContainerService extends IntentService {
String codePath = packageURI.getPath();
File codeFile = new File(codePath);
NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath);
- final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+ String[] abiList = Build.SUPPORTED_ABIS;
+ if (abiOverride != null) {
+ abiList = new String[] { abiOverride };
+ } else {
+ try {
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
+ NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+ abiList = Build.SUPPORTED_32_BIT_ABIS;
+ }
+ } catch (IOException ioe) {
+ Slog.w(TAG, "Problem determining ABI for: " + codeFile.getPath());
+ return null;
+ }
+ }
+
+ final int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
// Calculate size of container needed to hold base APK.
final int sizeMb;
@@ -414,7 +429,7 @@ public class DefaultContainerService extends IntentService {
int ret = PackageManager.INSTALL_SUCCEEDED;
if (abi >= 0) {
ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- sharedLibraryDir, Build.SUPPORTED_ABIS[abi]);
+ sharedLibraryDir, abiList[abi]);
} else if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
ret = abi;
}
@@ -672,7 +687,7 @@ public class DefaultContainerService extends IntentService {
private static final int PREFER_EXTERNAL = 2;
private int recommendAppInstallLocation(int installLocation, String archiveFilePath, int flags,
- long threshold) {
+ long threshold, String abiOverride) {
int prefer;
boolean checkBoth = false;
@@ -741,7 +756,7 @@ public class DefaultContainerService extends IntentService {
boolean fitsOnSd = false;
if (!emulated && (checkBoth || prefer == PREFER_EXTERNAL)) {
try {
- fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked);
+ fitsOnSd = isUnderExternalThreshold(apkFile, isForwardLocked, abiOverride);
} catch (IOException e) {
return PackageHelper.RECOMMEND_FAILED_INVALID_URI;
}
@@ -812,13 +827,13 @@ public class DefaultContainerService extends IntentService {
* @return true if file fits
* @throws IOException when file does not exist
*/
- private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked)
+ private boolean isUnderExternalThreshold(File apkFile, boolean isForwardLocked, String abiOverride)
throws IOException {
if (Environment.isExternalStorageEmulated()) {
return false;
}
- final int sizeMb = calculateContainerSize(apkFile, isForwardLocked);
+ final int sizeMb = calculateContainerSize(apkFile, isForwardLocked, abiOverride);
final int availSdMb;
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
@@ -832,9 +847,11 @@ public class DefaultContainerService extends IntentService {
return availSdMb > sizeMb;
}
- private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
+ private int calculateContainerSize(File apkFile, boolean forwardLocked,
+ String abiOverride) throws IOException {
NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile);
- final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+ final int abi = NativeLibraryHelper.findSupportedAbi(handle,
+ (abiOverride != null) ? new String[] { abiOverride } : Build.SUPPORTED_ABIS);
try {
return calculateContainerSize(handle, apkFile, abi, forwardLocked);
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index aa118ed..ae04e32 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -17,7 +17,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="2783841764617238354">"Asiakirjat"</string>
- <string name="title_open" msgid="4353228937663917801">"Avoinna alkaen"</string>
+ <string name="title_open" msgid="4353228937663917801">"Avaa sijainnista"</string>
<string name="title_save" msgid="2433679664882857999">"Tallenna kohteeseen"</string>
<string name="menu_create_dir" msgid="5947289605844398389">"Luo kansio"</string>
<string name="menu_grid" msgid="6878021334497835259">"Ruudukkonäkymä"</string>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index 070b130..b85b518 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -16,7 +16,7 @@
<resources xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
- <string name="app_label" msgid="2783841764617238354">"Documents"</string>
+ <string name="app_label" msgid="2783841764617238354">"Docs"</string>
<string name="title_open" msgid="4353228937663917801">"Ouvrir à partir de"</string>
<string name="title_save" msgid="2433679664882857999">"Enregistrer sous"</string>
<string name="menu_create_dir" msgid="5947289605844398389">"Créer un dossier"</string>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index e8944ec..8c9030d 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -20,14 +20,14 @@
<string name="title_open" msgid="4353228937663917801">"បើក​ពី"</string>
<string name="title_save" msgid="2433679664882857999">"រក្សា​ទុក​ទៅ"</string>
<string name="menu_create_dir" msgid="5947289605844398389">"បង្កើត​ថត"</string>
- <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាព​ក្រឡា"</string>
+ <string name="menu_grid" msgid="6878021334497835259">"ទិដ្ឋភាព​ក្រឡា​"</string>
<string name="menu_list" msgid="7279285939892417279">"ទិដ្ឋភាព​បញ្ជី"</string>
<string name="menu_sort" msgid="7677740407158414452">"តម្រៀប​តាម"</string>
<string name="menu_search" msgid="3816712084502856974">"ស្វែងរក"</string>
<string name="menu_settings" msgid="6008033148948428823">"ការ​កំណត់"</string>
<string name="menu_open" msgid="432922957274920903">"បើក"</string>
<string name="menu_save" msgid="2394743337684426338">"រក្សាទុក"</string>
- <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក"</string>
+ <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក​"</string>
<string name="menu_delete" msgid="8138799623850614177">"លុប"</string>
<string name="menu_select" msgid="8711270657353563424">"ជ្រើស \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
<string name="mode_selected_count" msgid="459111894725594625">"បាន​ជ្រើស <xliff:g id="COUNT">%1$d</xliff:g>"</string>
@@ -48,7 +48,7 @@
<string name="pref_advanced_devices" msgid="903257239609301276">"បង្ហាញ​ឧបករណ៍​កម្រិត​ខ្ពស់"</string>
<string name="pref_file_size" msgid="2826879315743961459">"បង្ហាញ​ទំហំ​ឯកសារ"</string>
<string name="pref_device_size" msgid="3542106883278997222">"បង្ហាញ​ទំហំ​ឧបករណ៍"</string>
- <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ"</string>
+ <string name="empty" msgid="7858882803708117596">"គ្មានធាតុ​"</string>
<string name="toast_no_application" msgid="1339885974067891667">"មិន​អាច​បើក​ឯកសារ"</string>
<string name="toast_failed_delete" msgid="2180678019407244069">"មិន​អាច​លុប​ឯកសារ​មួយ​ចំនួន"</string>
<string name="share_via" msgid="8966594246261344259">"ចែករំលែក​តាម"</string>
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 1be44f9..96ed2e7 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -16,8 +16,7 @@
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) \
- $(call all-proto-files-under,src)
+LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files)
LOCAL_MODULE := Keyguard
@@ -27,9 +26,6 @@ LOCAL_PRIVILEGED_MODULE := true
LOCAL_PROGUARD_FLAG_FILES := proguard.flags
-LOCAL_PROTOC_OPTIMIZE_TYPE := nano
-LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
-
LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index 112e371..2917faa 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -48,5 +48,18 @@
android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
<include layout="@layout/keyguard_status_area" />
+ <TextView
+ android:id="@+id/owner_info"
+ android:layout_marginLeft="16dp"
+ android:layout_marginRight="16dp"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_marginTop="@dimen/date_owner_info_margin"
+ android:layout_gravity="center_horizontal"
+ android:textColor="#99ffffff"
+ android:textSize="@dimen/widget_label_font_size"
+ android:ellipsize="marquee"
+ android:singleLine="true" />
+
</LinearLayout>
</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index a2e54a7..18b59f1 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -83,7 +83,7 @@
<string name="password_keyboard_label_alpha_key" msgid="8001096175167485649">"ABC"</string>
<string name="password_keyboard_label_alt_key" msgid="1284820942620288678">"ALT"</string>
<string name="keyboardview_keycode_alt" msgid="4856868820040051939">"Alt"</string>
- <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់"</string>
+ <string name="keyboardview_keycode_cancel" msgid="1203984017245783244">"បោះ​បង់​"</string>
<string name="keyboardview_keycode_delete" msgid="3337914833206635744">"លុប"</string>
<string name="keyboardview_keycode_done" msgid="1992571118466679775">"រួចរាល់"</string>
<string name="keyboardview_keycode_mode_change" msgid="4547387741906537519">"ប្ដូរ​របៀប"</string>
@@ -120,7 +120,7 @@
<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>
+ <string name="kg_login_password_hint" msgid="9057289103827298549">"ពាក្យសម្ងាត់​"</string>
<string name="kg_login_submit_button" msgid="5355904582674054702">"ចូល"</string>
<string name="kg_login_invalid_input" msgid="5754664119319872197">"ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​មិន​ត្រឹមត្រូវ។"</string>
<string name="kg_login_account_recovery_hint" msgid="5690709132841752974">"ភ្លេច​ឈ្មោះ​អ្នកប្រើ ឬ​ពាក្យ​សម្ងាត់​របស់​អ្នក?\nមើល "<b>"google.com/accounts/recovery"</b>" ។"</string>
diff --git a/packages/Keyguard/res/values-sw600dp/dimens.xml b/packages/Keyguard/res/values-sw600dp/dimens.xml
index b954792..e9e9b89 100644
--- a/packages/Keyguard/res/values-sw600dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp/dimens.xml
@@ -70,4 +70,7 @@
<!-- EmergencyCarrierArea overlap - amount to overlap the emergency button and carrier text.
Should be 0 on devices with plenty of room (e.g. tablets) -->
<dimen name="eca_overlap">0dip</dimen>
+
+ <!-- The vertical margin between the date and the owner info. -->
+ <dimen name="date_owner_info_margin">4dp</dimen>
</resources>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index e9cdfcd..f971522 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -163,4 +163,7 @@
<!-- The y translation to apply at the start in appear animations. -->
<dimen name="appear_y_translation_start">32dp</dimen>
+
+ <!-- The vertical margin between the date and the owner info. -->
+ <dimen name="date_owner_info_margin">2dp</dimen>
</resources>
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 8cf07fa..55d8d81 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -59,8 +59,8 @@
<string name="keyguard_charged">Charged</string>
<!-- When the lock screen is showing and the phone plugged in, and the battery
- is not fully charged, show the current charge %. -->
- <string name="keyguard_plugged_in">Charging, <xliff:g id="number">%d</xliff:g><xliff:g id="percent">%%</xliff:g></string>
+ is not fully charged, say that it's charging. -->
+ <string name="keyguard_plugged_in">Charging</string>
<!-- When the lock screen is showing and the battery is low, warn user to plug
in the phone soon. -->
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
index d589283..9bc2a4d 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
@@ -186,42 +186,16 @@ class KeyguardMessageArea extends TextView {
*/
void update() {
MutableInt icon = new MutableInt(0);
- CharSequence status = concat(getOwnerInfo(), getCurrentMessage());
+ CharSequence status = getCurrentMessage();
setCompoundDrawablesWithIntrinsicBounds(icon.value, 0, 0, 0);
setText(status);
}
- private CharSequence concat(CharSequence... args) {
- StringBuilder b = new StringBuilder();
- if (!TextUtils.isEmpty(args[0])) {
- b.append(args[0]);
- }
- for (int i = 1; i < args.length; i++) {
- CharSequence text = args[i];
- if (!TextUtils.isEmpty(text)) {
- if (b.length() > 0) {
- b.append(mSeparator);
- }
- b.append(text);
- }
- }
- return b.toString();
- }
CharSequence getCurrentMessage() {
return mShowingMessage ? mMessage : null;
}
- String getOwnerInfo() {
- ContentResolver res = getContext().getContentResolver();
- String info = null;
- final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled();
- if (ownerInfoEnabled && !mShowingMessage) {
- info = mLockPatternUtils.getOwnerInfo(mLockPatternUtils.getCurrentUser());
- }
- return info;
- }
-
private void hideMessage(int duration, boolean thenUpdate) {
if (duration > 0) {
Animator anim = ObjectAnimator.ofFloat(this, "alpha", 0f);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index e6de72f..a0b5536 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -475,7 +475,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
interpolator, null);
// And the forgot pattern button
- if (mForgotPatternButton.getVisibility() == View.VISIBLE) {
+ if (mForgotPatternButton != null
+ && mForgotPatternButton.getVisibility() == View.VISIBLE) {
mAppearAnimationUtils.createAnimation(mForgotPatternButton, delay, duration,
startTranslationY, interpolator, null);
}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index bef94fa..7918755 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -16,6 +16,7 @@
package com.android.keyguard;
+import android.content.ContentResolver;
import android.content.Context;
import android.content.res.Resources;
import android.text.TextUtils;
@@ -41,6 +42,7 @@ public class KeyguardStatusView extends GridLayout {
private TextView mAlarmStatusView;
private TextClock mDateView;
private TextClock mClockView;
+ private TextView mOwnerInfo;
private KeyguardUpdateMonitorCallback mInfoCallback = new KeyguardUpdateMonitorCallback() {
@@ -54,6 +56,7 @@ public class KeyguardStatusView extends GridLayout {
if (showing) {
if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
refresh();
+ updateOwnerInfo();
}
}
@@ -83,6 +86,7 @@ public class KeyguardStatusView extends GridLayout {
private void setEnableMarquee(boolean enabled) {
if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee");
if (mAlarmStatusView != null) mAlarmStatusView.setSelected(enabled);
+ mOwnerInfo.setSelected(enabled);
}
@Override
@@ -91,10 +95,12 @@ public class KeyguardStatusView extends GridLayout {
mAlarmStatusView = (TextView) findViewById(R.id.alarm_status);
mDateView = (TextClock) findViewById(R.id.date_view);
mClockView = (TextClock) findViewById(R.id.clock_view);
+ mOwnerInfo = (TextView) findViewById(R.id.owner_info);
mLockPatternUtils = new LockPatternUtils(getContext());
final boolean screenOn = KeyguardUpdateMonitor.getInstance(mContext).isScreenOn();
setEnableMarquee(screenOn);
refresh();
+ updateOwnerInfo();
// Disable elegant text height because our fancy colon makes the ymin value huge for no
// reason.
@@ -124,6 +130,16 @@ public class KeyguardStatusView extends GridLayout {
}
}
+ private void updateOwnerInfo() {
+ String ownerInfo = getOwnerInfo();
+ if (!TextUtils.isEmpty(ownerInfo)) {
+ mOwnerInfo.setVisibility(View.VISIBLE);
+ mOwnerInfo.setText(ownerInfo);
+ } else {
+ mOwnerInfo.setVisibility(View.GONE);
+ }
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -140,6 +156,16 @@ public class KeyguardStatusView extends GridLayout {
return LockPatternUtils.ID_DEFAULT_STATUS_WIDGET;
}
+ private String getOwnerInfo() {
+ ContentResolver res = getContext().getContentResolver();
+ String info = null;
+ final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled();
+ if (ownerInfoEnabled) {
+ info = mLockPatternUtils.getOwnerInfo(mLockPatternUtils.getCurrentUser());
+ }
+ return info;
+ }
+
// DateFormat.getBestDateTimePattern is extremely expensive, and refresh is called often.
// This is an optimization to ensure we only recompute the patterns when the inputs change.
private static final class Patterns {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index fef971c..668e1ef 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -418,7 +418,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
}
}
- /* package */ static class BatteryStatus {
+ public static class BatteryStatus {
public final int status;
public final int level;
public final int plugged;
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
deleted file mode 100644
index 20af2f1..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.keyguard.analytics;
-
-import com.google.protobuf.nano.CodedOutputByteBufferNano;
-import com.google.protobuf.nano.MessageNano;
-
-import android.content.Context;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.AsyncTask;
-import android.util.Log;
-import android.view.MotionEvent;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * Tracks sessions, touch and sensor events in Keyguard.
- *
- * A session starts when the user is presented with the Keyguard and ends when the Keyguard is no
- * longer visible to the user.
- */
-public class KeyguardAnalytics implements SensorEventListener {
-
- private static final boolean DEBUG = false;
- private static final String TAG = "KeyguardAnalytics";
- private static final long TIMEOUT_MILLIS = 11000; // 11 seconds.
-
- private static final int[] SENSORS = new int[] {
- Sensor.TYPE_ACCELEROMETER,
- Sensor.TYPE_GYROSCOPE,
- Sensor.TYPE_PROXIMITY,
- Sensor.TYPE_LIGHT,
- Sensor.TYPE_ROTATION_VECTOR,
- };
-
- private Session mCurrentSession = null;
- // Err on the side of caution, so logging is not started after a crash even tough the screen
- // is off.
- private boolean mScreenOn = false;
- private boolean mHidden = false;
-
- private final SensorManager mSensorManager;
- private final SessionTypeAdapter mSessionTypeAdapter;
- private final File mAnalyticsFile;
-
- public KeyguardAnalytics(Context context, SessionTypeAdapter sessionTypeAdapter,
- File analyticsFile) {
- mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
- mSessionTypeAdapter = sessionTypeAdapter;
- mAnalyticsFile = analyticsFile;
- }
-
- public Callback getCallback() {
- return mCallback;
- }
-
- public interface Callback {
- public void onShow();
- public void onHide();
- public void onScreenOn();
- public void onScreenOff();
- public boolean onTouchEvent(MotionEvent ev, int width, int height);
- public void onSetOccluded(boolean hidden);
- }
-
- public interface SessionTypeAdapter {
- public int getSessionType();
- }
-
- private void sessionEntrypoint() {
- if (mCurrentSession == null && mScreenOn && !mHidden) {
- onSessionStart();
- }
- }
-
- private void sessionExitpoint(int result) {
- if (mCurrentSession != null) {
- onSessionEnd(result);
- }
- }
-
- private void onSessionStart() {
- int type = mSessionTypeAdapter.getSessionType();
- mCurrentSession = new Session(System.currentTimeMillis(), System.nanoTime(), type);
- if (type == Session.TYPE_KEYGUARD_SECURE) {
- mCurrentSession.setRedactTouchEvents();
- }
- for (int sensorType : SENSORS) {
- Sensor s = mSensorManager.getDefaultSensor(sensorType);
- if (s != null) {
- mSensorManager.registerListener(this, s, SensorManager.SENSOR_DELAY_GAME);
- }
- }
- if (DEBUG) {
- Log.d(TAG, "onSessionStart()");
- }
- }
-
- private void onSessionEnd(int result) {
- if (DEBUG) {
- Log.d(TAG, String.format("onSessionEnd(success=%d)", result));
- }
- mSensorManager.unregisterListener(this);
-
- Session session = mCurrentSession;
- mCurrentSession = null;
-
- session.end(System.currentTimeMillis(), result);
- queueSession(session);
- }
-
- private void queueSession(final Session currentSession) {
- if (DEBUG) {
- Log.i(TAG, "Saving session.");
- }
- new AsyncTask<Void, Void, Void>() {
- @Override
- protected Void doInBackground(Void... params) {
- try {
- byte[] b = writeDelimitedProto(currentSession.toProto());
- OutputStream os = new FileOutputStream(mAnalyticsFile, true /* append */);
- if (DEBUG) {
- Log.d(TAG, String.format("Serialized size: %d kB.", b.length / 1024));
- }
- try {
- os.write(b);
- os.flush();
- } finally {
- try {
- os.close();
- } catch (IOException e) {
- Log.e(TAG, "Exception while closing file", e);
- }
- }
- } catch (IOException e) {
- Log.e(TAG, "Exception while writing file", e);
- }
- return null;
- }
-
- private byte[] writeDelimitedProto(MessageNano proto)
- throws IOException {
- byte[] result = new byte[CodedOutputByteBufferNano.computeMessageSizeNoTag(proto)];
- CodedOutputByteBufferNano ob = CodedOutputByteBufferNano.newInstance(result);
- ob.writeMessageNoTag(proto);
- ob.checkNoSpaceLeft();
- return result;
- }
- }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
- }
-
- @Override
- public synchronized void onSensorChanged(SensorEvent event) {
- if (false) {
- Log.v(TAG, String.format(
- "onSensorChanged(name=%s, values[0]=%f)",
- event.sensor.getName(), event.values[0]));
- }
- if (mCurrentSession != null) {
- mCurrentSession.addSensorEvent(event, System.nanoTime());
- enforceTimeout();
- }
- }
-
- private void enforceTimeout() {
- if (System.currentTimeMillis() - mCurrentSession.getStartTimestampMillis()
- > TIMEOUT_MILLIS) {
- onSessionEnd(Session.RESULT_UNKNOWN);
- if (DEBUG) {
- Log.i(TAG, "Analytics timed out.");
- }
- }
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- private final Callback mCallback = new Callback() {
- @Override
- public void onShow() {
- if (DEBUG) {
- Log.d(TAG, "onShow()");
- }
- synchronized (KeyguardAnalytics.this) {
- sessionEntrypoint();
- }
- }
-
- @Override
- public void onHide() {
- if (DEBUG) {
- Log.d(TAG, "onHide()");
- }
- synchronized (KeyguardAnalytics.this) {
- sessionExitpoint(Session.RESULT_SUCCESS);
- }
- }
-
- @Override
- public void onScreenOn() {
- if (DEBUG) {
- Log.d(TAG, "onScreenOn()");
- }
- synchronized (KeyguardAnalytics.this) {
- mScreenOn = true;
- sessionEntrypoint();
- }
- }
-
- @Override
- public void onScreenOff() {
- if (DEBUG) {
- Log.d(TAG, "onScreenOff()");
- }
- synchronized (KeyguardAnalytics.this) {
- mScreenOn = false;
- sessionExitpoint(Session.RESULT_FAILURE);
- }
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev, int width, int height) {
- if (DEBUG) {
- Log.v(TAG, "onTouchEvent(ev.action="
- + MotionEvent.actionToString(ev.getAction()) + ")");
- }
- synchronized (KeyguardAnalytics.this) {
- if (mCurrentSession != null) {
- mCurrentSession.addMotionEvent(ev);
- mCurrentSession.setTouchArea(width, height);
- enforceTimeout();
- }
- }
- return true;
- }
-
- @Override
- public void onSetOccluded(boolean hidden) {
- synchronized (KeyguardAnalytics.this) {
- if (hidden != mHidden) {
- if (DEBUG) {
- Log.d(TAG, "onSetOccluded(" + hidden + ")");
- }
- mHidden = hidden;
- if (hidden) {
- // Could have gone to camera on purpose / by falsing or an app could have
- // launched on top of the lockscreen.
- sessionExitpoint(Session.RESULT_UNKNOWN);
- } else {
- sessionEntrypoint();
- }
- }
- }
- }
- };
-
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java b/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java
deleted file mode 100644
index e68f751..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/PointerTracker.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.keyguard.analytics;
-
-import android.graphics.RectF;
-import android.util.FloatMath;
-import android.util.SparseArray;
-import android.view.MotionEvent;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.TouchEvent.BoundingBox;
-
-/**
- * Takes motion events and tracks the length and bounding box of each pointer gesture as well as
- * the bounding box of the whole gesture.
- */
-public class PointerTracker {
- private SparseArray<Pointer> mPointerInfoMap = new SparseArray<Pointer>();
- private RectF mTotalBoundingBox = new RectF();
-
- public void addMotionEvent(MotionEvent ev) {
- if (ev.getActionMasked() == MotionEvent.ACTION_DOWN) {
- float x = ev.getX();
- float y = ev.getY();
- mTotalBoundingBox.set(x, y, x, y);
- }
- for (int i = 0; i < ev.getPointerCount(); i++) {
- int id = ev.getPointerId(i);
- Pointer pointer = getPointer(id);
- float x = ev.getX(i);
- float y = ev.getY(i);
- boolean down = ev.getActionMasked() == MotionEvent.ACTION_DOWN
- || (ev.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN
- && ev.getActionIndex() == i);
- pointer.addPoint(x, y, down);
- mTotalBoundingBox.union(x, y);
- }
- }
-
- public float getPointerLength(int id) {
- return getPointer(id).length;
- }
-
- public BoundingBox getBoundingBox() {
- return boundingBoxFromRect(mTotalBoundingBox);
- }
-
- public BoundingBox getPointerBoundingBox(int id) {
- return boundingBoxFromRect(getPointer(id).boundingBox);
- }
-
- private BoundingBox boundingBoxFromRect(RectF f) {
- BoundingBox bb = new BoundingBox();
- bb.setHeight(f.height());
- bb.setWidth(f.width());
- return bb;
- }
-
- private Pointer getPointer(int id) {
- Pointer p = mPointerInfoMap.get(id);
- if (p == null) {
- p = new Pointer();
- mPointerInfoMap.put(id, p);
- }
- return p;
- }
-
- private static class Pointer {
- public float length;
- public final RectF boundingBox = new RectF();
-
- private float mLastX;
- private float mLastY;
-
- public void addPoint(float x, float y, boolean down) {
- float deltaX;
- float deltaY;
- if (down) {
- boundingBox.set(x, y, x, y);
- length = 0f;
- deltaX = 0;
- deltaY = 0;
- } else {
- deltaX = x - mLastX;
- deltaY = y - mLastY;
- }
- mLastX = x;
- mLastY = y;
- length += FloatMath.sqrt(deltaX * deltaX + deltaY * deltaY);
- boundingBox.union(x, y);
- }
- }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/Session.java b/packages/Keyguard/src/com/android/keyguard/analytics/Session.java
deleted file mode 100644
index 05f9165..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/Session.java
+++ /dev/null
@@ -1,220 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.keyguard.analytics;
-
-import android.os.Build;
-import android.util.Slog;
-import android.view.MotionEvent;
-
-import java.util.ArrayList;
-
-import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.SensorEvent;
-import static com.android.keyguard.analytics.KeyguardAnalyticsProtos.Session.TouchEvent;
-
-/**
- * Records data about one keyguard session.
- *
- * The recorded data contains start and end of the session, whether it unlocked the device
- * successfully, sensor data and touch data.
- *
- * If the keyguard is secure, the recorded touch data will correlate or contain the user pattern or
- * PIN. If this is not desired, the touch coordinates can be redacted before serialization.
- */
-public class Session {
-
- private static final String TAG = "KeyguardAnalytics";
- private static final boolean DEBUG = false;
-
- /**
- * The user has failed to unlock the device in this session.
- */
- public static final int RESULT_FAILURE = KeyguardAnalyticsProtos.Session.FAILURE;
- /**
- * The user has succeeded in unlocking the device in this session.
- */
- public static final int RESULT_SUCCESS = KeyguardAnalyticsProtos.Session.SUCCESS;
-
- /**
- * It is unknown how the session with the keyguard ended.
- */
- public static final int RESULT_UNKNOWN = KeyguardAnalyticsProtos.Session.UNKNOWN;
-
- /**
- * This session took place on an insecure keyguard.
- */
- public static final int TYPE_KEYGUARD_INSECURE
- = KeyguardAnalyticsProtos.Session.KEYGUARD_INSECURE;
-
- /**
- * This session took place on an secure keyguard.
- */
- public static final int TYPE_KEYGUARD_SECURE
- = KeyguardAnalyticsProtos.Session.KEYGUARD_SECURE;
-
- /**
- * This session took place during a fake wake up of the device.
- */
- public static final int TYPE_RANDOM_WAKEUP = KeyguardAnalyticsProtos.Session.RANDOM_WAKEUP;
-
-
- private final PointerTracker mPointerTracker = new PointerTracker();
-
- private final long mStartTimestampMillis;
- private final long mStartSystemTimeNanos;
- private final int mType;
-
- private boolean mRedactTouchEvents;
- private ArrayList<TouchEvent> mMotionEvents = new ArrayList<TouchEvent>(200);
- private ArrayList<SensorEvent> mSensorEvents = new ArrayList<SensorEvent>(600);
- private int mTouchAreaHeight;
- private int mTouchAreaWidth;
-
- private long mEndTimestampMillis;
- private int mResult;
- private boolean mEnded;
-
- public Session(long startTimestampMillis, long startSystemTimeNanos, int type) {
- mStartTimestampMillis = startTimestampMillis;
- mStartSystemTimeNanos = startSystemTimeNanos;
- mType = type;
- }
-
- public void end(long endTimestampMillis, int result) {
- mEnded = true;
- mEndTimestampMillis = endTimestampMillis;
- mResult = result;
- }
-
- public void addMotionEvent(MotionEvent motionEvent) {
- if (mEnded) {
- return;
- }
- mPointerTracker.addMotionEvent(motionEvent);
- mMotionEvents.add(protoFromMotionEvent(motionEvent));
- }
-
- public void addSensorEvent(android.hardware.SensorEvent eventOrig, long systemTimeNanos) {
- if (mEnded) {
- return;
- }
- SensorEvent event = protoFromSensorEvent(eventOrig, systemTimeNanos);
- mSensorEvents.add(event);
- if (DEBUG) {
- Slog.v(TAG, String.format("addSensorEvent(name=%s, values[0]=%f",
- event.getType(), event.values[0]));
- }
- }
-
- @Override
- public String toString() {
- final StringBuilder sb = new StringBuilder("Session{");
- sb.append("mType=").append(mType);
- sb.append(", mStartTimestampMillis=").append(mStartTimestampMillis);
- sb.append(", mStartSystemTimeNanos=").append(mStartSystemTimeNanos);
- sb.append(", mEndTimestampMillis=").append(mEndTimestampMillis);
- sb.append(", mResult=").append(mResult);
- sb.append(", mRedactTouchEvents=").append(mRedactTouchEvents);
- sb.append(", mTouchAreaHeight=").append(mTouchAreaHeight);
- sb.append(", mTouchAreaWidth=").append(mTouchAreaWidth);
- sb.append(", mMotionEvents=[size=").append(mMotionEvents.size()).append("]");
- sb.append(", mSensorEvents=[size=").append(mSensorEvents.size()).append("]");
- sb.append('}');
- return sb.toString();
- }
-
- public KeyguardAnalyticsProtos.Session toProto() {
- KeyguardAnalyticsProtos.Session proto = new KeyguardAnalyticsProtos.Session();
- proto.setStartTimestampMillis(mStartTimestampMillis);
- proto.setDurationMillis(mEndTimestampMillis - mStartTimestampMillis);
- proto.setBuild(Build.FINGERPRINT);
- proto.setResult(mResult);
- proto.sensorEvents = mSensorEvents.toArray(proto.sensorEvents);
- proto.touchEvents = mMotionEvents.toArray(proto.touchEvents);
- proto.setTouchAreaWidth(mTouchAreaWidth);
- proto.setTouchAreaHeight(mTouchAreaHeight);
- proto.setType(mType);
- if (mRedactTouchEvents) {
- redactTouchEvents(proto.touchEvents);
- }
- return proto;
- }
-
- private void redactTouchEvents(TouchEvent[] touchEvents) {
- for (int i = 0; i < touchEvents.length; i++) {
- TouchEvent t = touchEvents[i];
- for (int j = 0; j < t.pointers.length; j++) {
- TouchEvent.Pointer p = t.pointers[j];
- p.clearX();
- p.clearY();
- }
- t.setRedacted(true);
- }
- }
-
- private SensorEvent protoFromSensorEvent(android.hardware.SensorEvent ev, long sysTimeNanos) {
- SensorEvent proto = new SensorEvent();
- proto.setType(ev.sensor.getType());
- proto.setTimeOffsetNanos(sysTimeNanos - mStartSystemTimeNanos);
- proto.setTimestamp(ev.timestamp);
- proto.values = ev.values.clone();
- return proto;
- }
-
- private TouchEvent protoFromMotionEvent(MotionEvent ev) {
- int count = ev.getPointerCount();
- TouchEvent proto = new TouchEvent();
- proto.setTimeOffsetNanos(ev.getEventTimeNano() - mStartSystemTimeNanos);
- proto.setAction(ev.getActionMasked());
- proto.setActionIndex(ev.getActionIndex());
- proto.pointers = new TouchEvent.Pointer[count];
- for (int i = 0; i < count; i++) {
- TouchEvent.Pointer p = new TouchEvent.Pointer();
- p.setX(ev.getX(i));
- p.setY(ev.getY(i));
- p.setSize(ev.getSize(i));
- p.setPressure(ev.getPressure(i));
- p.setId(ev.getPointerId(i));
- proto.pointers[i] = p;
- if ((ev.getActionMasked() == MotionEvent.ACTION_POINTER_UP && ev.getActionIndex() == i)
- || ev.getActionMasked() == MotionEvent.ACTION_UP) {
- p.boundingBox = mPointerTracker.getPointerBoundingBox(p.getId());
- p.setLength(mPointerTracker.getPointerLength(p.getId()));
- }
- }
- if (ev.getActionMasked() == MotionEvent.ACTION_UP) {
- proto.boundingBox = mPointerTracker.getBoundingBox();
- }
- return proto;
- }
-
- /**
- * Discards the x / y coordinates of the touch events on serialization. Retained are the
- * size of the individual and overall bounding boxes and the length of each pointer's gesture.
- */
- public void setRedactTouchEvents() {
- mRedactTouchEvents = true;
- }
-
- public void setTouchArea(int width, int height) {
- mTouchAreaWidth = width;
- mTouchAreaHeight = height;
- }
-
- public long getStartTimestampMillis() {
- return mStartTimestampMillis;
- }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto b/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto
deleted file mode 100644
index 68b1590..0000000
--- a/packages/Keyguard/src/com/android/keyguard/analytics/keyguard_analytics.proto
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-syntax = "proto2";
-
-package keyguard;
-
-option java_package = "com.android.keyguard.analytics";
-option java_outer_classname = "KeyguardAnalyticsProtos";
-
-message Session {
- message TouchEvent {
- message BoundingBox {
- optional float width = 1;
- optional float height = 2;
- }
-
- enum Action {
- // Keep in sync with MotionEvent.
- DOWN = 0;
- UP = 1;
- MOVE = 2;
- CANCEL = 3;
- OUTSIDE = 4;
- POINTER_DOWN = 5;
- POINTER_UP = 6;
- }
-
- message Pointer {
- optional float x = 1;
- optional float y = 2;
- optional float size = 3;
- optional float pressure = 4;
- optional int32 id = 5;
- optional float length = 6;
- // Bounding box of the pointer. Only set on UP or POINTER_UP event of this pointer.
- optional BoundingBox boundingBox = 7;
- }
-
- optional uint64 timeOffsetNanos = 1;
- optional Action action = 2;
- optional int32 actionIndex = 3;
- repeated Pointer pointers = 4;
- /* If true, the the x / y coordinates of the touch events were redacted. Retained are the
- size of the individual and overall bounding boxes and the length of each pointer's
- gesture. */
- optional bool redacted = 5;
- // Bounding box of the whole gesture. Only set on UP event.
- optional BoundingBox boundingBox = 6;
- }
-
- message SensorEvent {
- enum Type {
- ACCELEROMETER = 1;
- GYROSCOPE = 4;
- LIGHT = 5;
- PROXIMITY = 8;
- ROTATION_VECTOR = 11;
- }
-
- optional Type type = 1;
- optional uint64 timeOffsetNanos = 2;
- repeated float values = 3;
- optional uint64 timestamp = 4;
- }
-
- enum Result {
- FAILURE = 0;
- SUCCESS = 1;
- UNKNOWN = 2;
- }
-
- enum Type {
- KEYGUARD_INSECURE = 0;
- KEYGUARD_SECURE = 1;
- RANDOM_WAKEUP = 2;
- }
-
- optional uint64 startTimestampMillis = 1;
- optional uint64 durationMillis = 2;
- optional string build = 3;
- optional Result result = 4;
- repeated TouchEvent touchEvents = 5;
- repeated SensorEvent sensorEvents = 6;
-
- optional int32 touchAreaWidth = 9;
- optional int32 touchAreaHeight = 10;
- optional Type type = 11;
-}
diff --git a/packages/Keyguard/test/SampleTrustAgent/Android.mk b/packages/Keyguard/test/SampleTrustAgent/Android.mk
index 7551fdf..2a18ee1 100644
--- a/packages/Keyguard/test/SampleTrustAgent/Android.mk
+++ b/packages/Keyguard/test/SampleTrustAgent/Android.mk
@@ -20,9 +20,8 @@ LOCAL_SRC_FILES := $(call all-java-files-under, src)
LOCAL_PACKAGE_NAME := SampleTrustAgent
-# Remove these to verify permission checks are working correctly
-#LOCAL_CERTIFICATE := platform
-#LOCAL_PRIVILEGED_MODULE := true
+# Remove this to verify permission checks are working correctly
+LOCAL_CERTIFICATE := platform
LOCAL_MODULE_TAGS := tests
diff --git a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
index 7904927..f3125f1 100644
--- a/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
+++ b/packages/Keyguard/test/SampleTrustAgent/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="com.android.trustagent.test">
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/>
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+ <uses-permission android:name="android.permission.PROVIDE_TRUST_AGENT" />
<application android:label="@string/app_name">
<service
android:name=".SampleTrustAgent"
diff --git a/packages/PrintSpooler/res/values-km-rKH/strings.xml b/packages/PrintSpooler/res/values-km-rKH/strings.xml
index c89f9bf..ba3c042 100644
--- a/packages/PrintSpooler/res/values-km-rKH/strings.xml
+++ b/packages/PrintSpooler/res/values-km-rKH/strings.xml
@@ -60,7 +60,7 @@
</plurals>
<string name="cancel" msgid="4373674107267141885">"បោះបង់"</string>
<string name="restart" msgid="2472034227037808749">"ចាប់ផ្ដើម​ឡើងវិញ"</string>
- <string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មាន​​​ការ​ភ្ជាប់​ទៅ​ម៉ាស៊ីន​បោះពុម្ព"</string>
+ <string name="no_connection_to_printer" msgid="2159246915977282728">"គ្មាន​​​ការ​ភ្ជាប់​ទៅ​ម៉ាស៊ីន​បោះពុម្ព​"</string>
<string name="reason_unknown" msgid="5507940196503246139">"មិន​ស្គាល់"</string>
<string name="printer_unavailable" msgid="2434170617003315690">"<xliff:g id="PRINT_JOB_NAME">%1$s</xliff:g> – មិន​អាច​ប្រើ​បាន"</string>
<string name="print_error_default_message" msgid="8568506918983980567">"មិន​អាច​បង្កើត​ការ​ងារ​បោះពុម្ព"</string>
diff --git a/packages/Shell/res/values-de/strings.xml b/packages/Shell/res/values-de/strings.xml
index 99522b1..34481ba 100644
--- a/packages/Shell/res/values-de/strings.xml
+++ b/packages/Shell/res/values-de/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Fehlerbericht erfasst"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Berühren, um Fehlerbericht zu teilen"</string>
+ <string name="bugreport_finished_text" msgid="3559904746859400732">"Tippen, um Fehlerbericht zu teilen"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Fehlerberichte enthalten Daten aus verschiedenen Protokolldateien des Systems, darunter auch personenbezogene und private Daten. Teilen Sie Fehlerberichte nur mit Apps und Personen, denen Sie vertrauen."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Diese Nachricht nächstes Mal zeigen"</string>
</resources>
diff --git a/packages/Shell/res/values-fr/strings.xml b/packages/Shell/res/values-fr/strings.xml
index 1da6f1f..12f5e88 100644
--- a/packages/Shell/res/values-fr/strings.xml
+++ b/packages/Shell/res/values-fr/strings.xml
@@ -18,7 +18,7 @@
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="app_label" msgid="3701846017049540910">"Shell"</string>
<string name="bugreport_finished_title" msgid="2293711546892863898">"Rapport de bug enregistré"</string>
- <string name="bugreport_finished_text" msgid="3559904746859400732">"Appuyer ici pour partager votre rapport de bug"</string>
+ <string name="bugreport_finished_text" msgid="3559904746859400732">"Appuyez ici pour partager le rapport de bug"</string>
<string name="bugreport_confirm" msgid="5130698467795669780">"Les rapports de bug contiennent des données des fichiers journaux du système, y compris des informations personnelles et privées. Ne partagez les rapports de bug qu\'avec les applications et les personnes que vous estimez fiables."</string>
<string name="bugreport_confirm_repeat" msgid="4926842460688645058">"Afficher ce message la prochaine fois"</string>
</resources>
diff --git a/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png
new file mode 100644
index 0000000..6cd1176
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/recents_nav_bar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png
new file mode 100644
index 0000000..7237f09
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/recents_nav_bar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png
new file mode 100644
index 0000000..8d56a1d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/recents_nav_bar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png
new file mode 100644
index 0000000..aed300b
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_nav_bar_background.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_06.xml b/packages/SystemUI/res/drawable/ic_qs_location_06.xml
index 25c9ae5..5642a8a 100644
--- a/packages/SystemUI/res/drawable/ic_qs_location_06.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_location_06.xml
@@ -27,7 +27,5 @@ Copyright (C) 2014 The Android Open Source Project
android:pathData="M12.0,16.0c-1.16,0.0 -2.1,0.94 -2.1,2.1C9.9,19.67 12.0,22.0 12.0,22.0s2.1,-2.33 2.1,-3.9C14.1,16.94 13.16,16.0 12.0,16.0zM12.0,18.85c-0.41,0.0 -0.75,-0.34 -0.75,-0.75s0.34,-0.75 0.75,-0.75c0.41,0.0 0.75,0.34 0.75,0.75S12.41,18.85 12.0,18.85z"/>
<path
android:pathData="M11.99,15c-1.35,0,-2.45,1.1,-2.45,2.45 c0,1.84,2.45,4.55,2.45,4.55s2.45,-2.71,2.45,-4.55C14.44,16.1,13.34,15,11.99,15z M11.99,18.33c-0.48,0,-0.88,-0.39,-0.88,-0.88 s0.39,-0.88,0.88,-0.88c0.48,0,0.87,0.39,0.87,0.88S12.47,18.33,11.99,18.33z"
- android:strokeWidth=".35"
- android:fill="#00000000"
- android:stroke="#CCCCCC"/>
+ android:fill="#4DFFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_07.xml b/packages/SystemUI/res/drawable/ic_qs_location_07.xml
index a69c3a2..1ad2ebc 100644
--- a/packages/SystemUI/res/drawable/ic_qs_location_07.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_location_07.xml
@@ -24,7 +24,5 @@ Copyright (C) 2014 The Android Open Source Project
<path
android:pathData="M12,9c-2.51,0,-4.55,2.04,-4.55,4.55 C7.45,16.96,12,22,12,22s4.55,-5.04,4.55,-8.45C16.55,11.04,14.51,9,12,9z M12,15.18c-0.9,0,-1.63,-0.73,-1.63,-1.62 s0.73,-1.62,1.63,-1.62c0.9,0,1.62,0.73,1.62,1.62S12.9,15.18,12,15.18z"
- android:strokeWidth="0.65"
- android:fill="#00000000"
- android:stroke="#CCCCCC"/>
+ android:fill="#4DFFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_08.xml b/packages/SystemUI/res/drawable/ic_qs_location_08.xml
index c89c047..179bc66 100644
--- a/packages/SystemUI/res/drawable/ic_qs_location_08.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_location_08.xml
@@ -24,7 +24,5 @@ Copyright (C) 2014 The Android Open Source Project
<path
android:pathData="M12,6c-3.09,0,-5.6,2.51,-5.6,5.6 C6.4,15.8,12,22,12,22s5.6,-6.2,5.6,-10.4C17.6,8.51,15.09,6,12,6z M12,13.6c-1.1,0,-2,-0.9,-2,-2s0.9,-2,2,-2c1.1,0,2,0.9,2,2 S13.1,13.6,12,13.6z"
- android:strokeWidth="0.8"
- android:fill="#00000000"
- android:stroke="#CCCCCC"/>
+ android:fill="#4DFFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_09.xml b/packages/SystemUI/res/drawable/ic_qs_location_09.xml
index 96bb6ce..6169af5 100644
--- a/packages/SystemUI/res/drawable/ic_qs_location_09.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_location_09.xml
@@ -24,7 +24,5 @@ Copyright (C) 2014 The Android Open Source Project
<path
android:pathData="M12,4c-3.48,0,-6.3,2.82,-6.3,6.3 C5.7,15.02,12,22,12,22s6.3,-6.98,6.3,-11.7C18.3,6.82,15.48,4,12,4z M12,12.55c-1.24,0,-2.25,-1.01,-2.25,-2.25S10.76,8.05,12,8.05 c1.24,0,2.25,1.01,2.25,2.25S13.24,12.55,12,12.55z"
- android:strokeWidth="0.9"
- android:fill="#00000000"
- android:stroke="#CCCCCC"/>
+ android:fill="#4DFFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_10.xml b/packages/SystemUI/res/drawable/ic_qs_location_10.xml
index aced4bd..93e2eb4 100644
--- a/packages/SystemUI/res/drawable/ic_qs_location_10.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_location_10.xml
@@ -24,7 +24,5 @@ Copyright (C) 2014 The Android Open Source Project
<path
android:pathData="M12,3C8.33,3,5.35,5.98,5.35,9.65 C5.35,14.64,12,22,12,22s6.65,-7.36,6.65,-12.35C18.65,5.98,15.67,3,12,3z M12,12.02c-1.31,0,-2.38,-1.06,-2.38,-2.38 S10.69,7.28,12,7.28c1.31,0,2.37,1.06,2.37,2.37S13.31,12.02,12,12.02z"
- android:strokeWidth="0.95"
- android:fill="#00000000"
- android:stroke="#CCCCCC"/>
+ android:fill="#4DFFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/ic_qs_location_11.xml b/packages/SystemUI/res/drawable/ic_qs_location_11.xml
index 578308e..09a3e63 100644
--- a/packages/SystemUI/res/drawable/ic_qs_location_11.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_location_11.xml
@@ -24,7 +24,5 @@ Copyright (C) 2014 The Android Open Source Project
<path
android:pathData="M12,2C8.13,2,5,5.13,5,9c0,5.25,7,13,7,13s7,-7.75,7,-13 C19,5.13,15.87,2,12,2z M12,11.5c-1.38,0,-2.5,-1.12,-2.5,-2.5s1.12,-2.5,2.5,-2.5c1.38,0,2.5,1.12,2.5,2.5S13.38,11.5,12,11.5z"
- android:fill="#00000000"
- android:stroke="#CCCCCC"
- android:strokeWidth="1.0"/>
+ android:fill="#4DFFFFFF"/>
</vector>
diff --git a/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml b/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml
new file mode 100644
index 0000000..b812d43
--- /dev/null
+++ b/packages/SystemUI/res/drawable/keyguard_overflow_number_background.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2014 The Android Open Source Project
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License
+ -->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+ android:shape="oval">
+ <solid android:color="#1a000000" />
+</shape> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml b/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
new file mode 100644
index 0000000..463fee8
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_nav_bar_scrim.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<ImageView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal|bottom"
+ android:scaleType="fitXY"
+ android:src="@drawable/recents_nav_bar_background" /> \ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
index f867068..c442f79 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -32,20 +32,20 @@
/>
<TextView
android:id="@+id/more_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
+ android:layout_width="32dp"
+ android:layout_height="32dp"
+ android:layout_marginStart="20dp"
android:layout_gravity="center_vertical"
- android:gravity="center_horizontal"
- android:textColor="@color/keyguard_overflow_content_color"
- android:textAllCaps="true"
- android:textAppearance="?android:attr/textAppearanceMedium"
+ android:background="@drawable/keyguard_overflow_number_background"
+ android:gravity="center"
+ android:textColor="#ff686868"
+ android:textStyle="bold"
+ android:textSize="14dp"
/>
<com.android.systemui.statusbar.NotificationOverflowIconsView
android:id="@+id/overflow_icons_view"
- android:layout_gravity="end|center_vertical"
- android:gravity="end"
- android:paddingLeft="8dp"
- android:paddingRight="8dp"
+ android:layout_gravity="center_vertical"
+ android:layout_marginStart="68dp"
android:layout_width="120dp"
android:layout_height="wrap_content"
/>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml b/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
index ff8800c..84d64b9 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_speed_bump.xml
@@ -28,7 +28,7 @@
android:layout_height="@dimen/speed_bump_height_collapsed"
android:layout_gravity="top"
android:orientation="horizontal">
- <View
+ <com.android.systemui.statusbar.AlphaOptimizedView
android:id="@+id/speedbump_line_left"
android:layout_width="0dp"
android:layout_height="1dp"
@@ -42,7 +42,7 @@
android:layout_marginEnd="8dp"
android:layout_height="match_parent"
android:layout_weight="0"/>
- <View
+ <com.android.systemui.statusbar.AlphaOptimizedView
android:id="@+id/speedbump_line_right"
android:layout_width="0dp"
android:layout_height="1dp"
diff --git a/packages/SystemUI/res/layout/volume_panel_item.xml b/packages/SystemUI/res/layout/volume_panel_item.xml
index 4a2a0c0..6e5ab47 100644
--- a/packages/SystemUI/res/layout/volume_panel_item.xml
+++ b/packages/SystemUI/res/layout/volume_panel_item.xml
@@ -35,7 +35,6 @@
android:layout_height="wrap_content"
android:layout_weight="1">
<SeekBar
- style="?android:attr/seekBarStyle"
android:id="@+id/seekbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index c45254e..c642626 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Aan."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Af"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Gekoppel."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"USB-verbinding"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Warmkol"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Kennisgewings"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"ONLANGS"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Geen onlangse programme nie"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Programinligting"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk word\ndalk gemonitor"</string>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 5c4d98b..d864f9f 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"በርቷል።"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"ጠፍቷል።"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"ተገናኝቷል።"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"ብሉቱዝ <xliff:g id="STATE">%s</xliff:g>።"</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"አካባቢ <xliff:g id="STATE">%s</xliff:g>።"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ማንቂያ ለ<xliff:g id="TIME">%s</xliff:g> ተዋቅሯል።"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"ፓነል ዝጋ"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"ተጨማሪ ጊዜ"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"ያነሰ ጊዜ"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ውሂብ ቦዝኗል"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G ውሂብ ቦዝኗል"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"የተንቀሳቃሽ ውሂብ ቦዝኗል"</string>
@@ -213,9 +212,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"ተጨማሪ ቅንብሮች"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"በማገናኘት ላይ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"መገናኛ ነጥብ"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"የቅርብ ጊዜዎች"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"ማሳወቂያዎች"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"ምንም የቅርብ ጊዜ መተግበሪያዎች የሉም"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"አውታረ መረብ\nክትትል ሊደረግበት ይችላል"</string>
@@ -234,10 +232,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"በጣም አስቸካይ ያልሆኑ ማሳወቂያዎች ከታች"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ለመክፈት ዳግም መታ ያድርጉ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ለማስከፈት ወደ ላይ ያንሸራትቱ"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"ይህን እስኪያጠፉት ድረስ"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"ለአንድ ደቂቃ"</item>
+ <item quantity="other" msgid="6924190729213550991">"ለ%d ደቂቃዎች"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"ለአንድ ሰዓት"</item>
+ <item quantity="other" msgid="5408537517529822157">"ለ%d ሰዓቶች"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index d7c5651..3906bfa 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"تم التشغيل."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"تم الإيقاف."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"متصل."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1‎ X‎"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"النطاق"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطة اتصال"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"الإشعارات"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"الأخيرة"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"ليست هناك تطبيقات حديثة"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"قد تكون الشبكة\nخاضعة للرقابة"</string>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 2405804..6ef23ad 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Вкл."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Изкл."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Има връзка."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Тетъринг"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка за достъп"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Известия"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"СКОРОШНИ"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Няма скорошни приложения"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежата може\nда се наблюдава"</string>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 982e0c6..9e3495e 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Activat."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Desactivat."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Connectat."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ancoratge a xarxa"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificacions"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"No hi ha aplicacions recents."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"És possible que la xarxa\nestigui controlada"</string>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 570e1bb..6050da4 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Zapnuto."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Vypnuto."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Připojeno."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Sdílení datového připojení"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Oznámení"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"POSLEDNÍ"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Žádné nedávné aplikace"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informace o aplikaci"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Síť může být\nmonitorována"</string>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 127192a..830bebf 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Til."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Fra."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Forbundet."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Netdeling"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Underretninger"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"SENESTE"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Der er ingen seneste apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netværket kan\nvære overvåget"</string>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c9c7b8e..72c9d64 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"An"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Aus"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Verbunden"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Benachrichtigungen"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"Letzte"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Keine neuen Apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netzwerk wird\neventuell überwacht."</string>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 1d90dae..2d3f246 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Ενεργό."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Ανενεργό."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Έχει συνδεθεί."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Πρόσδεση"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Σημείο πρόσβασης Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ειδοποιήσεις"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"ΠΡΟΣΦΑΤΑ"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Καμία πρόσφατη εφαρμογή"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Το δίκτυο μπορεί\nνα παρακολουθείται"</string>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index a9c6678..66233cc 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"On."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Off."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Connected."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index a9c6678..66233cc 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"On."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Off."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Connected."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"No recent apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 6ca4ebc..0810ee7 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Activado"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Desactivado"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,8 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"RECIENTES"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
+ <skip />
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Es posible que la red\nesté supervisada."</string>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index d0e9c0a..ad92c24 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Sí"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"No"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Anclaje a red"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificaciones"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"RECIENTES"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"No hay aplicaciones recientes"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La red se\npuede supervisar"</string>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index c692b28..71e2af6 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Sees."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Väljas."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Ühendatud."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jagamine"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Leviala"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Märguanded"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"HILJUTISED"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Hiljutisi rakendusi pole"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Võrku võidakse\njälgida"</string>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index ee2c48d..3ea2110 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"روشن."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"خاموش."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"متصل."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"اتصال به اینترنت با تلفن همراه"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"نقطه اتصال"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"اعلان‌ها"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"موارد اخیر"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"هیچ برنامه جدیدی موجود نیست"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"اطلاعات برنامه"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ممکن است شبکه\nتحت نظارت باشد"</string>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 44d35b3..eb68ea6 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Käytössä."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Pois käytöstä."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Yhdistetty."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,8 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Jaettu yhteys"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ilmoitukset"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"VIIMEISIMMÄT"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
+ <skip />
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Verkkoa saatetaan\nvalvoa"</string>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index d9790f6..4c1df8c 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Activé"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Désactivé"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Connecté"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1x"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"3G+"</string>
@@ -158,12 +160,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Localisation <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Fermer le panneau"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Plus longtemps"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Moins longtemps"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G désactivées"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Données mobiles désactivées"</string>
@@ -215,9 +214,9 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès sans fil"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
<skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"RÉCENTS"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
@@ -236,10 +235,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes affichées ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Touchez à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glissez vers le haut pour déverrouiller"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
+ <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
+ <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index d95fe06..bd709a0 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Activé"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Désactivé"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Connecté"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1x"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth : <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Localisation <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme réglée sur <xliff:g id="TIME">%s</xliff:g>"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Fermer le panneau"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Plus longtemps"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Moins longtemps"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Données 2G-3G désactivées"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Données 4G désactivées"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Données mobiles désactivées"</string>
@@ -215,9 +214,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Plus de paramètres"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Partage de connexion"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Point d\'accès"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"RÉCENTS"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifications"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Aucune application récente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informations sur l\'application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
@@ -236,10 +234,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notifications moins urgentes ci-dessous"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Appuyer à nouveau pour ouvrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Faire glisser pour déverrouiller"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Jusqu\'à la désactivation"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Pendant une minute"</item>
+ <item quantity="other" msgid="6924190729213550991">"Pendant %d minutes"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Pendant une heure"</item>
+ <item quantity="other" msgid="5408537517529822157">"Pendant %d heures"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 60d7de1..d6b6d6a 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"चालू."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"बंद."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"कनेक्ट है."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"टेदरिंग"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"हॉटस्पॉट"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"सूचनाएं"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"हाल ही का"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"कोई हाल ही का ऐप्स नहीं"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्‍लिकेशन जानकारी"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"नेटवर्क को\nमॉनीटर किया जा सकता है"</string>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 09dde42..79d7003 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Uključeno."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Isključeno."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Povezano."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Dijeljenje veze"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Žarišna točka"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obavijesti"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"NEDAVNO"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Nema nedavnih aplikacija"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mreža se\nmožda prati"</string>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index dc85416..915f5eb 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Bekapcsolva."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Kikapcsolva."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Csatlakoztatva."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Megosztás"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Értesítések"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"LEGUTÓBBIAK"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Nincs újabb alkalmazás"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Lehet, hogy a\nhálózat felügyelt"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index b11a004..ca327d8 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Միացված է:"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Անջատված է:"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Միացված է:"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth-ը <xliff:g id="STATE">%s</xliff:g> է:"</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Տեղադրությունը՝ <xliff:g id="STATE">%s</xliff:g>:"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Զարթուցիչը դրված է <xliff:g id="TIME">%s</xliff:g>-ին:"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Փակել վահանակը"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Ավելացնել ժամանակը"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Քչացնել ժամանակը"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G տվյալները անջատված են"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G տվյալները անջատված են"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Շարժական տվյալները անջատված են"</string>
@@ -213,9 +212,9 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Հավելյալ կարգավորումներ"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Միացում"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Թեժ կետ"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Ծանուցումներ"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
<skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"ՎԵՐՋԻՆՆԵՐԸ"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ցանցը կարող է\nվերահսկվել"</string>
@@ -234,10 +233,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Պակաս հրատապ ծանուցումները ստորև"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Կրկին հպեք՝ բացելու համար"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Սահեցրեք վերև` ապակողպելու համար"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Քանի դեռ չեք անջատել"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Մեկ րոպե"</item>
+ <item quantity="other" msgid="6924190729213550991">"%d րոպե"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Մեկ ժամ"</item>
+ <item quantity="other" msgid="5408537517529822157">"%d ժամ"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index f62209f..48c9a6d 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Aktif."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Nonaktif."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Tersambung."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Menambatkan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"TERBARU"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Tidak ada aplikasi terkini"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Jaringan bisa\ndiawasi"</string>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 6cf13be..8653c8f 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"ON"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"OFF"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Connesso."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notifiche"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"MESSAGGI RECENTI"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Nessuna app recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La rete potrebbe\nessere monitorata"</string>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 4f07006..3279bc1 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"פועל."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"כבוי."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"מחובר."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"‎1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"שיתוף אינטרנט בין ניידים"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"נקודה לשיתוף אינטרנט"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"הודעות"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"אחרונים"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"אין אפליקציות אחרונות"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ייתכן שהרשת\nמנוטרת"</string>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 84bbf8b..a1f7b5e 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"ON"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"OFF"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"接続済みです。"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"現在地: <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"アラームは<xliff:g id="TIME">%s</xliff:g>に設定されています。"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"パネルを閉じる"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"長くする"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"短くする"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G~3Gデータが無効になりました"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4Gデータが無効になりました"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"モバイルデータが無効になりました"</string>
@@ -215,9 +214,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"詳細設定"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"テザリング"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"アクセスポイント"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"最近"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"最近使ったアプリはありません"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ネットワークが監視される\n場合があります"</string>
@@ -236,10 +234,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"緊急度の低い通知を下に表示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"開くにはもう一度タップしてください"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ロック解除するには上にスワイプしてください"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"ユーザーがOFFにするまで"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"1分"</item>
+ <item quantity="other" msgid="6924190729213550991">"%d分"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"1時間"</item>
+ <item quantity="other" msgid="5408537517529822157">"%d時間"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index c31ea24..a1862da 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"ჩართული"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"გამორთულია."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"დაკავშირებულია."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"მდებარეობა <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"მაღვიძარა დაყენებულია: <xliff:g id="TIME">%s</xliff:g>"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"არეს დახურვა"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"მეტი დრო"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"ნაკლები დრო"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G ინტერნეტი გაითიშა."</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G მონაცემები გათიშულია"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"მობილური ინტერნეტი გაითიშა."</string>
@@ -213,9 +212,9 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"დამატებითი პარამეტრები"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"მოდემის რეჟიმი"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"წვდომის წერტილი"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"შეტყობინებები"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
<skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"ბოლო დროის"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"შესაძლოა ქსელზე\nმონიტორინგი ხორციელდებოდეს"</string>
@@ -234,10 +233,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ქვემოთ მითითებულია ნაკლებად სასწრაფო შეტყობინებები"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"შეეხეთ ისევ გასახსნელად"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"გაასრიალეთ ზევით განსაბლოკად"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"სანამ ამას გამორთავდეთ"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"ერთი წუთით"</item>
+ <item quantity="other" msgid="6924190729213550991">"%d წუთით"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"ერთი საათით"</item>
+ <item quantity="other" msgid="5408537517529822157">"%d საათით"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index a9cf7d6..3f5b844 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -64,7 +64,7 @@
<string name="screenshot_saving_ticker" msgid="7403652894056693515">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់…"</string>
<string name="screenshot_saving_title" msgid="8242282144535555697">"កំពុង​រក្សាទុក​រូបថត​អេក្រង់..."</string>
<string name="screenshot_saving_text" msgid="2419718443411738818">"រូបថត​អេក្រង់​កំពុង​ត្រូវ​បាន​រក្សាទុក។"</string>
- <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។"</string>
+ <string name="screenshot_saved_title" msgid="6461865960961414961">"បាន​ចាប់​យក​រូបថត​អេក្រង់។​"</string>
<string name="screenshot_saved_text" msgid="1152839647677558815">"ប៉ះ ​ដើម្បី​មើល​រូបថត​អេក្រង់​របស់​អ្នក​។"</string>
<string name="screenshot_failed_title" msgid="705781116746922771">"មិន​អាច​ចាប់​យក​រូប​ថត​អេក្រង់​។"</string>
<string name="screenshot_failed_text" msgid="8134011269572415402">"មិន​អាច​រក្សាទុក​រូបថត​អេក្រង់​។ ឧបករណ៍​ផ្ទុក​អាច​កំពុង​ប្រើ​​។"</string>
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"បើក។"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"បិទ"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"បាន​តភ្ជាប់។"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -140,7 +142,7 @@
<string name="accessibility_remove_notification" msgid="3603099514902182350">"សម្អាត​ការ​ជូន​ដំណឹង។"</string>
<string name="accessibility_gps_enabled" msgid="3511469499240123019">"បាន​បើក GPS ។"</string>
<string name="accessibility_gps_acquiring" msgid="8959333351058967158">"ទទួល​​ GPS ។"</string>
- <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ"</string>
+ <string name="accessibility_tty_enabled" msgid="4613200365379426561">"បាន​បើក​ម៉ាស៊ីន​អង្គុលីលេខ​"</string>
<string name="accessibility_ringer_vibrate" msgid="666585363364155055">"កម្មវិធី​រោទ៍​ញ័រ។"</string>
<string name="accessibility_ringer_silent" msgid="9061243307939135383">"កម្មវិធី​រោទ៍​ស្ងាត់។"</string>
<string name="accessibility_recents_item_dismissed" msgid="6803574935084867070">"<xliff:g id="APP">%s</xliff:g> បដិសេធ។"</string>
@@ -190,7 +192,7 @@
<string name="quick_settings_rotation_locked_portrait_label" msgid="1553131290066230775">"ចាក់​សោ​​បញ្ឈរ"</string>
<string name="quick_settings_rotation_locked_landscape_label" msgid="7216265671276086593">"ចាក់​សោ​​​ផ្ដេក"</string>
<string name="quick_settings_ime_label" msgid="7073463064369468429">"វិធីសាស្ត្រ​បញ្ចូល"</string>
- <string name="quick_settings_location_label" msgid="5011327048748762257">"ទី​តាំង"</string>
+ <string name="quick_settings_location_label" msgid="5011327048748762257">"ទី​តាំង​"</string>
<string name="quick_settings_location_off_label" msgid="7464544086507331459">"ទីតាំង​បាន​បិទ"</string>
<string name="quick_settings_media_device_label" msgid="1302906836372603762">"ឧបករណ៍​មេឌៀ"</string>
<string name="quick_settings_rssi_label" msgid="7725671335550695589">"RSSI"</string>
@@ -211,10 +213,11 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"ការ​ភ្ជាប់"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ហតស្ប៉ត"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ការ​ជូនដំណឹង"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"ថ្មីៗ"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
+ <skip />
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មាន​កម្មវិធី"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
- <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញ​អាច​\nត្រូវ​បាន​ត្រួតពិនិត្យ"</string>
+ <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញ​អាច​\nត្រូវ​បាន​ត្រួតពិនិត្យ​"</string>
<string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string>
<string name="description_direction_up" msgid="7169032478259485180">"រុញ​ឡើង​លើ​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
<string name="description_direction_left" msgid="7207478719805562165">"រុញ​ទៅ​ឆ្វេង​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index bb2e5c1..4772e54 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"사용"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"사용 안함"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"연결됨"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"테더링"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"핫스팟"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"알림"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"최근"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"최근에 사용한 앱 없음"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"네트워크가\n모니터링될 수 있음"</string>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index 7220777..d5117a9 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"ເປີດ."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"ປິດ."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"ເຊື່ອມ​ຕໍ່ແລ້ວ."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"​ການ​ປ່ອນ​ສັນ​ຍານ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"​ຮັອດ​ສະ​ປອດ"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"ການແຈ້ງເຕືອນ"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"ບໍ່​ດົນ​ມາ​ນີ້"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"ບໍ່​ມີ​ແອັບຯ​ທີ່​ຫາ​ກໍ​ໃຊ້"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"​ຂໍ້​ມູນ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ເຄືອຄ່າຍອາດ\nຖືກຕິດຕາມ"</string>
@@ -230,13 +232,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"ການ​ແຈ້ງເຕືອນ​ທີ່​ສຳຄັນ​ໜ້ອຍ​ກວ່າ​ຢູ່​ດ້ານ​ລຸ່ມ"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"ແຕະ​ອີກ​ຄັ້ງ​ເພື່ອ​ເປີດ"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນ​ຂຶ້ນ​ເພື່ອ​ປົດ​ລັອກ"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າ​ທ່ານ​ຈະ​ປິດ"</string>
+ <string name="zen_mode_forever" msgid="7420011936770086993">"ຈົນກວ່າ​ທ່ານ​ຈະ​ປິດ​"</string>
<plurals name="zen_mode_duration_minutes">
- <item quantity="one" msgid="9040808414992812341">"​ສຳ​ລັບ​ນຶ່ງ​ນາ​ທີ"</item>
- <item quantity="other" msgid="6924190729213550991">"ສຳ​ລັບ %d ນາ​ທີ"</item>
+ <item quantity="one" msgid="9040808414992812341">"ເປັນ​ເວລາ​ນຶ່ງ​ນາ​ທີ"</item>
+ <item quantity="other" msgid="6924190729213550991">"ເປັນ​ເວລາ %d ນາ​ທີ"</item>
</plurals>
<plurals name="zen_mode_duration_hours">
- <item quantity="one" msgid="3480040795582254384">"​ສຳ​ລັບນຶ່ງ​ຊົ່ວ​ໂມງ"</item>
- <item quantity="other" msgid="5408537517529822157">"ສຳ​ລັບ %d ຊົ່ວ​ໂມງ"</item>
+ <item quantity="one" msgid="3480040795582254384">"ເປັນ​ເວລາ​ນຶ່ງ​ຊົ່ວ​ໂມງ"</item>
+ <item quantity="other" msgid="5408537517529822157">"ເປັນ​ເວລາ %d ຊົ່ວ​ໂມງ"</item>
</plurals>
</resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index d0ebd54..574e559 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Įjungta."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Išjungta."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Prijungta."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Susiejimas"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Viešosios interneto prieigos taškas"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pranešimai"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"PASTARIEJI"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Nėra naujausių programų"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tinklas gali\nbūti stebimas"</string>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 23ce4a9..398553d 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Ieslēgts"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Izslēgts"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Savienojums ir izveidots."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,8 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Piesaiste"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tīklājs"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Paziņojumi"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"JAUNĀKIE"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
+ <skip />
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tīkls var\ntikt uzraudzīts"</string>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index c00b7ed..6a2e79e 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Идэвхижсэн."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Унтраах"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Холбогдсон."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Блютүүт <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Байршил <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Сэрүүлгийг <xliff:g id="TIME">%s</xliff:g>-д тохируулсан."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Самбарыг хаах"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Цаг нэмэх"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Цаг хасах"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G дата идэвхгүй болов"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G дата идэвхгүй байна"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Мобайл дата идэвхгүй болов"</string>
@@ -213,9 +212,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Өөр тохиргоо"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Модем болгох"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Сүлжээний цэг"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"СҮҮЛИЙН"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Мэдэгдэл"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Сүүлд ашигласан апп байхгүй"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Сүлжээ хянагдаж\nбайж болзошгүй"</string>
@@ -234,10 +232,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Яаралтай биш мэдэгдлүүдийг доор"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Нээхийн тулд дахин товшино уу"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Таныг унтраах хүртэл"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Нэг минутын турш"</item>
+ <item quantity="other" msgid="6924190729213550991">"%d минутын турш"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Нэг цагийн турш"</item>
+ <item quantity="other" msgid="5408537517529822157">"%d цагийн турш"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 263fc46..7ae9b55 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Dihidupkan."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Dimatikan."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Disambungkan."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Lokasi <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Penggera ditetapkan pada <xliff:g id="TIME">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Tutup panel"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Lagi masa"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Kurang masa"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data 2G-3G dilumpuhkan"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data 4G dilumpuhkan"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Data mudah alih dilumpuhkan"</string>
@@ -213,9 +212,9 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Lagi tetapan"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Penambatan"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Tempat liputan"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Pemberitahuan"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
<skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"TERBAHARU"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rangkaian mungkin\nboleh dipantau"</string>
@@ -234,10 +233,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Pemberitahuan kurang penting di bawah"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Ketik lagi untuk membuka"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Sehingga anda matikan"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Selama satu minit"</item>
+ <item quantity="other" msgid="6924190729213550991">"Selama %d minit"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Selama satu jam"</item>
+ <item quantity="other" msgid="5408537517529822157">"Selama %d jam"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 75706a2..e842c0f 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"På."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Av."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Tilkoblet."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tilknytning"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Wi-Fi-sone"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Varsler"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"NYLIGE"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Ingen nylige apper"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nettverket kan\nvære overvåket"</string>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index c4bef68..360b71d 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Ingeschakeld."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Uitgeschakeld."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Verbonden."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Meldingen"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"RECENTE"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Geen recente apps"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk kan\nworden gecontroleerd"</string>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 825dfec..25098d8 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Wł."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Wył."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Połączono."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Powiązanie"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Punkt dostępu"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Powiadomienia"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"OSTATNIE"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Brak ostatnio uruchomionych aplikacji"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieć może być\nmonitorowana"</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index f9ac828..34adc46 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Ativado."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Desativado."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Ligado."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Associação"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Zona Wi-Fi"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"RECENTES"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Nenhuma aplicação recente"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode ser\nmonitorizada"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 1c13e62..e3b1f84 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Ligado."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Desligado."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectado."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Localização <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Fechar painel"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Mais tempo"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Menos tempo"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dados 2G e 3G desativados"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dados 4G desativados"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Dados móveis desativados"</string>
@@ -215,9 +214,9 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mais configurações"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Ponto de acesso"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificações"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
<skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"RECENTES"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do aplicativo"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode estar\nsob monitoração"</string>
@@ -236,10 +235,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificações menos urgentes abaixo"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Até você desativar"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Por 1 minuto"</item>
+ <item quantity="other" msgid="6924190729213550991">"Por %d minutos"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Por 1 hora"</item>
+ <item quantity="other" msgid="5408537517529822157">"Por %d horas"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 00bf8c0..e6a3872 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -210,6 +210,8 @@
<skip />
<!-- no translation found for accessibility_desc_connected (8366256693719499665) -->
<skip />
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<!-- no translation found for accessibility_data_connection_gprs (1606477224486747751) -->
<skip />
<!-- no translation found for accessibility_data_connection_1x (994133468120244018) -->
@@ -392,7 +394,7 @@
<skip />
<!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
<skip />
- <!-- no translation found for recents_empty_message (2269156590813544104) -->
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
<skip />
<!-- no translation found for recents_app_info_button_label (2890317189376000030) -->
<skip />
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 7ffa77c..9bc9178 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Activat."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Dezactivat."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Conectat."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Locație: <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarmă setată pentru <xliff:g id="TIME">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Închideți panoul"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Mai mult timp"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Mai puțin timp"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Datele 2G-3G au fost dezactivate"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Datele 4G au fost dezactivate"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Datele mobile au fost dezactivate"</string>
@@ -213,9 +212,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mai multe setări"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"RECENTE"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Notificări"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Nicio aplicație recentă"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rețeaua poate\nfi monitorizată"</string>
@@ -234,10 +232,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Notificările mai puțin urgente mai jos"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Atingeți din nou pentru a deschide"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Până la dezactivare"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Timp de un minut"</item>
+ <item quantity="other" msgid="6924190729213550991">"Timp de %d (de) minute"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Timp de o oră"</item>
+ <item quantity="other" msgid="5408537517529822157">"Timp de %d (de) ore"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index d726428..619ebc2 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Вкл."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Выкл."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Подключено"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступа"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Уведомления"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"НЕДАВНИЕ СООБЩЕНИЯ"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Ничего не найдено."</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Действия в сети\nмогут отслеживаться"</string>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index 8debc9a..df880cf 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Zapnuté."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Vypnuté."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Pripojené."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth: <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Poloha: <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Budík nastavený na <xliff:g id="TIME">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Zavrieť panel"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Dlhší čas"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Kratší čas"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Dátové prenosy 2G a 3G sú zakázané"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Dátové prenosy 4G sú zakázané"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobilné dátové prenosy sú zakázané"</string>
@@ -215,9 +214,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Ďalšie nastavenia"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Zdieľanie dátového pripojenia"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"NEDÁVNE"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Upozornenia"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Žiadne nedávne aplikácie"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieť môže byť\nmonitorovaná"</string>
@@ -236,10 +234,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Menej naliehavé upozornenia sa nachádzajú nižšie"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Upozornenie otvoríte opätovným klepnutím"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Zariadenie odomknete prejdením prstom nahor"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Dokým túto funkciu nevypnete"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Na jednu minútu"</item>
+ <item quantity="other" msgid="6924190729213550991">"Na %d min"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Na jednu hodinu"</item>
+ <item quantity="other" msgid="5408537517529822157">"Na %d h"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 6171c16..d1170bd 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Vklopljen."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Izklopljen."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Povezan."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internet prek mobilne naprave"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Dostopna točka"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Obvestila"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"NEDAVNI"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Ni nedavnih aplikacij"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Omrežje je\nlahko spremljano"</string>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 14782e6..cfb6a2c 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Укључено."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Искључено."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Повезано је."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Повезивање"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Хотспот"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Обавештења"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"НАЈНОВИЈЕ"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Нема недавних апликација"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежа се можда\nнадгледа"</string>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index a7fb15d..4e3d72f 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Aktiverad."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Inaktiverad."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Ansluten."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,8 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Internetdelning"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Trådlös surfzon"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Aviseringar"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"NYA"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
+ <skip />
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nätverket kan\nvara övervakat"</string>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index b8d8c58..9bab46e 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -118,6 +118,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Imewashwa."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Imezimwa."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Imeunganishwa."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -154,12 +156,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Mahali <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Kengele imewekwa <xliff:g id="TIME">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Funga paneli ya maelezo"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Muda zaidi"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Muda kidogo"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Data ya 2G-3G imelemazwa"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Data ya 4G imelemazwa"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Data ya kifaa cha mkononi imelemazwa"</string>
@@ -211,9 +210,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Mipangilio zaidi"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Kusambaza mtandao"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Mtandao-hewa"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"YA HIVI KARIBUNI"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Arifa"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Hakuna programu za karibuni"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Huenda mtandao\nunafuatiliwa"</string>
@@ -232,10 +230,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Arifa zisizo za dharura sana ziko hapo chini"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Gonga tena ili ufungue"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Telezesha kidole ili ufungue"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Hadi utakapozima hili"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Kwa dakika moja"</item>
+ <item quantity="other" msgid="6924190729213550991">"Kwa dakika %d"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Kwa saa moja"</item>
+ <item quantity="other" msgid="5408537517529822157">"Kwa saa %d"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index dc75e78..4820071 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"เปิดอยู่"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"ปิดอยู่"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"เชื่อมต่อแล้ว"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"บลูทูธ <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"สถานที่ <xliff:g id="STATE">%s</xliff:g>"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"ตั้งเวลาปลุกไว้ที่ <xliff:g id="TIME">%s</xliff:g>"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"ปิดแผงควบคุม"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"เวลามากขึ้น"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"เวลาน้อยลง"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"ปิดใช้งานข้อมูล 2G-3G แล้ว"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"ปิดใช้งานข้อมูล 4G แล้ว"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"ปิดใช้งานข้อมูลมือถือแล้ว"</string>
@@ -213,9 +212,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"การตั้งค่าเพิ่มเติม"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"การปล่อยสัญญาณ"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"ฮอตสปอต"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"ล่าสุด"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"การแจ้งเตือน"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"ไม่มีแอปล่าสุด"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"เครือข่ายอาจ\nถูกตรวจสอบ"</string>
@@ -234,10 +232,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"การแจ้งเตือนที่เร่งด่วนน้อยด้านล่าง"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"แตะอีกครั้งเพื่อเปิด"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"กวาดขึ้นเพื่อปลดล็อก"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"จนกว่าคุณจะปิดฟังก์ชันนี้"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"1 นาที"</item>
+ <item quantity="other" msgid="6924190729213550991">"%d นาที"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"1 ชั่วโมง"</item>
+ <item quantity="other" msgid="5408537517529822157">"%d ชั่วโมง"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index 0713ddd..6c6af51 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Naka-on."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Naka-off."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Nakakonekta."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"<xliff:g id="STATE">%s</xliff:g> ng Bluetooth."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Lokasyon <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm set para sa <xliff:g id="TIME">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Isara ang panel"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Higit pang oras"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Mas kaunting oras"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"Di pinapagana ang 2G-3G na data"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"Hindi pinapagana ang 4G na data"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Hindi pinapagana ang data ng mobile"</string>
@@ -213,9 +212,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Marami pang setting"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Nagte-tether"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"MGA KAMAKAILAN"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Mga Notification"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Walang kamakailang mga app"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Impormasyon ng Application"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Maaaring\nsinusubaybayan ang network"</string>
@@ -234,10 +232,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Nasa ibaba ang mga notification na hindi masyadong mahalaga"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"I-tap ulit upang buksan"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Mag-swipe pataas upang i-unlock"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Hanggang sa i-off mo ito"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Sa loob ng isang minuto"</item>
+ <item quantity="other" msgid="6924190729213550991">"Sa loob ng %d (na) minuto"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Sa loob ng isang oras"</item>
+ <item quantity="other" msgid="5408537517529822157">"Sa loob ng %d (na) oras"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index c0ba250..85ba8fe 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Açık."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Kapalı."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Bağlandı."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -156,12 +158,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"Bluetooth <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"Konum: <xliff:g id="STATE">%s</xliff:g>."</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarm saati: <xliff:g id="TIME">%s</xliff:g>."</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"Paneli kapatın"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"Daha uzun süre"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"Daha kısa süre"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G verileri devre dışı bırakıldı"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G verileri devre dışı"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"Mobil veriler devre dışı"</string>
@@ -213,9 +212,9 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"Diğer ayarlar"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Tethering"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Hotspot"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"Bildirimler"</string>
+ <!-- no translation found for recents_empty_message (7883614615463619450) -->
<skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"SON İLETİLER"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ağ izleniyor\nolabilir"</string>
@@ -234,10 +233,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"Daha az acil bildirimler aşağıdadır"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"Açmak için tekrar hafifçe vurun"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"Kilidi açmak için hızlıca yukarı kaydırın"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"Siz bunu kapatana kadar"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"Bir dakika süreyle"</item>
+ <item quantity="other" msgid="6924190729213550991">"%d dakika süreyle"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"Bir saat süreyle"</item>
+ <item quantity="other" msgid="5408537517529822157">"%d saat süreyle"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index e149d7b..7f66e72 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Увімкнено."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Вимкнено."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Під’єднано."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Режим модема"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Точка доступу"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Сповіщення"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"ОСТАННІ"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Немає останніх додатків"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мережа може\nвідстежуватися"</string>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index f99c341..3ddea96 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Bật."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Tắt."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Đã kết nối."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Đang dùng làm điểm truy cập Internet"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"Điểm phát sóng"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Thông báo"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"GẦN ĐÂY"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Không có ứng dụng nào gần đây"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mạng có thể\nđược giám sát"</string>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 6940b2c..934ac8c 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"开启。"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"关闭。"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"已连接。"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -158,12 +160,9 @@
<string name="accessibility_quick_settings_bluetooth" msgid="5749054971341882340">"蓝牙:<xliff:g id="STATE">%s</xliff:g>。"</string>
<string name="accessibility_quick_settings_location" msgid="4577282329866813100">"位置信息服务<xliff:g id="STATE">%s</xliff:g>。"</string>
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"闹钟已设置为:<xliff:g id="TIME">%s</xliff:g>。"</string>
- <!-- no translation found for accessibility_quick_settings_close (2571790856136835943) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_more_time (5778794273488176726) -->
- <skip />
- <!-- no translation found for accessibility_quick_settings_less_time (101026945195230084) -->
- <skip />
+ <string name="accessibility_quick_settings_close" msgid="2571790856136835943">"关闭面板"</string>
+ <string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"更长时间"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"更短时间"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"2G-3G 数据网络已停用"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"4G 数据网络已停用"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"移动数据网络已停用"</string>
@@ -215,9 +214,8 @@
<string name="quick_settings_more_settings" msgid="326112621462813682">"更多设置"</string>
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"网络共享"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"热点"</string>
- <!-- no translation found for quick_settings_notifications_label (4818156442169154523) -->
- <skip />
- <string name="recents_empty_message" msgid="2269156590813544104">"最近"</string>
+ <string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"最近没有用过任何应用"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"网络可能会\n受到监控"</string>
@@ -236,10 +234,13 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太紧急的通知会显示在下方"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次点按即可打开"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上滑动即可解锁"</string>
- <!-- no translation found for zen_mode_forever (7420011936770086993) -->
- <skip />
- <!-- no translation found for zen_mode_duration_minutes:one (9040808414992812341) -->
- <!-- no translation found for zen_mode_duration_minutes:other (6924190729213550991) -->
- <!-- no translation found for zen_mode_duration_hours:one (3480040795582254384) -->
- <!-- no translation found for zen_mode_duration_hours:other (5408537517529822157) -->
+ <string name="zen_mode_forever" msgid="7420011936770086993">"直到您将其关闭"</string>
+ <plurals name="zen_mode_duration_minutes">
+ <item quantity="one" msgid="9040808414992812341">"1分钟"</item>
+ <item quantity="other" msgid="6924190729213550991">"%d分钟"</item>
+ </plurals>
+ <plurals name="zen_mode_duration_hours">
+ <item quantity="one" msgid="3480040795582254384">"1小时"</item>
+ <item quantity="other" msgid="5408537517529822157">"%d小时"</item>
+ </plurals>
</resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 04c00f5..40b56fe 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"開啟。"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"關閉。"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"已連線。"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -160,7 +162,7 @@
<string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"鬧鐘已設定為:<xliff:g id="TIME">%s</xliff:g>。"</string>
<string name="accessibility_quick_settings_close" msgid="2571790856136835943">"關閉面板"</string>
<string name="accessibility_quick_settings_more_time" msgid="5778794273488176726">"更多時間"</string>
- <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"更少時間"</string>
+ <string name="accessibility_quick_settings_less_time" msgid="101026945195230084">"較少時間"</string>
<string name="data_usage_disabled_dialog_3g_title" msgid="5257833881698644687">"已停用 2G-3G 數據"</string>
<string name="data_usage_disabled_dialog_4g_title" msgid="4789143363492682629">"已停用 4G 數據"</string>
<string name="data_usage_disabled_dialog_mobile_title" msgid="1046047248844821202">"已停用流動數據"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"熱點"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"近期"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資料"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網絡可能會\n受到監控"</string>
@@ -232,7 +234,7 @@
<string name="speed_bump_explanation" msgid="1288875699658819755">"不太緊急的通知會在下方顯示"</string>
<string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
<string name="keyguard_unlock" msgid="8043466894212841998">"向上快速滑動即可解鎖"</string>
- <string name="zen_mode_forever" msgid="7420011936770086993">"手動關閉這項設定前一律啟用"</string>
+ <string name="zen_mode_forever" msgid="7420011936770086993">"直至您關閉這項設定"</string>
<plurals name="zen_mode_duration_minutes">
<item quantity="one" msgid="9040808414992812341">"1 分鐘"</item>
<item quantity="other" msgid="6924190729213550991">"%d 分鐘"</item>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 4ffb01b..c1a48c4 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"開啟。"</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"關閉。"</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"已連線。"</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"HSPA"</string>
@@ -213,7 +215,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"網路共用"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"無線基地台"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"通知"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"近期"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"沒有最近使用的應用程式"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資訊"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網路可能\n受到監控"</string>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 4c44972..af49a7f 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -120,6 +120,8 @@
<string name="accessibility_desc_on" msgid="2385254693624345265">"Vula."</string>
<string name="accessibility_desc_off" msgid="6475508157786853157">"Vala."</string>
<string name="accessibility_desc_connected" msgid="8366256693719499665">"Ixhunyiwe."</string>
+ <!-- no translation found for accessibility_desc_connecting (3812924520316280149) -->
+ <skip />
<string name="accessibility_data_connection_gprs" msgid="1606477224486747751">"GPRS"</string>
<string name="accessibility_data_connection_1x" msgid="994133468120244018">"1 X"</string>
<string name="accessibility_data_connection_hspa" msgid="2032328855462645198">"I-HSPA"</string>
@@ -211,7 +213,7 @@
<string name="quick_settings_tethering_label" msgid="7153452060448575549">"Ukusebenzisa njengemodemu"</string>
<string name="quick_settings_hotspot_label" msgid="6046917934974004879">"I-Hotspot"</string>
<string name="quick_settings_notifications_label" msgid="4818156442169154523">"Izaziso"</string>
- <string name="recents_empty_message" msgid="2269156590813544104">"OKWAKAMUVA"</string>
+ <string name="recents_empty_message" msgid="7883614615463619450">"Azikho izinhlelo zokusebenza zakamuva"</string>
<string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string>
<string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
<string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Kungenzeka inethiwekhi\niqashiwe"</string>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 757d4ad..34cfbe8 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -46,7 +46,7 @@
<drawable name="notification_item_background_color_pressed">#ff454545</drawable>
<!-- Tint color for the content on the notification overflow card. -->
- <color name="keyguard_overflow_content_color">#ff666666</color>
+ <color name="keyguard_overflow_content_color">#ff686868</color>
<!-- The color of the red speed bump dot -->
<color name="speed_bump_dot_red">#ffd50000</color>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 0184df2..79a1df4 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -113,17 +113,20 @@
<!-- The min animation duration for animating views that are newly visible. -->
<integer name="recents_filter_animate_new_views_min_duration">125</integer>
<!-- The min animation duration for animating the task bar in. -->
- <integer name="recents_animate_task_bar_enter_duration">300</integer>
+ <integer name="recents_animate_task_bar_enter_duration">250</integer>
+ <!-- The animation delay for animating the first task in. This should roughly be the animation
+ duration of the transition in to recents. -->
+ <integer name="recents_animate_task_bar_enter_delay">225</integer>
<!-- The min animation duration for animating the task bar out. -->
- <integer name="recents_animate_task_bar_exit_duration">150</integer>
- <!-- The animation duration for animating in the info pane. -->
- <integer name="recents_animate_task_view_info_pane_duration">150</integer>
+ <integer name="recents_animate_task_bar_exit_duration">125</integer>
+ <!-- The min animation duration for animating the nav bar scrim in. -->
+ <integer name="recents_nav_bar_scrim_enter_duration">400</integer>
<!-- The animation duration for animating the removal of a task view. -->
<integer name="recents_animate_task_view_remove_duration">250</integer>
<!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
<integer name="recents_max_task_stack_view_dim">96</integer>
- <!-- Transposes the search bar layout in landscape -->
- <bool name="recents_transpose_search_layout_with_orientation">true</bool>
+ <!-- Transposes the recents layout in landscape. -->
+ <bool name="recents_transpose_layout_with_orientation">true</bool>
<!-- Whether to enable KeyguardService or not -->
<bool name="config_enableKeyguardService">true</bool>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index bfbdcf3..35bc7e3 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -83,7 +83,7 @@
<dimen name="notification_mid_height">128dp</dimen>
<!-- Height of a the summary ("more card") notification on keyguard. -->
- <dimen name="notification_summary_height">40dp</dimen>
+ <dimen name="notification_summary_height">44dp</dimen>
<!-- size at which Notification icons will be drawn in the status bar -->
<dimen name="status_bar_icon_drawing_size">18dip</dimen>
@@ -272,6 +272,9 @@
<!-- The padding between the individual notification cards. -->
<dimen name="notification_padding">4dp</dimen>
+ <!-- The minimum amount of top overscroll to go to the quick settings. -->
+ <dimen name="min_top_overscroll_to_qs">36dp</dimen>
+
<!-- The height of the collapsed speed bump view. -->
<dimen name="speed_bump_height_collapsed">24dp</dimen>
@@ -319,6 +322,20 @@
<!-- Volume panel z depth -->
<dimen name="volume_panel_z">3dp</dimen>
- <!-- Move distance for the hint animations on the lockscreen (unlock, phone, camera)-->
+ <!-- Distance between notifications and header when they are considered to be colliding. -->
+ <dimen name="header_notifications_collide_distance">24dp</dimen>
+
+ <!-- Distance the user needs to drag vertically such that a swipe is accepted to unlock the
+ device. -->
+ <dimen name="unlock_move_distance">75dp</dimen>
+
+ <!-- Move distance for the unlock hint animation on the lockscreen -->
<dimen name="hint_move_distance">75dp</dimen>
+
+ <!-- Move distance for the other hint animations on the lockscreen (phone, camera)-->
+ <dimen name="hint_move_distance_sideways">60dp</dimen>
+
+ <!-- The width of the region on the left/right edge of the screen for performing the camera/
+ phone hints. -->
+ <dimen name="edge_tap_area_width">48dp</dimen>
</resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 373f11f..de297e5 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -471,13 +471,13 @@
<!-- QuickSettings: Brightness [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_label">Brightness</string>
<!-- QuickSettings: Rotation Unlocked [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rotation_unlocked_label">Auto Rotate</string>
+ <string name="quick_settings_rotation_unlocked_label">Auto-rotate</string>
<!-- QuickSettings: Rotation Locked [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rotation_locked_label">Rotation Locked</string>
+ <string name="quick_settings_rotation_locked_label">Rotation locked</string>
<!-- QuickSettings: Locked to Portrait [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rotation_locked_portrait_label">Locked to Portrait</string>
+ <string name="quick_settings_rotation_locked_portrait_label">Portrait</string>
<!-- QuickSettings: Locked to Landscape [CHAR LIMIT=NONE] -->
- <string name="quick_settings_rotation_locked_landscape_label">Locked to Landscape</string>
+ <string name="quick_settings_rotation_locked_landscape_label">Landscape</string>
<!-- QuickSettings: IME [CHAR LIMIT=NONE] -->
<string name="quick_settings_ime_label">Input Method</string>
<!-- QuickSettings: Location [CHAR LIMIT=NONE] -->
@@ -505,7 +505,7 @@
<!-- QuickSettings: Wifi (Off) [CHAR LIMIT=NONE] -->
<string name="quick_settings_wifi_off_label">Wi-Fi Off</string>
<!-- QuickSettings: Remote display [CHAR LIMIT=NONE] -->
- <string name="quick_settings_remote_display_no_connection_label">Cast Screen</string>
+ <string name="quick_settings_remote_display_no_connection_label">Cast screen</string>
<!-- QuickSettings: Brightness dialog title [CHAR LIMIT=NONE] -->
<string name="quick_settings_brightness_dialog_title">Brightness</string>
<!-- QuickSettings: Brightness dialog auto brightness button [CHAR LIMIT=NONE] -->
@@ -558,10 +558,8 @@
<!-- Zen mode: Short title. [CHAR LIMIT=40] -->
<string name="zen_mode_title">Do not disturb</string>
- <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=12] -->
- <plurals name="keyguard_more_overflow_text">
- <item quantity="other">%d more</item>
- </plurals>
+ <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=1] -->
+ <string name="keyguard_more_overflow_text">+<xliff:g id="number_of_notifications" example="5">%d</xliff:g></string>
<!-- An explanation for the visual speed bump in the notifications, which will appear when you click on it. [CHAR LIMIT=50] -->
<string name="speed_bump_explanation">Less urgent notifications below</string>
@@ -572,11 +570,20 @@
<!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
<string name="keyguard_unlock">Swipe up to unlock</string>
+ <!-- Shows when people have clicked at the left edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
+ <string name="phone_hint">Swipe right for phone</string>
+
+ <!-- Shows when people have clicked at the right edge of the screen to explain how to open the phone. In right-to-left languages, this is the opposite direction. [CHAR LIMIT=60] -->
+ <string name="camera_hint">Swipe left for camera</string>
+
<string name="bugreport_tile_extended" translatable="false">%s\n%s (%s)</string>
<!-- Zen mode condition: no exit criteria. [CHAR LIMIT=NONE] -->
<string name="zen_mode_forever">Until you turn this off</string>
+ <!-- Indication on the keyguard that is shown when the device is charging. [CHAR LIMIT=40]-->
+ <string name="keyguard_indication_charging_time">Charging (<xliff:g id="charging_time_left" example="4 hours and 2 minutes">%s</xliff:g> until full)</string>
+
<!-- Zen mode condition: time duration in minutes. [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_duration_minutes">
<item quantity="one">For one minute</item>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 6a12232..4c269a2 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -197,6 +197,7 @@
<style name="systemui_theme" parent="@android:style/Theme.DeviceDefault">
<item name="android:colorPrimary">@color/primary_color</item>
+ <item name="android:colorControlActivated">@color/system_accent_color</item>
</style>
<style name="NotificationsQuickSettings">
@@ -213,11 +214,6 @@
<item name="android:colorControlActivated">#ffffffff</item>
</style>
- <style name="QSAccentTheme" parent="@android:style/Theme.DeviceDefault">
- <item name="android:colorControlNormal">@color/system_accent_color</item>
- <item name="android:colorControlActivated">@color/system_accent_color</item>
- </style>
-
<style name="BorderlessButton" parent="@android:style/Widget.Quantum.Button.Borderless" />
<style name="BorderlessButton.Tiny">
diff --git a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
index 4147155..14392b4 100644
--- a/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
+++ b/packages/SystemUI/src/com/android/systemui/DessertCaseView.java
@@ -507,7 +507,6 @@ public class DessertCaseView extends FrameLayout {
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
- | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
);
}
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 4d6d815..006619b 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -42,6 +42,7 @@ public class ExpandHelper implements Gefingerpoken {
boolean canChildBeExpanded(View v);
void setUserExpandedChild(View v, boolean userExpanded);
void setUserLockedChild(View v, boolean userLocked);
+ void expansionStateChanged(boolean isExpanding);
}
private static final String TAG = "ExpandHelper";
@@ -77,7 +78,6 @@ public class ExpandHelper implements Gefingerpoken {
private boolean mWatchingForPull;
private boolean mHasPopped;
private View mEventSource;
- private View mCurrView;
private float mOldHeight;
private float mNaturalHeight;
private float mInitialTouchFocusY;
@@ -86,8 +86,7 @@ public class ExpandHelper implements Gefingerpoken {
private float mLastFocusY;
private float mLastSpanY;
private int mTouchSlop;
- private int mLastMotionY;
- private float mPopLimit;
+ private float mLastMotionY;
private int mPopDuration;
private float mPullGestureMinXSpan;
private Callback mCallback;
@@ -95,10 +94,14 @@ public class ExpandHelper implements Gefingerpoken {
private ViewScaler mScaler;
private ObjectAnimator mScaleAnimation;
private Vibrator mVibrator;
+ private boolean mEnabled = true;
+ private ExpandableView mResizedView;
+ private float mCurrentHeight;
private int mSmallSize;
private int mLargeSize;
private float mMaximumStretch;
+ private boolean mOnlyMovements;
private int mGravity;
@@ -109,17 +112,14 @@ public class ExpandHelper implements Gefingerpoken {
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
if (DEBUG_SCALE) Log.v(TAG, "onscalebegin()");
- float focusX = detector.getFocusX();
- float focusY = detector.getFocusY();
- final ExpandableView underFocus = findView(focusX, focusY);
- startExpanding(underFocus, STRETCH);
+ startExpanding(mResizedView, STRETCH);
return mExpanding;
}
@Override
public boolean onScale(ScaleGestureDetector detector) {
- if (DEBUG_SCALE) Log.v(TAG, "onscale() on " + mCurrView);
+ if (DEBUG_SCALE) Log.v(TAG, "onscale() on " + mResizedView);
return true;
}
@@ -138,6 +138,7 @@ public class ExpandHelper implements Gefingerpoken {
public void setHeight(float h) {
if (DEBUG_SCALE) Log.v(TAG, "SetHeight: setting to " + h);
mView.setActualHeight((int) h);
+ mCurrentHeight = h;
}
public float getHeight() {
return mView.getActualHeight();
@@ -165,7 +166,6 @@ public class ExpandHelper implements Gefingerpoken {
mGravity = Gravity.TOP;
mScaleAnimation = ObjectAnimator.ofFloat(mScaler, "height", 0f);
mScaleAnimation.setDuration(EXPAND_DURATION);
- mPopLimit = mContext.getResources().getDimension(R.dimen.blinds_pop_threshold);
mPopDuration = mContext.getResources().getInteger(R.integer.blinds_pop_duration_ms);
mPullGestureMinXSpan = mContext.getResources().getDimension(R.dimen.pull_span_min);
@@ -188,7 +188,6 @@ public class ExpandHelper implements Gefingerpoken {
float target = hand + mOldHeight;
float newHeight = clamp(target);
mScaler.setHeight(newHeight);
-
mLastFocusY = mSGD.getFocusY();
mLastSpanY = mSGD.getCurrentSpan();
}
@@ -252,6 +251,9 @@ public class ExpandHelper implements Gefingerpoken {
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ if (!isEnabled()) {
+ return false;
+ }
final int action = ev.getAction();
if (DEBUG_SCALE) Log.d(TAG, "intercept: act=" + MotionEvent.actionToString(action) +
" expanding=" + mExpanding +
@@ -270,38 +272,34 @@ public class ExpandHelper implements Gefingerpoken {
if (DEBUG_SCALE) Log.d(TAG, "set initial span: " + mInitialTouchSpan);
if (mExpanding) {
+ mLastMotionY = ev.getRawY();
return true;
} else {
if ((action == MotionEvent.ACTION_MOVE) && 0 != (mExpansionStyle & BLINDS)) {
// we've begun Venetian blinds style expansion
return true;
}
- final float xspan = mSGD.getCurrentSpanX();
- if ((action == MotionEvent.ACTION_MOVE &&
- xspan > mPullGestureMinXSpan &&
- xspan > mSGD.getCurrentSpanY())) {
- // detect a vertical pulling gesture with fingers somewhat separated
- if (DEBUG_SCALE) Log.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
-
- final ExpandableView underFocus = findView(x, y);
- startExpanding(underFocus, PULL);
- return true;
- }
- if (mScrollAdapter != null && !mScrollAdapter.isScrolledToTop()) {
- return false;
- }
- // Now look for other gestures
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: {
+ final float xspan = mSGD.getCurrentSpanX();
+ if (xspan > mPullGestureMinXSpan &&
+ xspan > mSGD.getCurrentSpanY() && !mExpanding) {
+ // detect a vertical pulling gesture with fingers somewhat separated
+ if (DEBUG_SCALE) Log.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
+ startExpanding(mResizedView, PULL);
+ mWatchingForPull = false;
+ }
if (mWatchingForPull) {
- final int yDiff = y - mLastMotionY;
+ final float yDiff = ev.getRawY() - mInitialTouchY;
if (yDiff > mTouchSlop) {
if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
- mLastMotionY = y;
- final ExpandableView underFocus = findView(x, y);
- if (startExpanding(underFocus, BLINDS)) {
- mInitialTouchY = mLastMotionY;
- mHasPopped = false;
+ mWatchingForPull = false;
+ if (mResizedView != null && !isFullyExpanded(mResizedView)) {
+ if (startExpanding(mResizedView, BLINDS)) {
+ mLastMotionY = ev.getRawY();
+ mInitialTouchY = ev.getRawY();
+ mHasPopped = false;
+ }
}
}
}
@@ -310,8 +308,10 @@ public class ExpandHelper implements Gefingerpoken {
case MotionEvent.ACTION_DOWN:
mWatchingForPull = mScrollAdapter != null &&
- isInside(mScrollAdapter.getHostView(), x, y);
- mLastMotionY = y;
+ isInside(mScrollAdapter.getHostView(), x, y)
+ && mScrollAdapter.isScrolledToTop();
+ mResizedView = findView(x, y);
+ mInitialTouchY = ev.getY();
break;
case MotionEvent.ACTION_CANCEL:
@@ -321,12 +321,28 @@ public class ExpandHelper implements Gefingerpoken {
clearView();
break;
}
+ mLastMotionY = ev.getRawY();
return mExpanding;
}
}
+ public void setEnabled(boolean enable) {
+ mEnabled = enable;
+ }
+
+ private boolean isEnabled() {
+ return mEnabled;
+ }
+
+ private boolean isFullyExpanded(ExpandableView underFocus) {
+ return underFocus.getIntrinsicHeight() == underFocus.getMaxHeight();
+ }
+
@Override
public boolean onTouchEvent(MotionEvent ev) {
+ if (!isEnabled()) {
+ return false;
+ }
final int action = ev.getActionMasked();
if (DEBUG_SCALE) Log.d(TAG, "touch: act=" + MotionEvent.actionToString(action) +
" expanding=" + mExpanding +
@@ -335,47 +351,71 @@ public class ExpandHelper implements Gefingerpoken {
(0 != (mExpansionStyle & STRETCH) ? " (stretch)" : ""));
mSGD.onTouchEvent(ev);
+ final int x = (int) mSGD.getFocusX();
+ final int y = (int) mSGD.getFocusY();
+ if (mOnlyMovements) {
+ mLastMotionY = ev.getRawY();
+ return false;
+ }
switch (action) {
+ case MotionEvent.ACTION_DOWN:
+ mWatchingForPull = mScrollAdapter != null &&
+ isInside(mScrollAdapter.getHostView(), x, y);
+ mResizedView = findView(x, y);
+ mInitialTouchY = ev.getY();
+ break;
case MotionEvent.ACTION_MOVE: {
- if (0 != (mExpansionStyle & BLINDS)) {
- final float rawHeight = ev.getY() - mInitialTouchY + mOldHeight;
+ if (mWatchingForPull) {
+ final float yDiff = ev.getRawY() - mInitialTouchY;
+ if (yDiff > mTouchSlop) {
+ if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
+ mWatchingForPull = false;
+ if (mResizedView != null && !isFullyExpanded(mResizedView)) {
+ if (startExpanding(mResizedView, BLINDS)) {
+ mInitialTouchY = ev.getRawY();
+ mLastMotionY = ev.getRawY();
+ mHasPopped = false;
+ }
+ }
+ }
+ }
+ if (mExpanding && 0 != (mExpansionStyle & BLINDS)) {
+ final float rawHeight = ev.getRawY() - mLastMotionY + mCurrentHeight;
final float newHeight = clamp(rawHeight);
- final boolean wasClosed = (mOldHeight == mSmallSize);
boolean isFinished = false;
+ boolean expanded = false;
if (rawHeight > mNaturalHeight) {
isFinished = true;
+ expanded = true;
}
if (rawHeight < mSmallSize) {
isFinished = true;
+ expanded = false;
}
- final float pull = Math.abs(ev.getY() - mInitialTouchY);
- if (mHasPopped || pull > mPopLimit) {
- if (!mHasPopped) {
- vibrate(mPopDuration);
- mHasPopped = true;
- }
- }
-
- if (mHasPopped) {
- mScaler.setHeight(newHeight);
+ if (!mHasPopped) {
+ vibrate(mPopDuration);
+ mHasPopped = true;
}
- final int x = (int) mSGD.getFocusX();
- final int y = (int) mSGD.getFocusY();
- ExpandableView underFocus = findView(x, y);
- if (isFinished && underFocus != null && underFocus != mCurrView) {
- finishExpanding(false); // @@@ needed?
- startExpanding(underFocus, BLINDS);
- mInitialTouchY = y;
- mHasPopped = false;
+ mScaler.setHeight(newHeight);
+ mLastMotionY = ev.getRawY();
+ if (isFinished) {
+ mCallback.setUserExpandedChild(mResizedView, expanded);
+ mCallback.expansionStateChanged(false);
+ return false;
+ } else {
+ mCallback.expansionStateChanged(true);
}
return true;
}
if (mExpanding) {
+
+ // Gestural expansion is running
updateExpansion();
+ mLastMotionY = ev.getRawY();
return true;
}
@@ -396,7 +436,8 @@ public class ExpandHelper implements Gefingerpoken {
clearView();
break;
}
- return true;
+ mLastMotionY = ev.getRawY();
+ return mResizedView != null;
}
/**
@@ -407,15 +448,16 @@ public class ExpandHelper implements Gefingerpoken {
return false;
}
mExpansionStyle = expandType;
- if (mExpanding && v == mCurrView) {
+ if (mExpanding && v == mResizedView) {
return true;
}
mExpanding = true;
+ mCallback.expansionStateChanged(true);
if (DEBUG) Log.d(TAG, "scale type " + expandType + " beginning on view: " + v);
mCallback.setUserLockedChild(v, true);
- setView(v);
- mScaler.setView((ExpandableView) v);
+ mScaler.setView(v);
mOldHeight = mScaler.getHeight();
+ mCurrentHeight = mOldHeight;
if (mCallback.canChildBeExpanded(v)) {
if (DEBUG) Log.d(TAG, "working on an expandable child");
mNaturalHeight = mScaler.getNaturalHeight(mLargeSize);
@@ -425,14 +467,13 @@ public class ExpandHelper implements Gefingerpoken {
}
if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight +
" mNaturalHeight: " + mNaturalHeight);
- v.getParent().requestDisallowInterceptTouchEvent(true);
return true;
}
private void finishExpanding(boolean force) {
if (!mExpanding) return;
- if (DEBUG) Log.d(TAG, "scale in finishing on view: " + mCurrView);
+ if (DEBUG) Log.d(TAG, "scale in finishing on view: " + mResizedView);
float currentHeight = mScaler.getHeight();
float targetHeight = mSmallSize;
@@ -446,11 +487,12 @@ public class ExpandHelper implements Gefingerpoken {
if (mScaleAnimation.isRunning()) {
mScaleAnimation.cancel();
}
- mCallback.setUserExpandedChild(mCurrView, targetHeight == mNaturalHeight);
+ mCallback.setUserExpandedChild(mResizedView, targetHeight == mNaturalHeight);
+ mCallback.expansionStateChanged(false);
if (targetHeight != currentHeight) {
mScaleAnimation.setFloatValues(targetHeight);
mScaleAnimation.setupStartValues();
- final View scaledView = mCurrView;
+ final View scaledView = mResizedView;
mScaleAnimation.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -460,7 +502,7 @@ public class ExpandHelper implements Gefingerpoken {
});
mScaleAnimation.start();
} else {
- mCallback.setUserLockedChild(mCurrView, false);
+ mCallback.setUserLockedChild(mResizedView, false);
}
mExpanding = false;
@@ -470,16 +512,11 @@ public class ExpandHelper implements Gefingerpoken {
if (DEBUG) Log.d(TAG, "currentHeight is: " + currentHeight);
if (DEBUG) Log.d(TAG, "mSmallSize is: " + mSmallSize);
if (DEBUG) Log.d(TAG, "targetHeight is: " + targetHeight);
- if (DEBUG) Log.d(TAG, "scale was finished on view: " + mCurrView);
+ if (DEBUG) Log.d(TAG, "scale was finished on view: " + mResizedView);
}
private void clearView() {
- mCurrView = null;
-
- }
-
- private void setView(View v) {
- mCurrView = v;
+ mResizedView = null;
}
/**
@@ -494,6 +531,18 @@ public class ExpandHelper implements Gefingerpoken {
}
/**
+ * Change the expansion mode to only observe movements and don't perform any resizing.
+ * This is needed when the expanding is finished and the scroller kicks in,
+ * performing an overscroll motion. We only want to shrink it again when we are not
+ * overscrolled.
+ *
+ * @param onlyMovements Should only movements be observed?
+ */
+ public void onlyObserveMovements(boolean onlyMovements) {
+ mOnlyMovements = onlyMovements;
+ }
+
+ /**
* Triggers haptic feedback.
*/
private synchronized void vibrate(long duration) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index f7b4994..ffd76a7 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -59,8 +59,6 @@ import com.android.keyguard.KeyguardUpdateMonitor;
import com.android.keyguard.KeyguardUpdateMonitorCallback;
import com.android.keyguard.MultiUserAvatarCache;
import com.android.keyguard.ViewMediatorCallback;
-import com.android.keyguard.analytics.KeyguardAnalytics;
-import com.android.keyguard.analytics.Session;
import com.android.systemui.SystemUI;
import com.android.systemui.statusbar.phone.PhoneStatusBar;
import com.android.systemui.statusbar.phone.ScrimController;
@@ -70,7 +68,6 @@ import com.android.systemui.statusbar.phone.StatusBarWindowManager;
import java.io.File;
import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
/**
@@ -117,7 +114,6 @@ import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapte
public class KeyguardViewMediator extends SystemUI {
private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
final static boolean DEBUG = false;
- private static final boolean ENABLE_ANALYTICS = Build.IS_DEBUGGABLE;
private final static boolean DBG_WAKE = false;
private final static String TAG = "KeyguardViewMediator";
@@ -199,8 +195,6 @@ public class KeyguardViewMediator extends SystemUI {
private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
- private KeyguardAnalytics mKeyguardAnalytics;
-
// these are protected by synchronized (this)
/**
@@ -469,22 +463,6 @@ public class KeyguardViewMediator extends SystemUI {
mViewMediatorCallback, mLockPatternUtils);
final ContentResolver cr = mContext.getContentResolver();
- if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
- Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
- mKeyguardAnalytics = new KeyguardAnalytics(mContext, new SessionTypeAdapter() {
-
- @Override
- public int getSessionType() {
- return mLockPatternUtils.isSecure() && !mUpdateMonitor.getUserHasTrust(
- mLockPatternUtils.getCurrentUser())
- ? Session.TYPE_KEYGUARD_SECURE
- : Session.TYPE_KEYGUARD_INSECURE;
- }
- }, new File(mContext.getCacheDir(), "keyguard_analytics.bin"));
- } else {
- mKeyguardAnalytics = null;
- }
-
mScreenOn = mPM.isScreenOn();
mLockSounds = new SoundPool(1, AudioManager.STREAM_SYSTEM, 0);
@@ -585,9 +563,6 @@ public class KeyguardViewMediator extends SystemUI {
} else {
doKeyguardLocked(null);
}
- if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
- mKeyguardAnalytics.getCallback().onScreenOff();
- }
}
KeyguardUpdateMonitor.getInstance(mContext).dispatchScreenTurndOff(why);
}
@@ -830,9 +805,6 @@ public class KeyguardViewMediator extends SystemUI {
updateActivityLockScreenState();
adjustStatusBarLocked();
}
- if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
- mKeyguardAnalytics.getCallback().onSetOccluded(isOccluded);
- }
}
}
@@ -906,6 +878,7 @@ public class KeyguardViewMediator extends SystemUI {
if (mLockPatternUtils.checkVoldPassword()) {
if (DEBUG) Log.d(TAG, "Not showing lock screen since just decrypted");
// Without this, settings is not enabled until the lock screen first appears
+ mShowing = false;
hideLocked();
return;
}
@@ -1219,9 +1192,17 @@ public class KeyguardViewMediator extends SystemUI {
if (DEBUG) Log.d(TAG, "handleHide");
try {
- // Don't actually hide the Keyguard at the moment, wait for window manager until
- // it tells us it's safe to do so with startKeyguardExitAnimation.
- mWM.keyguardGoingAway();
+ if (mShowing) {
+
+ // Don't actually hide the Keyguard at the moment, wait for window manager until
+ // it tells us it's safe to do so with startKeyguardExitAnimation.
+ mWM.keyguardGoingAway();
+ } else {
+
+ // Don't try to rely on WindowManager - if Keyguard wasn't showing, window
+ // manager won't start the exit animation.
+ handleStartKeyguardExitAnimation(0, 0);
+ }
} catch (RemoteException e) {
Log.e(TAG, "Error while calling WindowManager", e);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 2bf369a..07ffd66 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -156,12 +156,14 @@ public class QSPanel extends ViewGroup {
AnimatorListener listener = null;
if (show) {
if (mDetailRecord != null) return;
- final View detail = r.tile.createDetailView(mContext, mDetail);
- if (detail == null) return;
+ if (r.detailView == null) {
+ r.detailView = r.tile.createDetailView(mContext, mDetail);
+ }
+ if (r.detailView == null) return;
mDetailRecord = r;
mDetail.removeAllViews();
mDetail.bringToFront();
- mDetail.addView(detail);
+ mDetail.addView(r.detailView);
} else {
if (mDetailRecord == null) return;
listener = mTeardownDetailWhenDone;
@@ -273,6 +275,7 @@ public class QSPanel extends ViewGroup {
private static final class TileRecord {
QSTile<?> tile;
QSTileView tileView;
+ View detailView;
int row;
int col;
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
index 2edd8d5..5388994 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSTileView.java
@@ -135,7 +135,7 @@ public class QSTileView extends ViewGroup {
}
private Drawable getTileBackground() {
- final int[] attrs = new int[] { android.R.attr.selectableItemBackground};
+ final int[] attrs = new int[] { android.R.attr.selectableItemBackgroundBorderless };
final TypedArray ta = mContext.obtainStyledAttributes(attrs);
final Drawable d = ta.getDrawable(0);
ta.recycle();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
index 7b6c544..901cc10 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/SignalTileView.java
@@ -18,6 +18,8 @@ package com.android.systemui.qs;
import android.animation.ValueAnimator;
import android.content.Context;
+import android.graphics.ColorFilter;
+import android.graphics.LightingColorFilter;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
@@ -29,6 +31,7 @@ import com.android.systemui.qs.QSTile.SignalState;
public final class SignalTileView extends QSTileView {
private static final long DEFAULT_DURATION = new ValueAnimator().getDuration();
private static final long SHORT_DURATION = DEFAULT_DURATION / 3;
+ private static final ColorFilter FILTER = new LightingColorFilter(0xffffffff, 0xff283034);
private FrameLayout mIconFrame;
private ImageView mSignal;
@@ -41,10 +44,12 @@ public final class SignalTileView extends QSTileView {
mIn = new ImageView(context);
mIn.setImageResource(R.drawable.ic_qs_signal_in);
+ mIn.setColorFilter(FILTER);
addView(mIn);
mOut = new ImageView(context);
mOut.setImageResource(R.drawable.ic_qs_signal_out);
+ mOut.setColorFilter(FILTER);
addView(mOut);
}
@@ -88,10 +93,12 @@ public final class SignalTileView extends QSTileView {
final SignalState s = (SignalState) state;
mSignal.setImageDrawable(null); // force refresh
mSignal.setImageResource(s.iconId);
+ mSignal.setColorFilter(FILTER);
if (s.overlayIconId > 0) {
mOverlay.setVisibility(VISIBLE);
mOverlay.setImageDrawable(null); // force refresh
mOverlay.setImageResource(s.overlayIconId);
+ mOverlay.setColorFilter(FILTER);
} else {
mOverlay.setVisibility(GONE);
}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
index d220e1a..20ed629 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/BluetoothTile.java
@@ -94,7 +94,7 @@ public class BluetoothTile extends QSTile<QSTile.BooleanState> {
}
} else {
state.iconId = R.drawable.ic_qs_bluetooth_off;
- state.label = mContext.getString(R.string.quick_settings_bluetooth_off_label);
+ state.label = mContext.getString(R.string.quick_settings_bluetooth_label);
stateContentDescription = mContext.getString(R.string.accessibility_desc_off);
}
state.contentDescription = mContext.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
index e496468..db9b054 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/LocationTile.java
@@ -85,7 +85,7 @@ public class LocationTile extends QSTile<QSTile.BooleanState> {
mContext.getString(R.string.accessibility_desc_on));
} else {
if (state.icon == null) state.iconId = R.drawable.ic_qs_location_11;
- state.label = mContext.getString(R.string.quick_settings_location_off_label);
+ state.label = mContext.getString(R.string.quick_settings_location_label);
state.contentDescription = mContext.getString(
R.string.accessibility_quick_settings_location,
mContext.getString(R.string.accessibility_desc_off));
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
index 20bbf8b..b981ed6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/NotificationsTile.java
@@ -22,7 +22,6 @@ import android.content.Intent;
import android.content.IntentFilter;
import android.media.AudioManager;
import android.util.Log;
-import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
@@ -49,8 +48,7 @@ public class NotificationsTile extends QSTile<NotificationsTile.NotificationsSta
@Override
public View createDetailView(Context context, ViewGroup root) {
- final Context themedContext = new ContextThemeWrapper(mContext, R.style.QSAccentTheme);
- final View v = LayoutInflater.from(themedContext).inflate(R.layout.qs_detail, root, false);
+ final View v = LayoutInflater.from(context).inflate(R.layout.qs_detail, root, false);
final TextView title = (TextView) v.findViewById(android.R.id.title);
title.setText(R.string.quick_settings_notifications_label);
final View close = v.findViewById(android.R.id.button1);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
index a1e70b9..6b73002 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/WifiTile.java
@@ -99,7 +99,7 @@ public class WifiTile extends QSTile<QSTile.SignalState> {
signalContentDescription = r.getString(R.string.accessibility_no_wifi);
} else {
state.iconId = R.drawable.ic_qs_wifi_no_network;
- state.label = r.getString(R.string.quick_settings_wifi_off_label);
+ state.label = r.getString(R.string.quick_settings_wifi_label);
signalContentDescription = r.getString(R.string.accessibility_wifi_off);
}
state.contentDescription = mContext.getString(
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index ca9bb94..bb19415 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -152,6 +152,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
// Recents service binding
Messenger mService = null;
Messenger mMessenger;
+ RecentsMessageHandler mHandler;
boolean mServiceIsBound = false;
boolean mToggleRecentsUponServiceBound;
RecentsServiceConnection mConnection = new RecentsServiceConnection();
@@ -168,7 +169,8 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
public AlternateRecentsComponent(Context context) {
mContext = context;
mSystemServicesProxy = new SystemServicesProxy(context);
- mMessenger = new Messenger(new RecentsMessageHandler());
+ mHandler = new RecentsMessageHandler();
+ mMessenger = new Messenger(mHandler);
}
public void onStart() {
@@ -507,7 +509,7 @@ public class AlternateRecentsComponent implements ActivityOptions.OnAnimationSta
if (!useThumbnailTransition) {
ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
R.anim.recents_from_launcher_enter,
- R.anim.recents_from_launcher_exit);
+ R.anim.recents_from_launcher_exit, mHandler, this);
startAlternateRecentsActivity(opts, false);
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index df387c1..8680786 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -26,11 +26,14 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Pair;
+import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import com.android.systemui.R;
@@ -67,6 +70,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
FrameLayout mContainerView;
RecentsView mRecentsView;
View mEmptyView;
+ View mNavBarScrimView;
AppWidgetHost mAppWidgetHost;
AppWidgetProviderInfo mSearchAppWidgetInfo;
@@ -99,7 +103,7 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
dismissRecentsIfVisible();
}
} else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) {
- // Try and start the enter animation
+ // Try and start the enter animation (or restart it on configuration changed)
mRecentsView.startOnEnterAnimation();
}
}
@@ -129,6 +133,9 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
mRecentsView.setBSP(root);
}
+ // Hide the scrim by default when we enter recents
+ mNavBarScrimView.setVisibility(View.INVISIBLE);
+
// Add the default no-recents layout
if (stacks.size() == 1 && stacks.get(0).getTaskCount() == 0) {
mEmptyView.setVisibility(View.VISIBLE);
@@ -269,10 +276,12 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
// Create the empty view
LayoutInflater inflater = LayoutInflater.from(this);
mEmptyView = inflater.inflate(R.layout.recents_empty, mContainerView, false);
+ mNavBarScrimView = inflater.inflate(R.layout.recents_nav_bar_scrim, mContainerView, false);
mContainerView = new FrameLayout(this);
mContainerView.addView(mRecentsView);
mContainerView.addView(mEmptyView);
+ mContainerView.addView(mNavBarScrimView);
setContentView(mContainerView);
// Update the recent tasks
@@ -282,6 +291,16 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
bindSearchBarAppWidget();
// Add the search bar layout
addSearchBarAppWidgetView();
+
+ // Update if we are getting a configuration change
+ if (savedInstanceState != null) {
+ onConfigurationChange();
+ }
+ }
+
+ void onConfigurationChange() {
+ // Try and start the enter animation (or restart it on configuration changed)
+ mRecentsView.startOnEnterAnimation();
}
@Override
@@ -433,17 +452,44 @@ public class RecentsActivity extends Activity implements RecentsView.RecentsView
@Override
public void onBackPressed() {
- boolean interceptedByInfoPanelClose = false;
-
// Unfilter any stacks
if (!mRecentsView.unfilterFilteredStacks()) {
- super.onBackPressed();
+ if (!mRecentsView.launchFirstTask()) {
+ super.onBackPressed();
+ }
}
}
@Override
- public void onTaskLaunching() {
+ public void onEnterAnimationTriggered() {
+ // Fade in the scrim
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ if (config.hasNavBarScrim()) {
+ mNavBarScrimView.setVisibility(View.VISIBLE);
+ mNavBarScrimView.setAlpha(0f);
+ mNavBarScrimView.animate().alpha(1f)
+ .setStartDelay(config.taskBarEnterAnimDelay)
+ .setDuration(config.navBarScrimEnterDuration)
+ .setInterpolator(config.fastOutSlowInInterpolator)
+ .withLayer()
+ .start();
+ }
+ }
+
+ @Override
+ public void onTaskLaunching(boolean isTaskInStackBounds) {
mTaskLaunched = true;
+
+ // Fade out the scrim
+ RecentsConfiguration config = RecentsConfiguration.getInstance();
+ if (!isTaskInStackBounds && config.hasNavBarScrim()) {
+ mNavBarScrimView.animate().alpha(0f)
+ .setStartDelay(0)
+ .setDuration(config.taskBarExitAnimDuration)
+ .setInterpolator(config.fastOutSlowInInterpolator)
+ .withLayer()
+ .start();
+ }
}
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 6391685..0cf6ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -41,7 +41,7 @@ public class RecentsConfiguration {
public Rect displayRect = new Rect();
boolean isLandscape;
- boolean transposeSearchLayoutWithOrientation;
+ boolean transposeRecentsLayoutWithOrientation;
int searchBarAppWidgetId = -1;
public float animationPxMovementPerSecond;
@@ -58,7 +58,6 @@ public class RecentsConfiguration {
public float taskStackWidthPaddingPct;
public int taskStackTopPaddingPx;
- public int taskViewInfoPaneAnimDuration;
public int taskViewRemoveAnimDuration;
public int taskViewRemoveAnimTranslationXPx;
public int taskViewTranslationZMinPx;
@@ -76,8 +75,11 @@ public class RecentsConfiguration {
public int taskBarViewHighlightColor;
public int taskBarEnterAnimDuration;
+ public int taskBarEnterAnimDelay;
public int taskBarExitAnimDuration;
+ public int navBarScrimEnterDuration;
+
public boolean launchedFromAltTab;
public boolean launchedWithThumbnailAnimation;
@@ -108,8 +110,8 @@ public class RecentsConfiguration {
isLandscape = res.getConfiguration().orientation ==
Configuration.ORIENTATION_LANDSCAPE;
- transposeSearchLayoutWithOrientation =
- res.getBoolean(R.bool.recents_transpose_search_layout_with_orientation);
+ transposeRecentsLayoutWithOrientation =
+ res.getBoolean(R.bool.recents_transpose_layout_with_orientation);
if (Console.Enabled) {
Console.log(Constants.Log.UI.MeasureAndLayout,
"[RecentsConfiguration|orientation]", isLandscape ? "Landscape" : "Portrait",
@@ -133,8 +135,6 @@ public class RecentsConfiguration {
taskStackWidthPaddingPct = widthPaddingPctValue.getFloat();
taskStackTopPaddingPx = res.getDimensionPixelSize(R.dimen.recents_stack_top_padding);
- taskViewInfoPaneAnimDuration =
- res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
taskViewRemoveAnimDuration =
res.getInteger(R.integer.recents_animate_task_view_remove_duration);
taskViewRemoveAnimTranslationXPx =
@@ -163,9 +163,14 @@ public class RecentsConfiguration {
taskBarEnterAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
+ taskBarEnterAnimDelay =
+ res.getInteger(R.integer.recents_animate_task_bar_enter_delay);
taskBarExitAnimDuration =
res.getInteger(R.integer.recents_animate_task_bar_exit_duration);
+ navBarScrimEnterDuration =
+ res.getInteger(R.integer.recents_nav_bar_scrim_enter_duration);
+
fastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
com.android.internal.R.interpolator.fast_out_slow_in);
fastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
@@ -203,11 +208,16 @@ public class RecentsConfiguration {
launchedWithThumbnailAnimation = false;
}
- /** Returns whether the search bar app widget exists */
+ /** Returns whether the search bar app widget exists. */
public boolean hasSearchBarAppWidget() {
return searchBarAppWidgetId >= 0;
}
+ /** Returns whether the nav bar scrim should be visible. */
+ public boolean hasNavBarScrim() {
+ return !transposeRecentsLayoutWithOrientation || !isLandscape;
+ }
+
/**
* Returns the task stack bounds in the current orientation. These bounds do not account for
* the system insets.
@@ -216,7 +226,7 @@ public class RecentsConfiguration {
if (hasSearchBarAppWidget()) {
Rect searchBarBounds = new Rect();
getSearchBarBounds(width, height, searchBarBounds);
- if (isLandscape && transposeSearchLayoutWithOrientation) {
+ if (isLandscape && transposeRecentsLayoutWithOrientation) {
// In landscape, the search bar appears on the left, so shift the task rect right
taskStackBounds.set(searchBarBounds.width(), 0, width, height);
} else {
@@ -239,7 +249,7 @@ public class RecentsConfiguration {
return;
}
- if (isLandscape && transposeSearchLayoutWithOrientation) {
+ if (isLandscape && transposeRecentsLayoutWithOrientation) {
// In landscape, the search bar appears on the left
searchBarSpaceBounds.set(0, 0, searchBarSpaceHeightPx, height);
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
index 4e620b6..8bcc7f5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsPackageMonitor.java
@@ -38,6 +38,7 @@ public class RecentsPackageMonitor extends PackageMonitor {
PackageCallbacks mCb;
List<ActivityManager.RecentTaskInfo> mTasks;
SystemServicesProxy mSsp;
+ boolean mRegistered;
public RecentsPackageMonitor(Context context) {
mSsp = new SystemServicesProxy(context);
@@ -46,13 +47,19 @@ public class RecentsPackageMonitor extends PackageMonitor {
/** Registers the broadcast receivers with the specified callbacks. */
public void register(Context context, PackageCallbacks cb) {
mCb = cb;
- register(context, Looper.getMainLooper(), false);
+ if (!mRegistered) {
+ register(context, Looper.getMainLooper(), false);
+ mRegistered = true;
+ }
}
/** Unregisters the broadcast receivers. */
@Override
public void unregister() {
- super.unregister();
+ if (mRegistered) {
+ super.unregister();
+ mRegistered = false;
+ }
mTasks.clear();
}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 6005275..db398b1 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -54,7 +54,8 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** The RecentsView callbacks */
public interface RecentsViewCallbacks {
- public void onTaskLaunching();
+ public void onTaskLaunching(boolean isTaskInStackBounds);
+ public void onEnterAnimationTriggered();
}
// The space partitioning root of this container
@@ -160,6 +161,9 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
/** Requests all task stacks to start their enter-recents animation */
public void startOnEnterAnimation() {
+ // Notify callbacks that we are starting the enter animation
+ mCb.onEnterAnimationTriggered();
+
int childCount = getChildCount();
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
@@ -351,7 +355,11 @@ public class RecentsView extends FrameLayout implements TaskStackView.TaskStackV
final TaskStack stack, final Task task) {
// Notify any callbacks of the launching of a new task
if (mCb != null) {
- mCb.onTaskLaunching();
+ boolean isTaskInStackBounds = false;
+ if (stackView != null && tv != null) {
+ isTaskInStackBounds = stackView.isTaskInStackBounds(tv);
+ }
+ mCb.onTaskLaunching(isTaskInStackBounds);
}
final Runnable launchRunnable = new Runnable() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 053f122..5830e37 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -430,6 +430,13 @@ public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCal
return getScrollAmountOutOfBounds(getStackScroll()) != 0;
}
+ /** Returns whether the task view is in the stack bounds or not */
+ boolean isTaskInStackBounds(TaskView tv) {
+ Rect r = new Rect();
+ tv.getHitRect(r);
+ return r.bottom <= mRect.bottom;
+ }
+
/** Updates the min and max virtual scroll bounds */
void updateMinMaxScroll(boolean boundScrollToNewMinMax) {
// Compute the min and max scroll values
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index ffa181d..632c816 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -234,7 +234,7 @@ public class TaskView extends FrameLayout implements Task.TaskCallbacks, View.On
mBarView.setTranslationY(-mBarView.getMeasuredHeight());
mBarView.animate()
.translationY(0)
- .setStartDelay(200)
+ .setStartDelay(config.taskBarEnterAnimDelay)
.setInterpolator(config.fastOutSlowInInterpolator)
.setDuration(config.taskBarEnterAnimDuration)
.withLayer()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedView.java
new file mode 100644
index 0000000..d2fe858
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedView.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.View;
+
+/**
+ * A View which does not have overlapping renderings commands and therefore does not need a
+ * layer when alpha is changed.
+ */
+public class AlphaOptimizedView extends View
+{
+ public AlphaOptimizedView(Context context) {
+ super(context);
+ }
+
+ public AlphaOptimizedView(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public AlphaOptimizedView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ }
+
+ public AlphaOptimizedView(Context context, AttributeSet attrs, int defStyleAttr,
+ int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ }
+
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
index 5b2ea0b..517a4e8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/DragDownHelper.java
@@ -25,7 +25,6 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
-
import com.android.systemui.ExpandHelper;
import com.android.systemui.Gefingerpoken;
import com.android.systemui.R;
@@ -87,6 +86,7 @@ public class DragDownHelper implements Gefingerpoken {
captureStartingChild(mInitialTouchX, mInitialTouchY);
mInitialTouchY = y;
mInitialTouchX = x;
+ mOnDragDownListener.onTouchSlopExceeded();
return true;
}
break;
@@ -202,5 +202,6 @@ public class DragDownHelper implements Gefingerpoken {
void onDraggedDown(View startingChild);
void onDragDownReset();
void onThresholdReached();
+ void onTouchSlopExceeded();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 088f076..ac2537c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -69,7 +69,9 @@ public abstract class ExpandableView extends FrameLayout {
? MeasureSpec.makeMeasureSpec(ownMaxHeight, MeasureSpec.EXACTLY)
: MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY);
}
- child.measure(widthMeasureSpec, childHeightSpec);
+ child.measure(
+ getChildMeasureSpec(widthMeasureSpec, 0 /* padding */, layoutParams.width),
+ childHeightSpec);
int childHeight = child.getMeasuredHeight();
maxChildHeight = Math.max(maxChildHeight, childHeight);
} else {
@@ -79,7 +81,9 @@ public abstract class ExpandableView extends FrameLayout {
int ownHeight = hasFixedHeight ? ownMaxHeight : maxChildHeight;
newHeightSpec = MeasureSpec.makeMeasureSpec(ownHeight, MeasureSpec.EXACTLY);
for (View child : mMatchParentViews) {
- child.measure(widthMeasureSpec, newHeightSpec);
+ child.measure(getChildMeasureSpec(
+ widthMeasureSpec, 0 /* padding */, child.getLayoutParams().width),
+ newHeightSpec);
}
mMatchParentViews.clear();
int width = MeasureSpec.getSize(widthMeasureSpec);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
index de27119..4233ab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
@@ -52,7 +52,7 @@ public class InterceptedNotifications {
for (int i = 0; i < n; i++) {
final StatusBarNotification sbn = mIntercepted.valueAt(i);
mReleased.add(sbn.getKey());
- mBar.addNotificationInternal(sbn, null);
+ mBar.displayNotification(sbn, null);
}
mIntercepted.clear();
updateSyntheticNotification();
@@ -71,16 +71,17 @@ public class InterceptedNotifications {
public void retryIntercepts(Ranking ranking) {
if (ranking == null) return;
- boolean changed = false;
final int N = mIntercepted.size();
+ final ArraySet<String> removed = new ArraySet<String>(N);
for (int i = 0; i < N; i++) {
final StatusBarNotification sbn = mIntercepted.valueAt(i);
if (!tryIntercept(sbn, ranking)) {
- changed = true;
- mBar.addNotificationInternal(sbn, ranking);
+ removed.add(sbn.getKey());
+ mBar.displayNotification(sbn, ranking);
}
}
- if (changed) {
+ if (!removed.isEmpty()) {
+ mIntercepted.removeAll(removed);
updateSyntheticNotification();
}
}
@@ -96,12 +97,6 @@ public class InterceptedNotifications {
return ent.key.equals(mSynKey);
}
- public void update(StatusBarNotification notification) {
- if (mIntercepted.containsKey(notification.getKey())) {
- mIntercepted.put(notification.getKey(), notification);
- }
- }
-
private boolean shouldDisplayIntercepted() {
return Settings.Secure.getInt(mContext.getContentResolver(),
Settings.Secure.DISPLAY_INTERCEPTED_NOTIFICATIONS, 0) != 0;
@@ -129,7 +124,7 @@ public class InterceptedNotifications {
mBar.getCurrentUserHandle());
if (mSynKey == null) {
mSynKey = sbn.getKey();
- mBar.addNotificationInternal(sbn, null);
+ mBar.displayNotification(sbn, null);
} else {
mBar.updateNotificationInternal(sbn, null);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
new file mode 100644
index 0000000..ce35e4b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.KeyguardIndicationTextView;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.BatteryManager;
+import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.text.format.Formatter;
+import android.util.Log;
+import android.view.View;
+
+/**
+ * Controls the little text indicator on the keyguard.
+ */
+public class KeyguardIndicationController {
+
+ private static final String TAG = "KeyguardIndicationController";
+
+ private static final int MSG_HIDE_TRANSIENT = 1;
+
+ private final Context mContext;
+ private final KeyguardIndicationTextView mTextView;
+ private final IBatteryStats mBatteryInfo;
+
+ private String mRestingIndication;
+ private String mTransientIndication;
+ private boolean mVisible;
+
+ private boolean mPowerPluggedIn;
+ private boolean mPowerCharged;
+
+ public KeyguardIndicationController(Context context, KeyguardIndicationTextView textView) {
+ mContext = context;
+ mTextView = textView;
+
+ mBatteryInfo = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService(BatteryStats.SERVICE_NAME));
+ KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitor);
+ context.registerReceiverAsUser(
+ mReceiver, UserHandle.OWNER, new IntentFilter(Intent.ACTION_TIME_TICK), null, null);
+ }
+
+ public void setVisible(boolean visible) {
+ mVisible = visible;
+ mTextView.setVisibility(visible ? View.VISIBLE : View.GONE);
+ if (visible) {
+ hideTransientIndication();
+ updateIndication();
+ }
+ }
+
+ /**
+ * Sets the indication that is shown if nothing else is showing.
+ */
+ public void setRestingIndication(String restingIndication) {
+ mRestingIndication = restingIndication;
+ updateIndication();
+ }
+
+ /**
+ * Hides transient indication in {@param delayMs}.
+ */
+ public void hideTransientIndicationDelayed(long delayMs) {
+ mHandler.sendMessageDelayed(
+ mHandler.obtainMessage(MSG_HIDE_TRANSIENT), delayMs);
+ }
+
+ /**
+ * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
+ */
+ public void showTransientIndication(int transientIndication) {
+ showTransientIndication(mContext.getResources().getString(transientIndication));
+ }
+
+ /**
+ * Shows {@param transientIndication} until it is hidden by {@link #hideTransientIndication}.
+ */
+ public void showTransientIndication(String transientIndication) {
+ mTransientIndication = transientIndication;
+ mHandler.removeMessages(MSG_HIDE_TRANSIENT);
+ updateIndication();
+ }
+
+ /**
+ * Hides transient indication.
+ */
+ public void hideTransientIndication() {
+ if (mTransientIndication != null) {
+ mTransientIndication = null;
+ mHandler.removeMessages(MSG_HIDE_TRANSIENT);
+ updateIndication();
+ }
+ }
+
+ private void updateIndication() {
+ if (mVisible) {
+ mTextView.switchIndication(computeIndication());
+ }
+ }
+
+ private String computeIndication() {
+ if (!TextUtils.isEmpty(mTransientIndication)) {
+ return mTransientIndication;
+ }
+ if (mPowerPluggedIn) {
+ return computePowerIndication();
+ }
+ return mRestingIndication;
+ }
+
+ private String computePowerIndication() {
+ if (mPowerCharged) {
+ return mContext.getResources().getString(R.string.keyguard_charged);
+ }
+
+ // Try fetching charging time from battery stats.
+ try {
+ long chargingTimeRemaining = mBatteryInfo.computeChargeTimeRemaining();
+ if (chargingTimeRemaining > 0) {
+ String chargingTimeFormatted =
+ Formatter.formatShortElapsedTime(mContext, chargingTimeRemaining);
+ return mContext.getResources().getString(
+ R.string.keyguard_indication_charging_time, chargingTimeFormatted);
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "Error calling IBatteryStats: ", e);
+ }
+
+ // Fall back to simple charging label.
+ return mContext.getResources().getString(R.string.keyguard_plugged_in);
+ }
+
+ KeyguardUpdateMonitorCallback mUpdateMonitor = new KeyguardUpdateMonitorCallback() {
+ @Override
+ public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) {
+ mPowerPluggedIn = status.status == BatteryManager.BATTERY_STATUS_CHARGING
+ || status.status == BatteryManager.BATTERY_STATUS_FULL;
+ mPowerCharged = status.isCharged();
+ updateIndication();
+ }
+ };
+
+ BroadcastReceiver mReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (mVisible) {
+ updateIndication();
+ }
+ }
+ };
+
+ private final Handler mHandler = new Handler() {
+ @Override
+ public void handleMessage(Message msg) {
+ if (msg.what == MSG_HIDE_TRANSIENT && mTransientIndication != null) {
+ mTransientIndication = null;
+ updateIndication();
+ }
+ }
+ };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
index ce31894..6819d9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -18,15 +18,13 @@ package com.android.systemui.statusbar;
import android.app.Notification;
import android.content.Context;
-import android.graphics.Color;
+import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
-import android.view.View;
import android.widget.ImageView;
-import android.widget.LinearLayout;
import android.widget.TextView;
-import com.android.internal.statusbar.StatusBarIcon;
+import com.android.internal.util.NotificationColorUtil;
import com.android.systemui.R;
import com.android.systemui.statusbar.phone.IconMerger;
@@ -37,6 +35,8 @@ public class NotificationOverflowIconsView extends IconMerger {
private TextView mMoreText;
private int mTintColor;
+ private int mIconSize;
+ private NotificationColorUtil mNotificationColorUtil = new NotificationColorUtil();
public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -46,6 +46,8 @@ public class NotificationOverflowIconsView extends IconMerger {
protected void onFinishInflate() {
super.onFinishInflate();
mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
+ mIconSize = getResources().getDimensionPixelSize(
+ com.android.internal.R.dimen.status_bar_icon_size);
}
public void setMoreText(TextView moreText) {
@@ -56,14 +58,24 @@ public class NotificationOverflowIconsView extends IconMerger {
StatusBarIconView v = new StatusBarIconView(getContext(), "",
notification.notification.getNotification());
v.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
- v.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
- addView(v);
+ addView(v, mIconSize, mIconSize);
v.set(notification.icon.getStatusBarIcon());
+ applyColor(notification.notification.getNotification(), v);
updateMoreText();
}
+ private void applyColor(Notification notification, StatusBarIconView view) {
+ if (notification.color != Notification.COLOR_DEFAULT) {
+ if (mNotificationColorUtil.isGrayscale(view.getDrawable())) {
+ view.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
+ }
+ } else {
+ view.setColorFilter(notification.color, PorterDuff.Mode.SRC_ATOP);
+ }
+ }
+
private void updateMoreText() {
- mMoreText.setText(getResources().getQuantityString(
- R.plurals.keyguard_more_overflow_text, getChildCount(), getChildCount()));
+ mMoreText.setText(
+ getResources().getString(R.string.keyguard_more_overflow_text, getChildCount()));
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java
index 3ca021a..1503072 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotView.java
@@ -41,6 +41,11 @@ public class SpeedBumpDotView extends View {
canvas.drawCircle(radius, radius, radius, mPaint);
}
+ @Override
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
public void setColor(int color) {
mPaint.setColor(color);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java
index 06a7f95..4febab1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpDotsState.java
@@ -70,23 +70,12 @@ public class SpeedBumpDotsState {
for (int i = 0; i < childCount; i++) {
View child = mHostView.getChildAt(i);
ViewState viewState = mStateMap.get(child);
- float translationX = child.getTranslationX();
- float translationY = child.getTranslationY();
- float scale = child.getScaleX();
- float alpha = child.getAlpha();
- if (translationX != viewState.xTranslation) {
- child.setTranslationX(viewState.xTranslation);
- }
- if (translationY != viewState.yTranslation) {
- child.setTranslationY(viewState.yTranslation);
- }
- if (scale != viewState.scale) {
- child.setScaleX(viewState.scale);
- child.setScaleY(viewState.scale);
- }
- if (alpha != viewState.alpha) {
- child.setAlpha(viewState.alpha);
- }
+
+ child.setTranslationX(viewState.xTranslation);
+ child.setTranslationY(viewState.yTranslation);
+ child.setScaleX(viewState.scale);
+ child.setScaleY(viewState.scale);
+ child.setAlpha(viewState.alpha);
}
}
@@ -115,7 +104,7 @@ public class SpeedBumpDotsState {
ViewState viewState = mStateMap.get(child);
child.animate().setInterpolator(mFastOutSlowInInterpolator)
.setStartDelay(startDelay)
- .alpha(viewState.alpha).withLayer()
+ .alpha(viewState.alpha)
.translationX(viewState.xTranslation)
.translationY(viewState.yTranslation)
.scaleX(viewState.scale).scaleY(viewState.scale);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
index a84daef..689d0e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SpeedBumpView.java
@@ -37,8 +37,8 @@ public class SpeedBumpView extends ExpandableView implements View.OnClickListene
private final int mDotsHeight;
private final int mTextPaddingInset;
private SpeedBumpDotsLayout mDots;
- private View mLineLeft;
- private View mLineRight;
+ private AlphaOptimizedView mLineLeft;
+ private AlphaOptimizedView mLineRight;
private boolean mIsExpanded;
private boolean mDividerVisible = true;
private ValueAnimator mCurrentAnimator;
@@ -89,8 +89,8 @@ public class SpeedBumpView extends ExpandableView implements View.OnClickListene
protected void onFinishInflate() {
super.onFinishInflate();
mDots = (SpeedBumpDotsLayout) findViewById(R.id.speed_bump_dots_layout);
- mLineLeft = findViewById(R.id.speedbump_line_left);
- mLineRight = findViewById(R.id.speedbump_line_right);
+ mLineLeft = (AlphaOptimizedView) findViewById(R.id.speedbump_line_left);
+ mLineRight = (AlphaOptimizedView) findViewById(R.id.speedbump_line_right);
mExplanationText = (TextView) findViewById(R.id.speed_bump_text);
resetExplanationText();
@@ -176,8 +176,7 @@ public class SpeedBumpView extends ExpandableView implements View.OnClickListene
.scaleX(scale)
.scaleY(scale)
.translationY(translationY)
- .setListener(needsHideListener ? mHideExplanationListener : null)
- .withLayer();
+ .setListener(needsHideListener ? mHideExplanationListener : null);
mExplanationTextVisible = visible;
}
}
@@ -211,7 +210,6 @@ public class SpeedBumpView extends ExpandableView implements View.OnClickListene
float endTranslationXRight = nowVisible ? 0.0f : mCenterX - mLineRight.getLeft();
mLineLeft.animate()
.alpha(endValue)
- .withLayer()
.scaleX(endValue)
.scaleY(endValue)
.translationX(endTranslationXLeft)
@@ -219,7 +217,6 @@ public class SpeedBumpView extends ExpandableView implements View.OnClickListene
.withEndAction(onFinishedRunnable);
mLineRight.animate()
.alpha(endValue)
- .withLayer()
.scaleX(endValue)
.scaleY(endValue)
.translationX(endTranslationXRight)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java
index 367d326..0fdc185 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BounceInterpolator.java
@@ -27,6 +27,7 @@ public class BounceInterpolator implements Interpolator {
@Override
public float getInterpolation(float t) {
+ t *= 11f / 10f;
if (t < 4f / 11f) {
return SCALE_FACTOR * t * t;
} else if (t < 8f / 11f) {
@@ -36,8 +37,7 @@ public class BounceInterpolator implements Interpolator {
float t2 = t - 9f / 11f;
return SCALE_FACTOR * t2 * t2 + 15f / 16f;
} else {
- float t2 = t - 21f / 22f;
- return SCALE_FACTOR * t2 * t2 + 63f / 64f;
+ return 1;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java
index b4f4865..086a266 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardPageSwipeHelper.java
@@ -28,6 +28,7 @@ import android.view.ViewConfiguration;
import android.view.ViewPropertyAnimator;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
+
import com.android.systemui.R;
import com.android.systemui.statusbar.FlingAnimationUtils;
@@ -39,7 +40,10 @@ import java.util.ArrayList;
public class KeyguardPageSwipeHelper {
private static final float SWIPE_MAX_ICON_SCALE_AMOUNT = 2.0f;
- private static final float SWIPE_RESTING_ALPHA_AMOUNT = 0.7f;
+ public static final float SWIPE_RESTING_ALPHA_AMOUNT = 0.5f;
+ public static final long HINT_PHASE1_DURATION = 250;
+ private static final long HINT_PHASE2_DURATION = 450;
+
private final Context mContext;
private FlingAnimationUtils mFlingAnimationUtils;
@@ -54,11 +58,13 @@ public class KeyguardPageSwipeHelper {
private int mTouchSlop;
private int mMinTranslationAmount;
private int mMinFlingVelocity;
+ private int mHintDistance;
private PowerManager mPowerManager;
private final View mLeftIcon;
private final View mCenterIcon;
private final View mRightIcon;
private Interpolator mFastOutSlowIn;
+ private Interpolator mBounceInterpolator;
private Animator mSwipeAnimator;
private boolean mCallbackCalled;
@@ -81,9 +87,12 @@ public class KeyguardPageSwipeHelper {
mMinFlingVelocity = configuration.getScaledMinimumFlingVelocity();
mMinTranslationAmount = mContext.getResources().getDimensionPixelSize(
R.dimen.keyguard_min_swipe_amount);
+ mHintDistance =
+ mContext.getResources().getDimensionPixelSize(R.dimen.hint_move_distance_sideways);
mFlingAnimationUtils = new FlingAnimationUtils(mContext, 0.4f);
mFastOutSlowIn = AnimationUtils.loadInterpolator(mContext,
android.R.interpolator.fast_out_slow_in);
+ mBounceInterpolator = new BounceInterpolator();
}
public boolean onTouchEvent(MotionEvent event) {
@@ -168,6 +177,83 @@ public class KeyguardPageSwipeHelper {
return false;
}
+ public void startHintAnimation(boolean right, Runnable onFinishedListener) {
+ startHintAnimationPhase1(right, onFinishedListener);
+ }
+
+ /**
+ * Phase 1: Move everything sidewards.
+ */
+ private void startHintAnimationPhase1(boolean right, final Runnable onFinishedListener) {
+ float target = right ? -mHintDistance : mHintDistance;
+ startHintTranslationAnimations(target, HINT_PHASE1_DURATION, mFastOutSlowIn);
+ ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, target);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mTranslation = (float) animation.getAnimatedValue();
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ if (mCancelled) {
+ mSwipeAnimator = null;
+ onFinishedListener.run();
+ } else {
+ startUnlockHintAnimationPhase2(onFinishedListener);
+ }
+ }
+ });
+ animator.setInterpolator(mFastOutSlowIn);
+ animator.setDuration(HINT_PHASE1_DURATION);
+ animator.start();
+ mSwipeAnimator = animator;
+ }
+
+ /**
+ * Phase 2: Move back.
+ */
+ private void startUnlockHintAnimationPhase2(final Runnable onFinishedListener) {
+ startHintTranslationAnimations(0f /* target */, HINT_PHASE2_DURATION, mBounceInterpolator);
+ ValueAnimator animator = ValueAnimator.ofFloat(mTranslation, 0f);
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ mTranslation = (float) animation.getAnimatedValue();
+ }
+ });
+ animator.addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mSwipeAnimator = null;
+ onFinishedListener.run();
+ }
+ });
+ animator.setInterpolator(mBounceInterpolator);
+ animator.setDuration(HINT_PHASE2_DURATION);
+ animator.start();
+ mSwipeAnimator = animator;
+ }
+
+ private void startHintTranslationAnimations(float target, long duration,
+ Interpolator interpolator) {
+ ArrayList<View> targetViews = mCallback.getTranslationViews();
+ for (View targetView : targetViews) {
+ targetView.animate()
+ .setDuration(duration)
+ .setInterpolator(interpolator)
+ .translationX(target);
+ }
+ }
+
private void onUserActivity(long when) {
mPowerManager.userActivity(when, false);
}
@@ -180,7 +266,6 @@ public class KeyguardPageSwipeHelper {
View targetView = mTranslation > 0 ? mLeftIcon : mRightIcon;
targetView.animate().cancel();
if (mSwipeAnimator != null) {
- mSwipeAnimator.removeAllListeners();
mSwipeAnimator.cancel();
hideInactiveIcons(true);
}
@@ -218,11 +303,18 @@ public class KeyguardPageSwipeHelper {
}
});
animator.addListener(new AnimatorListenerAdapter() {
+ private boolean mCancelled;
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ mCancelled = true;
+ }
+
@Override
public void onAnimationEnd(Animator animation) {
mSwipeAnimator = null;
mSwipingInProgress = false;
- if (!snapBack && !mCallbackCalled) {
+ if (!snapBack && !mCallbackCalled && !mCancelled) {
// ensure that the callback is called eventually
mCallback.onAnimationToSideStarted(mTranslation < 0);
@@ -281,7 +373,7 @@ public class KeyguardPageSwipeHelper {
private void setTranslation(float translation, boolean isReset) {
translation = rightSwipePossible() ? translation : Math.max(0, translation);
translation = leftSwipePossible() ? translation : Math.min(0, translation);
- if (translation != mTranslation) {
+ if (translation != mTranslation || isReset) {
ArrayList<View> translatedViews = mCallback.getTranslationViews();
for (View view : translatedViews) {
view.setTranslationX(translation);
@@ -307,7 +399,7 @@ public class KeyguardPageSwipeHelper {
}
}
- private void showAllIcons(boolean animate) {
+ public void showAllIcons(boolean animate) {
float scale = 1.0f;
float alpha = SWIPE_RESTING_ALPHA_AMOUNT;
updateIcon(mRightIcon, scale, alpha, animate);
@@ -315,6 +407,11 @@ public class KeyguardPageSwipeHelper {
updateIcon(mLeftIcon, scale, alpha, animate);
}
+ public void animateHideLeftRightIcon() {
+ updateIcon(mRightIcon, 0f, 0f, true);
+ updateIcon(mLeftIcon, 0f, 0f, true);
+ }
+
private void hideInactiveIcons(boolean animate){
View otherView = mTranslation < 0 ? mLeftIcon : mRightIcon;
updateIcon(otherView, 0, 0, animate);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index dfd5a88..7926d03 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -48,7 +48,8 @@ public class NotificationPanelView extends PanelView implements
View.OnClickListener, NotificationStackScrollLayout.OnOverscrollTopChangedListener,
KeyguardPageSwipeHelper.Callback {
- private static float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.6f;
+ private static final float EXPANSION_RUBBER_BAND_EXTRA_FACTOR = 0.6f;
+ private static final float LOCK_ICON_ACTIVE_SCALE = 1.2f;
private KeyguardPageSwipeHelper mPageSwiper;
private StatusBarHeaderView mHeader;
@@ -82,17 +83,20 @@ public class NotificationPanelView extends PanelView implements
private float mQsExpansionHeight;
private int mQsMinExpansionHeight;
private int mQsMaxExpansionHeight;
- private int mMinStackHeight;
private int mQsPeekHeight;
- private float mNotificationTranslation;
- private int mStackScrollerIntrinsicPadding;
private boolean mStackScrollerOverscrolling;
private boolean mQsExpansionEnabled = true;
private ValueAnimator mQsExpansionAnimator;
private FlingAnimationUtils mFlingAnimationUtils;
private int mStatusBarMinHeight;
+ private boolean mHeaderHidden;
+ private boolean mUnlockIconActive;
+ private int mNotificationsHeaderCollideDistance;
+ private int mUnlockMoveDistance;
private Interpolator mFastOutSlowInInterpolator;
+ private Interpolator mFastOutLinearInterpolator;
+ private Interpolator mLinearOutSlowInInterpolator;
private ObjectAnimator mClockAnimator;
private int mClockAnimationTarget = -1;
private int mTopPaddingAdjustment;
@@ -143,6 +147,10 @@ public class NotificationPanelView extends PanelView implements
mNotificationStackScroller.setOverscrollTopChangedListener(this);
mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
android.R.interpolator.fast_out_slow_in);
+ mLinearOutSlowInInterpolator = AnimationUtils.loadInterpolator(getContext(),
+ android.R.interpolator.linear_out_slow_in);
+ mFastOutLinearInterpolator = AnimationUtils.loadInterpolator(getContext(),
+ android.R.interpolator.fast_out_linear_in);
mKeyguardBottomArea = (KeyguardBottomAreaView) findViewById(R.id.keyguard_bottom_area);
mSwipeTranslationViews.add(mNotificationStackScroller);
mSwipeTranslationViews.add(mKeyguardStatusView);
@@ -154,11 +162,13 @@ public class NotificationPanelView extends PanelView implements
super.loadDimens();
mNotificationTopPadding = getResources().getDimensionPixelSize(
R.dimen.notifications_top_padding);
- mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height);
mFlingAnimationUtils = new FlingAnimationUtils(getContext(), 0.4f);
mStatusBarMinHeight = getResources().getDimensionPixelSize(
com.android.internal.R.dimen.status_bar_height);
mQsPeekHeight = getResources().getDimensionPixelSize(R.dimen.qs_peek_height);
+ mNotificationsHeaderCollideDistance =
+ getResources().getDimensionPixelSize(R.dimen.header_notifications_collide_distance);
+ mUnlockMoveDistance = getResources().getDimensionPixelOffset(R.dimen.unlock_move_distance);
mClockPositionAlgorithm.loadDimens(getResources());
}
@@ -171,7 +181,8 @@ public class NotificationPanelView extends PanelView implements
mQsMaxExpansionHeight = mHeader.getExpandedHeight() + mQsContainer.getHeight();
if (mQsExpanded) {
if (mQsFullyExpanded) {
- setQsStackScrollerPadding(mQsMaxExpansionHeight);
+ mQsExpansionHeight = mQsMaxExpansionHeight;
+ requestScrollerTopPaddingUpdate(false /* animate */);
}
} else {
if (!mStackScrollerOverscrolling) {
@@ -188,11 +199,12 @@ public class NotificationPanelView extends PanelView implements
*/
private void positionClockAndNotifications() {
boolean animateClock = mNotificationStackScroller.isAddOrRemoveAnimationPending();
+ int stackScrollerPadding;
if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
int bottom = mStackScrollerOverscrolling
? mHeader.getCollapsedHeight()
: mHeader.getBottom();
- mStackScrollerIntrinsicPadding = bottom + mQsPeekHeight
+ stackScrollerPadding = bottom + mQsPeekHeight
+ mNotificationTopPadding;
mTopPaddingAdjustment = 0;
} else {
@@ -210,12 +222,11 @@ public class NotificationPanelView extends PanelView implements
mKeyguardStatusView.setY(mClockPositionResult.clockY);
}
applyClockAlpha(mClockPositionResult.clockAlpha);
- mStackScrollerIntrinsicPadding = mClockPositionResult.stackScrollerPadding;
+ stackScrollerPadding = mClockPositionResult.stackScrollerPadding;
mTopPaddingAdjustment = mClockPositionResult.stackScrollerPaddingAdjustment;
}
- mNotificationStackScroller.setTopPadding(mStackScrollerIntrinsicPadding,
- mAnimateNextTopPaddingChange || animateClock);
- mAnimateNextTopPaddingChange = false;
+ mNotificationStackScroller.setIntrinsicPadding(stackScrollerPadding);
+ requestScrollerTopPaddingUpdate(animateClock);
}
private void startClockAnimation(int y) {
@@ -231,8 +242,8 @@ public class NotificationPanelView extends PanelView implements
mClockAnimator.removeAllListeners();
mClockAnimator.cancel();
}
- mClockAnimator =
- ObjectAnimator.ofFloat(mKeyguardStatusView, View.Y, mClockAnimationTarget);
+ mClockAnimator = ObjectAnimator
+ .ofFloat(mKeyguardStatusView, View.Y, mClockAnimationTarget);
mClockAnimator.setInterpolator(mFastOutSlowInInterpolator);
mClockAnimator.setDuration(StackStateAnimator.ANIMATION_DURATION_STANDARD);
mClockAnimator.addListener(new AnimatorListenerAdapter() {
@@ -277,6 +288,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public void resetViews() {
mBlockTouches = false;
+ mUnlockIconActive = false;
mPageSwiper.reset();
closeQs();
}
@@ -369,6 +381,7 @@ public class NotificationPanelView extends PanelView implements
mInitialTouchX = x;
mQsTracking = true;
mIntercepting = false;
+ mNotificationStackScroller.removeLongPressCallback();
return true;
}
break;
@@ -411,7 +424,9 @@ public class NotificationPanelView extends PanelView implements
}
// TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
// implementation.
- if (!mIsExpanding && !mQsExpanded && mStatusBar.getBarState() != StatusBarState.SHADE) {
+ if ((!mIsExpanding || mHintAnimationRunning)
+ && !mQsExpanded
+ && mStatusBar.getBarState() != StatusBarState.SHADE) {
mPageSwiper.onTouchEvent(event);
if (mPageSwiper.isSwipingInProgress()) {
return true;
@@ -506,6 +521,13 @@ public class NotificationPanelView extends PanelView implements
updateQsState();
}
+ @Override
+ public void flingTopOverscroll(float velocity, boolean open) {
+ mStackScrollerOverscrolling = false;
+ setQsExpansion(mQsExpansionHeight);
+ flingSettings(velocity, open);
+ }
+
private void onQsExpansionStarted() {
onQsExpansionStarted(0);
}
@@ -537,10 +559,11 @@ public class NotificationPanelView extends PanelView implements
mHeader.setExpanded(expandVisually, mStackScrollerOverscrolling);
mNotificationStackScroller.setEnabled(!mQsExpanded);
mQsPanel.setVisibility(expandVisually ? View.VISIBLE : View.INVISIBLE);
- mQsContainer.setVisibility(mKeyguardShowing && !mQsExpanded
+ mQsContainer.setVisibility(mKeyguardShowing && !expandVisually
? View.INVISIBLE
: View.VISIBLE);
mScrollView.setTouchEnabled(mQsExpanded);
+ mNotificationStackScroller.setTouchEnabled(!mQsExpanded);
}
private void setQsExpansion(float height) {
@@ -554,9 +577,7 @@ public class NotificationPanelView extends PanelView implements
mQsExpansionHeight = height;
mHeader.setExpansion(height - mQsPeekHeight);
setQsTranslation(height);
- if (!mStackScrollerOverscrolling) {
- setQsStackScrollerPadding(height);
- }
+ requestScrollerTopPaddingUpdate(false /* animate */);
mStatusBar.userActivity();
}
@@ -564,24 +585,12 @@ public class NotificationPanelView extends PanelView implements
mQsContainer.setY(height - mQsContainer.getHeight());
}
- private void setQsStackScrollerPadding(float height) {
- float start = height - mScrollView.getScrollY() + mNotificationTopPadding;
- float stackHeight = mNotificationStackScroller.getHeight() - start;
- if (stackHeight <= mMinStackHeight) {
- float overflow = mMinStackHeight - stackHeight;
- stackHeight = mMinStackHeight;
- start = mNotificationStackScroller.getHeight() - stackHeight;
- mNotificationStackScroller.setTranslationY(overflow);
- mNotificationTranslation = overflow + mScrollView.getScrollY();
- } else {
- mNotificationStackScroller.setTranslationY(0);
- mNotificationTranslation = mScrollView.getScrollY();
- }
- mNotificationStackScroller.setTopPadding(clampQsStackScrollerPadding((int) start), false);
- }
- private int clampQsStackScrollerPadding(int desiredPadding) {
- return Math.max(desiredPadding, mStackScrollerIntrinsicPadding);
+ private void requestScrollerTopPaddingUpdate(boolean animate) {
+ mNotificationStackScroller.updateTopPadding(mQsExpansionHeight,
+ mScrollView.getScrollY(),
+ mAnimateNextTopPaddingChange || animate);
+ mAnimateNextTopPaddingChange = false;
}
private void trackMovement(MotionEvent event) {
@@ -689,11 +698,9 @@ public class NotificationPanelView extends PanelView implements
@Override
protected int getMaxPanelHeight() {
// TODO: Figure out transition for collapsing when QS is open, adjust height here.
- int maxPanelHeight = super.getMaxPanelHeight();
- int emptyBottomMargin = mStackScrollerContainer.getHeight()
- - mNotificationStackScroller.getHeight()
- + mNotificationStackScroller.getEmptyBottomMargin();
- int maxHeight = maxPanelHeight - emptyBottomMargin - mTopPaddingAdjustment;
+ int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
+ int maxHeight = mNotificationStackScroller.getHeight() - emptyBottomMargin
+ - mTopPaddingAdjustment;
maxHeight = Math.max(maxHeight, mStatusBarMinHeight);
return maxHeight;
}
@@ -708,6 +715,79 @@ public class NotificationPanelView extends PanelView implements
positionClockAndNotifications();
}
mNotificationStackScroller.setStackHeight(expandedHeight);
+ updateKeyguardHeaderVisibility();
+ updateUnlockIcon();
+ }
+
+ private void updateUnlockIcon() {
+ if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
+ || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+ boolean active = getMaxPanelHeight() - getExpandedHeight() > mUnlockMoveDistance;
+ if (active && !mUnlockIconActive && mTracking) {
+ mKeyguardBottomArea.getLockIcon().animate()
+ .alpha(1f)
+ .scaleY(LOCK_ICON_ACTIVE_SCALE)
+ .scaleX(LOCK_ICON_ACTIVE_SCALE)
+ .setInterpolator(mFastOutLinearInterpolator)
+ .setDuration(150);
+ } else if (!active && mUnlockIconActive && mTracking) {
+ mKeyguardBottomArea.getLockIcon().animate()
+ .alpha(KeyguardPageSwipeHelper.SWIPE_RESTING_ALPHA_AMOUNT)
+ .scaleY(1f)
+ .scaleX(1f)
+ .setInterpolator(mFastOutLinearInterpolator)
+ .setDuration(150);
+ }
+ mUnlockIconActive = active;
+ }
+ }
+
+ /**
+ * Hides the header when notifications are colliding with it.
+ */
+ private void updateKeyguardHeaderVisibility() {
+ if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
+ || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+ boolean hidden;
+ if (mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+
+ // When on Keyguard, we hide the header as soon as the top card of the notification
+ // stack scroller is close enough (collision distance) to the bottom of the header.
+ hidden = mNotificationStackScroller.getNotificationsTopY()
+ <= mHeader.getBottom() + mNotificationsHeaderCollideDistance;
+ } else {
+
+ // In SHADE_LOCKED, the top card is already really close to the header. Hide it as
+ // soon as we start translating the stack.
+ hidden = mNotificationStackScroller.getTranslationY() < 0;
+ }
+
+ if (hidden && !mHeaderHidden) {
+ mHeader.animate()
+ .alpha(0f)
+ .withLayer()
+ .translationY(-mHeader.getHeight()/2)
+ .setInterpolator(mFastOutLinearInterpolator)
+ .setDuration(200);
+ } else if (!hidden && mHeaderHidden) {
+ mHeader.animate()
+ .alpha(1f)
+ .withLayer()
+ .translationY(0)
+ .setInterpolator(mLinearOutSlowInInterpolator)
+ .setDuration(200);
+ }
+ mHeaderHidden = hidden;
+ } else {
+ mHeader.animate().cancel();
+ mHeader.setAlpha(1f);
+ mHeader.setTranslationY(0f);
+ if (mHeader.getLayerType() != LAYER_TYPE_NONE) {
+ mHeader.setLayerType(LAYER_TYPE_NONE, null);
+ }
+ mHeaderHidden = false;
+ }
+
}
@Override
@@ -726,24 +806,44 @@ public class NotificationPanelView extends PanelView implements
@Override
protected void onOverExpansionChanged(float overExpansion) {
- float currentOverScroll = mNotificationStackScroller.getCurrentOverScrolledPixels(true);
- float expansionChange = overExpansion - mOverExpansion;
- expansionChange *= EXPANSION_RUBBER_BAND_EXTRA_FACTOR;
- mNotificationStackScroller.setOverScrolledPixels(currentOverScroll + expansionChange,
- true /* onTop */,
- false /* animate */);
- super.onOverExpansionChanged(overExpansion);
+ if (mStatusBar.getBarState() != StatusBarState.KEYGUARD) {
+ float currentOverScroll = mNotificationStackScroller.getCurrentOverScrolledPixels(true);
+ float expansionChange = overExpansion - mOverExpansion;
+ expansionChange *= EXPANSION_RUBBER_BAND_EXTRA_FACTOR;
+ mNotificationStackScroller.setOverScrolledPixels(currentOverScroll + expansionChange,
+ true /* onTop */,
+ false /* animate */);
+ }
+ }
+
+ @Override
+ protected void onTrackingStarted() {
+ super.onTrackingStarted();
+ if (mStatusBar.getBarState() == StatusBarState.KEYGUARD
+ || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED) {
+ mPageSwiper.animateHideLeftRightIcon();
+ }
}
@Override
protected void onTrackingStopped(boolean expand) {
super.onTrackingStopped(expand);
- mOverExpansion = 0.0f;
- mNotificationStackScroller.setOverScrolledPixels(0.0f, true /* onTop */,
- true /* animate */);
+ mNotificationStackScroller.setOverScrolledPixels(0.0f, true /* onTop */, true /* animate */);
+ if (expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD
+ || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) {
+ mPageSwiper.showAllIcons(true);
+ }
+ if (!expand && (mStatusBar.getBarState() == StatusBarState.KEYGUARD
+ || mStatusBar.getBarState() == StatusBarState.SHADE_LOCKED)) {
+ mKeyguardBottomArea.getLockIcon().animate()
+ .alpha(0f)
+ .scaleX(2f)
+ .scaleY(2f)
+ .setInterpolator(mFastOutLinearInterpolator)
+ .setDuration(100);
+ }
}
-
@Override
public void onHeightChanged(ExpandableView view) {
requestPanelHeightUpdate();
@@ -752,8 +852,7 @@ public class NotificationPanelView extends PanelView implements
@Override
public void onScrollChanged() {
if (mQsExpanded) {
- mNotificationStackScroller.setTranslationY(
- mNotificationTranslation - mScrollView.getScrollY());
+ requestScrollerTopPaddingUpdate(false /* animate */);
}
}
@@ -777,14 +876,61 @@ public class NotificationPanelView extends PanelView implements
@Override
public void onAnimationToSideStarted(boolean rightPage) {
- if (rightPage) {
- mKeyguardBottomArea.launchCamera();
- } else {
+ boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? rightPage : !rightPage;
+ if (start) {
mKeyguardBottomArea.launchPhone();
+ } else {
+ mKeyguardBottomArea.launchCamera();
}
mBlockTouches = true;
}
+ @Override
+ protected void onEdgeClicked(boolean right) {
+ if ((right && getRightIcon().getVisibility() != View.VISIBLE)
+ || (!right && getLeftIcon().getVisibility() != View.VISIBLE)) {
+ return;
+ }
+ mHintAnimationRunning = true;
+ mPageSwiper.startHintAnimation(right, new Runnable() {
+ @Override
+ public void run() {
+ mHintAnimationRunning = false;
+ mStatusBar.onHintFinished();
+ }
+ });
+ startHighlightIconAnimation(right ? getRightIcon() : getLeftIcon());
+ boolean start = getLayoutDirection() == LAYOUT_DIRECTION_RTL ? right : !right;
+ if (start) {
+ mStatusBar.onPhoneHintStarted();
+ } else {
+ mStatusBar.onCameraHintStarted();
+ }
+ }
+
+ @Override
+ protected void startUnlockHintAnimation() {
+ super.startUnlockHintAnimation();
+ startHighlightIconAnimation(getCenterIcon());
+ }
+
+ /**
+ * Starts the highlight (making it fully opaque) animation on an icon.
+ */
+ private void startHighlightIconAnimation(final View icon) {
+ icon.animate()
+ .alpha(1.0f)
+ .setDuration(KeyguardPageSwipeHelper.HINT_PHASE1_DURATION)
+ .setInterpolator(mFastOutSlowInInterpolator)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ icon.animate().alpha(KeyguardPageSwipeHelper.SWIPE_RESTING_ALPHA_AMOUNT)
+ .setDuration(KeyguardPageSwipeHelper.HINT_PHASE1_DURATION)
+ .setInterpolator(mFastOutSlowInInterpolator);
+ }
+ });
+ }
@Override
public float getPageWidth() {
@@ -798,7 +944,9 @@ public class NotificationPanelView extends PanelView implements
@Override
public View getLeftIcon() {
- return mKeyguardBottomArea.getPhoneImageView();
+ return getLayoutDirection() == LAYOUT_DIRECTION_RTL
+ ? mKeyguardBottomArea.getCameraImageView()
+ : mKeyguardBottomArea.getPhoneImageView();
}
@Override
@@ -808,6 +956,8 @@ public class NotificationPanelView extends PanelView implements
@Override
public View getRightIcon() {
- return mKeyguardBottomArea.getCameraImageView();
+ return getLayoutDirection() == LAYOUT_DIRECTION_RTL
+ ? mKeyguardBottomArea.getPhoneImageView()
+ : mKeyguardBottomArea.getCameraImageView();
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 4686933..89a1907 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -50,15 +50,17 @@ public abstract class PanelView extends FrameLayout {
protected PhoneStatusBar mStatusBar;
private float mPeekHeight;
private float mHintDistance;
+ private int mEdgeTapAreaWidth;
private float mInitialOffsetOnTouch;
private float mExpandedFraction = 0;
- private float mExpandedHeight = 0;
+ protected float mExpandedHeight = 0;
private boolean mJustPeeked;
private boolean mClosing;
- private boolean mTracking;
+ protected boolean mTracking;
private boolean mTouchSlopExceeded;
private int mTrackingPointer;
protected int mTouchSlop;
+ protected boolean mHintAnimationRunning;
private ValueAnimator mHeightAnimator;
private ObjectAnimator mPeekAnimator;
@@ -111,6 +113,7 @@ public abstract class PanelView extends FrameLayout {
final ViewConfiguration configuration = ViewConfiguration.get(getContext());
mTouchSlop = configuration.getScaledTouchSlop();
mHintDistance = res.getDimension(R.dimen.hint_move_distance);
+ mEdgeTapAreaWidth = res.getDimensionPixelSize(R.dimen.edge_tap_area_width);
}
private void trackMovement(MotionEvent event) {
@@ -147,7 +150,6 @@ public abstract class PanelView extends FrameLayout {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
-
mInitialTouchY = y;
mInitialTouchX = x;
mInitialOffsetOnTouch = mExpandedHeight;
@@ -156,10 +158,11 @@ public abstract class PanelView extends FrameLayout {
initVelocityTracker();
}
trackMovement(event);
- if (!waitForTouchSlop || mHeightAnimator != null) {
+ if (!waitForTouchSlop || (mHeightAnimator != null && !mHintAnimationRunning)) {
if (mHeightAnimator != null) {
mHeightAnimator.cancel(); // end any outstanding animations
}
+ mTouchSlopExceeded = (mHeightAnimator != null && !mHintAnimationRunning);
onTrackingStarted();
}
if (mExpandedHeight == 0) {
@@ -216,13 +219,14 @@ public abstract class PanelView extends FrameLayout {
case MotionEvent.ACTION_CANCEL:
mTrackingPointer = -1;
trackMovement(event);
- if (mTracking && mTouchSlopExceeded) {
+ if ((mTracking && mTouchSlopExceeded)
+ || event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
float vel = getCurrentVelocity();
boolean expand = flingExpands(vel);
onTrackingStopped(expand);
fling(vel, expand);
} else {
- boolean expands = onEmptySpaceClick();
+ boolean expands = onEmptySpaceClick(mInitialTouchX);
onTrackingStopped(expands);
}
if (mVelocityTracker != null) {
@@ -279,8 +283,9 @@ public abstract class PanelView extends FrameLayout {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
- if (mHeightAnimator != null) {
+ if (mHeightAnimator != null && !mHintAnimationRunning) {
mHeightAnimator.cancel(); // end any outstanding animations
+ mTouchSlopExceeded = true;
return true;
}
mInitialTouchY = y;
@@ -305,6 +310,9 @@ public abstract class PanelView extends FrameLayout {
trackMovement(event);
if (scrolledToBottom) {
if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) {
+ if (mHeightAnimator != null) {
+ mHeightAnimator.cancel();
+ }
mInitialOffsetOnTouch = mExpandedHeight;
mInitialTouchY = y;
mInitialTouchX = x;
@@ -362,8 +370,10 @@ public abstract class PanelView extends FrameLayout {
protected void fling(float vel, boolean expand) {
cancelPeek();
float target = expand ? getMaxPanelHeight() : 0.0f;
- if (target == mExpandedHeight) {
+ if (target == mExpandedHeight || mOverExpansion > 0) {
onExpandingFinished();
+ mExpandedHeight = target;
+ mOverExpansion = 0.0f;
mBar.panelExpansionChanged(this, mExpandedFraction);
return;
}
@@ -452,6 +462,7 @@ public abstract class PanelView extends FrameLayout {
overExpansion = Math.max(0, overExpansion);
if (overExpansion != mOverExpansion) {
onOverExpansionChanged(overExpansion);
+ mOverExpansion = overExpansion;
}
if (DEBUG) {
@@ -462,9 +473,7 @@ public abstract class PanelView extends FrameLayout {
mExpandedFraction = Math.min(1f, (fh == 0) ? 0 : mExpandedHeight / fh);
}
- protected void onOverExpansionChanged(float overExpansion) {
- mOverExpansion = overExpansion;
- }
+ protected abstract void onOverExpansionChanged(float overExpansion);
protected abstract void onHeightUpdated(float expandedHeight);
@@ -550,14 +559,22 @@ public abstract class PanelView extends FrameLayout {
}
cancelPeek();
onExpandingStarted();
- startUnlockHintAnimationPhase1();
+ startUnlockHintAnimationPhase1(new Runnable() {
+ @Override
+ public void run() {
+ onExpandingFinished();
+ mStatusBar.onHintFinished();
+ mHintAnimationRunning = false;
+ }
+ });
mStatusBar.onUnlockHintStarted();
+ mHintAnimationRunning = true;
}
/**
* Phase 1: Move everything upwards.
*/
- private void startUnlockHintAnimationPhase1() {
+ private void startUnlockHintAnimationPhase1(final Runnable onAnimationFinished) {
float target = Math.max(0, getMaxPanelHeight() - mHintDistance);
ValueAnimator animator = createHeightAnimator(target);
animator.setDuration(250);
@@ -574,10 +591,9 @@ public abstract class PanelView extends FrameLayout {
public void onAnimationEnd(Animator animation) {
if (mCancelled) {
mHeightAnimator = null;
- onExpandingFinished();
- mStatusBar.onUnlockHintFinished();
+ onAnimationFinished.run();
} else {
- startUnlockHintAnimationPhase2();
+ startUnlockHintAnimationPhase2(onAnimationFinished);
}
}
});
@@ -588,7 +604,7 @@ public abstract class PanelView extends FrameLayout {
/**
* Phase 2: Bounce down.
*/
- private void startUnlockHintAnimationPhase2() {
+ private void startUnlockHintAnimationPhase2(final Runnable onAnimationFinished) {
ValueAnimator animator = createHeightAnimator(getMaxPanelHeight());
animator.setDuration(450);
animator.setInterpolator(mBounceInterpolator);
@@ -596,8 +612,7 @@ public abstract class PanelView extends FrameLayout {
@Override
public void onAnimationEnd(Animator animation) {
mHeightAnimator = null;
- onExpandingFinished();
- mStatusBar.onUnlockHintFinished();
+ onAnimationFinished.run();
}
});
animator.start();
@@ -620,13 +635,30 @@ public abstract class PanelView extends FrameLayout {
*
* @return whether the panel will be expanded after the action performed by this method
*/
- private boolean onEmptySpaceClick() {
+ private boolean onEmptySpaceClick(float x) {
+ if (mHintAnimationRunning) {
+ return true;
+ }
+ if (x < mEdgeTapAreaWidth
+ && mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+ onEdgeClicked(false /* right */);
+ return true;
+ } else if (x > getWidth() - mEdgeTapAreaWidth
+ && mStatusBar.getBarState() == StatusBarState.KEYGUARD) {
+ onEdgeClicked(true /* right */);
+ return true;
+ } else {
+ return onMiddleClicked();
+ }
+ }
+
+ private boolean onMiddleClicked() {
switch (mStatusBar.getBarState()) {
case StatusBarState.KEYGUARD:
startUnlockHintAnimation();
return true;
case StatusBarState.SHADE_LOCKED:
- // TODO: Go to Keyguard again.
+ mStatusBar.goToKeyguard();
return true;
case StatusBarState.SHADE:
collapse();
@@ -636,6 +668,8 @@ public abstract class PanelView extends FrameLayout {
}
}
+ protected abstract void onEdgeClicked(boolean right);
+
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
+ " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
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 b1216e6..e55de94 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -105,6 +105,7 @@ import com.android.systemui.statusbar.DragDownHelper;
import com.android.systemui.statusbar.ExpandableNotificationRow;
import com.android.systemui.statusbar.GestureRecorder;
import com.android.systemui.statusbar.InterceptedNotifications;
+import com.android.systemui.statusbar.KeyguardIndicationController;
import com.android.systemui.statusbar.NotificationData;
import com.android.systemui.statusbar.NotificationData.Entry;
import com.android.systemui.statusbar.NotificationOverflowContainer;
@@ -122,7 +123,6 @@ import com.android.systemui.statusbar.policy.LocationControllerImpl;
import com.android.systemui.statusbar.policy.NetworkControllerImpl;
import com.android.systemui.statusbar.policy.RotationLockControllerImpl;
import com.android.systemui.statusbar.policy.ZenModeController;
-import com.android.systemui.statusbar.policy.ZenModeControllerImpl;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
@@ -174,6 +174,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
/** The minimum delay in ms between reports of notification visibility. */
private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
+ /**
+ * The delay to reset the hint text when the hint animation is finished running.
+ */
+ private static final int HINT_RESET_DELAY_MS = 1200;
+
// fling gesture tuning parameters, scaled to display density
private float mSelfExpandVelocityPx; // classic value: 2000px/s
private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
@@ -248,10 +253,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
View mKeyguardStatusView;
KeyguardBottomAreaView mKeyguardBottomArea;
boolean mLeaveOpenOnKeyguardHide;
- KeyguardIndicationTextView mKeyguardIndicationTextView;
+ KeyguardIndicationController mKeyguardIndicationController;
- // TODO: Fetch phrase from search/hotword provider.
- String mKeyguardHotwordPhrase = "";
int mKeyguardMaxNotificationCount;
View mDateTimeView;
@@ -662,8 +665,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mKeyguardBottomArea =
(KeyguardBottomAreaView) mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
mKeyguardBottomArea.setActivityStarter(this);
- mKeyguardIndicationTextView = (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
- R.id.keyguard_indication_text);
+ mKeyguardIndicationController = new KeyguardIndicationController(mContext,
+ (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
+ R.id.keyguard_indication_text));
mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
mDateTimeView = mHeader.findViewById(R.id.datetime);
@@ -1047,16 +1051,22 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void addNotificationInternal(StatusBarNotification notification, Ranking ranking) {
- if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore());
- Entry shadeEntry = createNotificationViews(notification);
- if (shadeEntry == null) {
- return;
- }
+ if (DEBUG) Log.d(TAG, "addNotification key=" + notification.getKey());
if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(notification, ranking)) {
// Forward the ranking so we can sort the new notification.
mNotificationData.updateRanking(ranking);
return;
}
+ mIntercepted.remove(notification.getKey());
+ displayNotification(notification, ranking);
+ }
+
+ public void displayNotification(StatusBarNotification notification,
+ Ranking ranking) {
+ Entry shadeEntry = createNotificationViews(notification);
+ if (shadeEntry == null) {
+ return;
+ }
if (mUseHeadsUp && shouldInterrupt(notification)) {
if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
Entry interruptionCandidate = new Entry(notification, null);
@@ -1112,7 +1122,8 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void updateNotificationInternal(StatusBarNotification notification, Ranking ranking) {
super.updateNotificationInternal(notification, ranking);
- mIntercepted.update(notification);
+ // if we're here, then the notification is already in the shade
+ mIntercepted.remove(notification.getKey());
}
@Override
@@ -2847,12 +2858,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
private void updateKeyguardState() {
if (mState == StatusBarState.KEYGUARD) {
mKeyguardStatusView.setVisibility(View.VISIBLE);
- mKeyguardIndicationTextView.setVisibility(View.VISIBLE);
- mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
+ mKeyguardIndicationController.setVisible(true);
mNotificationPanel.resetViews();
} else {
mKeyguardStatusView.setVisibility(View.GONE);
- mKeyguardIndicationTextView.setVisibility(View.GONE);
+ mKeyguardIndicationController.setVisible(false);
}
if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
mKeyguardBottomArea.setVisibility(View.VISIBLE);
@@ -2875,9 +2885,12 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
public void updateStackScrollerState() {
if (mStackScroller == null) return;
- mStackScroller.setDimmed(mState == StatusBarState.KEYGUARD, false /* animate */);
- mStackScroller.setVisibility(!mShowLockscreenNotifications && mState == StatusBarState.KEYGUARD
+ boolean onKeyguard = mState == StatusBarState.KEYGUARD;
+ mStackScroller.setDimmed(onKeyguard, false /* animate */);
+ mStackScroller.setVisibility(!mShowLockscreenNotifications && onKeyguard
? View.INVISIBLE : View.VISIBLE);
+ mStackScroller.setScrollingEnabled(!onKeyguard);
+ mStackScroller.setExpandingEnabled(!onKeyguard);
}
public void userActivity() {
@@ -2936,7 +2949,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void onActivated(View view) {
userActivity();
- mKeyguardIndicationTextView.switchIndication(R.string.notification_tap_again);
+ mKeyguardIndicationController.showTransientIndication(R.string.notification_tap_again);
mStackScroller.setActivatedChild(view);
}
@@ -2951,7 +2964,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
@Override
public void onActivationReset(View view) {
if (view == mStackScroller.getActivatedChild()) {
- mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
+ mKeyguardIndicationController.hideTransientIndication();
mStackScroller.setActivatedChild(null);
}
}
@@ -2960,11 +2973,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
public void onUnlockHintStarted() {
- mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock);
+ mKeyguardIndicationController.showTransientIndication(R.string.keyguard_unlock);
}
- public void onUnlockHintFinished() {
- mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
+ public void onHintFinished() {
+ // Delay the reset a bit so the user can read the text.
+ mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
+ }
+
+ public void onCameraHintStarted() {
+ mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
+ }
+
+ public void onPhoneHintStarted() {
+ mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
}
public void onTrackingStopped(boolean expand) {
@@ -3000,6 +3022,11 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
mStackScroller.setDimmed(false /* dimmed */, true /* animate */);
}
+ @Override
+ public void onTouchSlopExceeded() {
+ mStackScroller.removeLongPressCallback();
+ }
+
/**
* If secure with redaction: Show bouncer, go to unlocked shade.
*
@@ -3023,6 +3050,16 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode,
}
/**
+ * Goes back to the keyguard after hanging around in {@link StatusBarState#SHADE_LOCKED}.
+ */
+ public void goToKeyguard() {
+ if (mState == StatusBarState.SHADE_LOCKED) {
+ setBarState(StatusBarState.KEYGUARD);
+ updateKeyguardState();
+ }
+ }
+
+ /**
* @return a ViewGroup that spans the entire panel which contains the quick settings
*/
public ViewGroup getQuickSettingsOverlayParent() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
index 1344703..7c87580 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QSTileHost.java
@@ -95,7 +95,6 @@ public class QSTileHost implements QSTile.Host {
mTiles.add(new LocationTile(this));
mTiles.add(new CastTile(this));
mTiles.add(new HotspotTile(this));
- mTiles.add(new BugreportTile(this));
mUserTracker = new CurrentUserTracker(mContext) {
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index b51626d..d5e8e8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -40,7 +40,6 @@ public class StatusBarWindowView extends FrameLayout {
public static final String TAG = "StatusBarWindowView";
public static final boolean DEBUG = BaseStatusBar.DEBUG;
- private ExpandHelper mExpandHelper;
private DragDownHelper mDragDownHelper;
private NotificationStackScrollLayout mStackScrollLayout;
private NotificationPanelView mNotificationPanel;
@@ -73,12 +72,6 @@ public class StatusBarWindowView extends FrameLayout {
mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
R.id.notification_stack_scroller);
mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
- int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
- int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
- mExpandHelper = new ExpandHelper(getContext(), mStackScrollLayout,
- minHeight, maxHeight);
- mExpandHelper.setEventSource(this);
- mExpandHelper.setScrollAdapter(mStackScrollLayout);
mDragDownHelper = new DragDownHelper(getContext(), this, mStackScrollLayout, mService);
// We really need to be able to animate while window animations are going on
@@ -114,12 +107,6 @@ public class StatusBarWindowView extends FrameLayout {
boolean intercept = false;
if (mNotificationPanel.isFullyExpanded()
&& mStackScrollLayout.getVisibility() == View.VISIBLE
- && (mService.getBarState() == StatusBarState.SHADE
- || (mService.getBarState() == StatusBarState.SHADE_LOCKED
- && !mService.isBouncerShowing()))) {
- intercept = mExpandHelper.onInterceptTouchEvent(ev);
- } else if (mNotificationPanel.isFullyExpanded()
- && mStackScrollLayout.getVisibility() == View.VISIBLE
&& mService.getBarState() == StatusBarState.KEYGUARD
&& !mService.isBouncerShowing()) {
intercept = mDragDownHelper.onInterceptTouchEvent(ev);
@@ -139,10 +126,7 @@ public class StatusBarWindowView extends FrameLayout {
@Override
public boolean onTouchEvent(MotionEvent ev) {
boolean handled = false;
- if (mNotificationPanel.isFullyExpanded()
- && mService.getBarState() != StatusBarState.KEYGUARD) {
- handled = mExpandHelper.onTouchEvent(ev);
- } else if (mService.getBarState() == StatusBarState.KEYGUARD) {
+ if (mService.getBarState() == StatusBarState.KEYGUARD) {
handled = mDragDownHelper.onTouchEvent(ev);
}
if (!handled) {
@@ -168,8 +152,8 @@ public class StatusBarWindowView extends FrameLayout {
}
public void cancelExpandHelper() {
- if (mExpandHelper != null) {
- mExpandHelper.cancel();
+ if (mStackScrollLayout != null) {
+ mStackScrollLayout.cancelExpandHelper();
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index ac26da2..df01c12 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -225,6 +225,11 @@ public class HeadsUpNotificationView extends FrameLayout implements SwipeHelper.
}
}
+ @Override
+ public void expansionStateChanged(boolean isExpanding) {
+
+ }
+
// SwipeHelper.Callback methods
@Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
index 6225c12..4cf72a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeController.java
@@ -16,6 +16,7 @@
package com.android.systemui.statusbar.policy;
+import android.net.Uri;
import android.service.notification.Condition;
public interface ZenModeController {
@@ -24,10 +25,12 @@ public interface ZenModeController {
void setZen(boolean zen);
boolean isZen();
void requestConditions(boolean request);
- void select(Condition condition);
+ void setExitConditionId(Uri exitConditionId);
+ Uri getExitConditionId();
public static class Callback {
public void onZenChanged(boolean zen) {}
+ public void onExitConditionChanged(Uri exitConditionId) {}
public void onConditionsChanged(Condition[] conditions) {}
}
} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
index adf2935..da8fd32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/ZenModeControllerImpl.java
@@ -25,6 +25,7 @@ import android.os.ServiceManager;
import android.provider.Settings.Global;
import android.service.notification.Condition;
import android.service.notification.IConditionListener;
+import android.service.notification.ZenModeConfig;
import android.util.Slog;
import com.android.systemui.qs.GlobalSetting;
@@ -35,10 +36,12 @@ import java.util.LinkedHashMap;
/** Platform implementation of the zen mode controller. **/
public class ZenModeControllerImpl implements ZenModeController {
private static final String TAG = "ZenModeControllerImpl";
+ private static final boolean DEBUG = false;
private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
private final Context mContext;
- private final GlobalSetting mSetting;
+ private final GlobalSetting mModeSetting;
+ private final GlobalSetting mConfigSetting;
private final INotificationManager mNoMan;
private final LinkedHashMap<Uri, Condition> mConditions = new LinkedHashMap<Uri, Condition>();
@@ -46,13 +49,20 @@ public class ZenModeControllerImpl implements ZenModeController {
public ZenModeControllerImpl(Context context, Handler handler) {
mContext = context;
- mSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
+ mModeSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE) {
@Override
protected void handleValueChanged(int value) {
fireZenChanged(value != 0);
}
};
- mSetting.setListening(true);
+ mConfigSetting = new GlobalSetting(mContext, handler, Global.ZEN_MODE_CONFIG_ETAG) {
+ @Override
+ protected void handleValueChanged(int value) {
+ fireExitConditionChanged();
+ }
+ };
+ mModeSetting.setListening(true);
+ mConfigSetting.setListening(true);
mNoMan = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
}
@@ -69,12 +79,12 @@ public class ZenModeControllerImpl implements ZenModeController {
@Override
public boolean isZen() {
- return mSetting.getValue() != 0;
+ return mModeSetting.getValue() != 0;
}
@Override
public void setZen(boolean zen) {
- mSetting.setValue(zen ? 1 : 0);
+ mModeSetting.setValue(zen ? 1 : 0);
}
@Override
@@ -91,12 +101,25 @@ public class ZenModeControllerImpl implements ZenModeController {
}
@Override
- public void select(Condition condition) {
+ public void setExitConditionId(Uri exitConditionId) {
+ try {
+ mNoMan.setZenModeCondition(exitConditionId);
+ } catch (RemoteException e) {
+ // noop
+ }
+ }
+
+ @Override
+ public Uri getExitConditionId() {
try {
- mNoMan.setZenModeCondition(condition == null ? null : condition.id);
+ final ZenModeConfig config = mNoMan.getZenModeConfig();
+ if (config != null) {
+ return config.exitConditionId;
+ }
} catch (RemoteException e) {
// noop
}
+ return null;
}
private void fireZenChanged(boolean zen) {
@@ -111,6 +134,14 @@ public class ZenModeControllerImpl implements ZenModeController {
}
}
+ private void fireExitConditionChanged() {
+ final Uri exitConditionId = getExitConditionId();
+ if (DEBUG) Slog.d(TAG, "exitConditionId changed: " + exitConditionId);
+ for (Callback cb : mCallbacks) {
+ cb.onExitConditionChanged(exitConditionId);
+ }
+ }
+
private void updateConditions(Condition[] conditions) {
if (conditions == null || conditions.length == 0) return;
for (Condition c : conditions) {
@@ -124,8 +155,8 @@ public class ZenModeControllerImpl implements ZenModeController {
private final IConditionListener mListener = new IConditionListener.Stub() {
@Override
public void onConditionsReceived(Condition[] conditions) {
- Slog.d(TAG, "onConditionsReceived " + (conditions == null ? 0 : conditions.length)
- + " mRequesting=" + mRequesting);
+ if (DEBUG) Slog.d(TAG, "onConditionsReceived "
+ + (conditions == null ? 0 : conditions.length) + " mRequesting=" + mRequesting);
if (!mRequesting) return;
updateConditions(conditions);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 6892b85..0383706 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -30,7 +30,6 @@ import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.animation.AnimationUtils;
import android.widget.OverScroller;
-
import com.android.systemui.ExpandHelper;
import com.android.systemui.R;
import com.android.systemui.SwipeHelper;
@@ -51,13 +50,15 @@ public class NotificationStackScrollLayout extends ViewGroup
private static final String TAG = "NotificationStackScrollLayout";
private static final boolean DEBUG = false;
- private static final float RUBBER_BAND_FACTOR = 0.35f;
+ private static final float RUBBER_BAND_FACTOR_NORMAL = 0.35f;
+ private static final float RUBBER_BAND_FACTOR_AFTER_EXPAND = 0.15f;
/**
* Sentinel value for no current active pointer. Used by {@link #mActivePointerId}.
*/
private static final int INVALID_POINTER = -1;
+ private ExpandHelper mExpandHelper;
private SwipeHelper mSwipeHelper;
private boolean mSwipingInProgress;
private int mCurrentStackHeight = Integer.MAX_VALUE;
@@ -73,6 +74,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private float mMaxOverScroll;
private boolean mIsBeingDragged;
private int mLastMotionY;
+ private int mDownX;
private int mActivePointerId;
private int mSidePaddings;
@@ -106,6 +108,7 @@ public class NotificationStackScrollLayout extends ViewGroup
private ArrayList<View> mSwipedOutViews = new ArrayList<View>();
private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
private boolean mAnimationsEnabled;
+ private boolean mChangePositionInProgress;
/**
* The raw amount of the overScroll on the top, which is not rubber-banded.
@@ -128,6 +131,39 @@ public class NotificationStackScrollLayout extends ViewGroup
private boolean mChildrenUpdateRequested;
private SpeedBumpView mSpeedBumpView;
private boolean mIsExpansionChanging;
+ private boolean mExpandingNotification;
+ private boolean mExpandedInThisMotion;
+ private boolean mScrollingEnabled;
+
+ /**
+ * Was the scroller scrolled to the top when the down motion was observed?
+ */
+ private boolean mScrolledToTopOnFirstDown;
+
+ /**
+ * The minimal amount of over scroll which is needed in order to switch to the quick settings
+ * when over scrolling on a expanded card.
+ */
+ private float mMinTopOverScrollToEscape;
+ private int mIntrinsicPadding;
+ private int mNotificationTopPadding;
+ private int mMinStackHeight;
+ private boolean mDontReportNextOverScroll;
+
+ /**
+ * The maximum scrollPosition which we are allowed to reach when a notification was expanded.
+ * This is needed to avoid scrolling too far after the notification was collapsed in the same
+ * motion.
+ */
+ private int mMaxScrollAfterExpand;
+ private OnLongClickListener mLongClickListener;
+
+ /**
+ * Should in this touch motion only be scrolling allowed? It's true when the scroller was
+ * animating.
+ */
+ private boolean mOnlyScrollingInThisMotion;
+ private boolean mTouchEnabled = true;
private ViewTreeObserver.OnPreDrawListener mChildrenUpdater
= new ViewTreeObserver.OnPreDrawListener() {
@Override
@@ -194,6 +230,7 @@ public class NotificationStackScrollLayout extends ViewGroup
float densityScale = getResources().getDisplayMetrics().density;
float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
+ mSwipeHelper.setLongPressListener(mLongClickListener);
mSidePaddings = context.getResources()
.getDimensionPixelSize(R.dimen.notification_side_padding);
@@ -207,6 +244,17 @@ public class NotificationStackScrollLayout extends ViewGroup
mPaddingBetweenElementsNormal = context.getResources()
.getDimensionPixelSize(R.dimen.notification_padding);
updatePadding(false);
+ int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
+ int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
+ mExpandHelper = new ExpandHelper(getContext(), this,
+ minHeight, maxHeight);
+ mExpandHelper.setEventSource(this);
+ mExpandHelper.setScrollAdapter(this);
+ mMinTopOverScrollToEscape = getResources().getDimensionPixelSize(
+ R.dimen.min_top_overscroll_to_qs);
+ mNotificationTopPadding = getResources().getDimensionPixelSize(
+ R.dimen.notifications_top_padding);
+ mMinStackHeight = getResources().getDimensionPixelSize(R.dimen.collapsed_stack_height);
}
private void updatePadding(boolean dimmed) {
@@ -343,7 +391,7 @@ public class NotificationStackScrollLayout extends ViewGroup
return mTopPadding;
}
- public void setTopPadding(int topPadding, boolean animate) {
+ private void setTopPadding(int topPadding, boolean animate) {
if (mTopPadding != topPadding) {
mTopPadding = topPadding;
updateAlgorithmHeightAndPadding();
@@ -414,6 +462,7 @@ public class NotificationStackScrollLayout extends ViewGroup
public void setLongPressListener(View.OnLongClickListener listener) {
mSwipeHelper.setLongPressListener(listener);
+ mLongClickListener = listener;
}
public void onChildDismissed(View v) {
@@ -511,6 +560,29 @@ public class NotificationStackScrollLayout extends ViewGroup
if (v instanceof ExpandableNotificationRow) {
((ExpandableNotificationRow) v).setUserLocked(userLocked);
}
+ removeLongPressCallback();
+ requestDisallowInterceptTouchEvent(true);
+ }
+
+ @Override
+ public void expansionStateChanged(boolean isExpanding) {
+ mExpandingNotification = isExpanding;
+ if (!mExpandedInThisMotion) {
+ mMaxScrollAfterExpand = mOwnScrollY;
+ mExpandedInThisMotion = true;
+ }
+ }
+
+ public void setScrollingEnabled(boolean enable) {
+ mScrollingEnabled = enable;
+ }
+
+ public void setExpandingEnabled(boolean enable) {
+ mExpandHelper.setEnabled(enable);
+ }
+
+ private boolean isScrollingEnabled() {
+ return mScrollingEnabled;
}
public View getChildContentView(View v) {
@@ -548,18 +620,44 @@ public class NotificationStackScrollLayout extends ViewGroup
if (!isEnabled()) {
return false;
}
+ boolean isCancelOrUp = ev.getActionMasked() == MotionEvent.ACTION_CANCEL
+ || ev.getActionMasked()== MotionEvent.ACTION_UP;
+ boolean expandWantsIt = false;
+ if (!mSwipingInProgress && !mOnlyScrollingInThisMotion) {
+ if (isCancelOrUp) {
+ mExpandHelper.onlyObserveMovements(false);
+ }
+ boolean wasExpandingBefore = mExpandingNotification;
+ expandWantsIt = mExpandHelper.onTouchEvent(ev);
+ if (mExpandedInThisMotion && !mExpandingNotification && wasExpandingBefore) {
+ dispatchDownEventToScroller(ev);
+ }
+ }
boolean scrollerWantsIt = false;
- if (!mSwipingInProgress) {
+ if (!mSwipingInProgress && !mExpandingNotification) {
scrollerWantsIt = onScrollTouch(ev);
}
boolean horizontalSwipeWantsIt = false;
- if (!mIsBeingDragged) {
+ if (!mIsBeingDragged
+ && !mExpandingNotification
+ && !mExpandedInThisMotion
+ && !mOnlyScrollingInThisMotion) {
horizontalSwipeWantsIt = mSwipeHelper.onTouchEvent(ev);
}
- return horizontalSwipeWantsIt || scrollerWantsIt || super.onTouchEvent(ev);
+ return horizontalSwipeWantsIt || scrollerWantsIt || expandWantsIt || super.onTouchEvent(ev);
+ }
+
+ private void dispatchDownEventToScroller(MotionEvent ev) {
+ MotionEvent downEvent = MotionEvent.obtain(ev);
+ downEvent.setAction(MotionEvent.ACTION_DOWN);
+ onScrollTouch(downEvent);
+ downEvent.recycle();
}
private boolean onScrollTouch(MotionEvent ev) {
+ if (!isScrollingEnabled()) {
+ return false;
+ }
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
@@ -583,6 +681,7 @@ public class NotificationStackScrollLayout extends ViewGroup
// Remember where the motion event started
mLastMotionY = (int) ev.getY();
+ mDownX = (int) ev.getX();
mActivePointerId = ev.getPointerId(0);
break;
}
@@ -594,8 +693,11 @@ public class NotificationStackScrollLayout extends ViewGroup
}
final int y = (int) ev.getY(activePointerIndex);
+ final int x = (int) ev.getX(activePointerIndex);
int deltaY = mLastMotionY - y;
- if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
+ final int xDiff = Math.abs(x - mDownX);
+ final int yDiff = Math.abs(deltaY);
+ if (!mIsBeingDragged && yDiff > mTouchSlop && yDiff > xDiff) {
setIsBeingDragged(true);
if (deltaY > 0) {
deltaY -= mTouchSlop;
@@ -606,7 +708,10 @@ public class NotificationStackScrollLayout extends ViewGroup
if (mIsBeingDragged) {
// Scroll to follow the motion event
mLastMotionY = y;
- final int range = getScrollRange();
+ int range = getScrollRange();
+ if (mExpandedInThisMotion) {
+ range = Math.min(range, mMaxScrollAfterExpand);
+ }
float scrollAmount;
if (deltaY < 0) {
@@ -631,19 +736,28 @@ public class NotificationStackScrollLayout extends ViewGroup
velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
- if (getChildCount() > 0) {
- if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
- fling(-initialVelocity);
- } else {
- if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
- getScrollRange())) {
- postInvalidateOnAnimation();
+ if (shouldOverScrollFling(initialVelocity)) {
+ onOverScrollFling(true, initialVelocity);
+ } else {
+ if (getChildCount() > 0) {
+ if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
+ float currentOverScrollTop = getCurrentOverScrollAmount(true);
+ if (currentOverScrollTop == 0.0f || initialVelocity > 0) {
+ fling(-initialVelocity);
+ } else {
+ onOverScrollFling(false, initialVelocity);
+ }
+ } else {
+ if (mScroller.springBack(mScrollX, mOwnScrollY, 0, 0, 0,
+ getScrollRange())) {
+ postInvalidateOnAnimation();
+ }
}
}
- }
- mActivePointerId = INVALID_POINTER;
- endDrag();
+ mActivePointerId = INVALID_POINTER;
+ endDrag();
+ }
}
break;
case MotionEvent.ACTION_CANCEL:
@@ -658,17 +772,27 @@ public class NotificationStackScrollLayout extends ViewGroup
case MotionEvent.ACTION_POINTER_DOWN: {
final int index = ev.getActionIndex();
mLastMotionY = (int) ev.getY(index);
+ mDownX = (int) ev.getX(index);
mActivePointerId = ev.getPointerId(index);
break;
}
case MotionEvent.ACTION_POINTER_UP:
onSecondaryPointerUp(ev);
mLastMotionY = (int) ev.getY(ev.findPointerIndex(mActivePointerId));
+ mDownX = (int) ev.getX(ev.findPointerIndex(mActivePointerId));
break;
}
return true;
}
+ private void onOverScrollFling(boolean open, int initialVelocity) {
+ if (mOverscrollTopChangedListener != null) {
+ mOverscrollTopChangedListener.flingTopOverscroll(initialVelocity, open);
+ }
+ mDontReportNextOverScroll = true;
+ setOverScrollAmount(0.0f, true, false);
+ }
+
/**
* Perform a scroll upwards and adapt the overscroll amounts accordingly
*
@@ -689,11 +813,13 @@ public class NotificationStackScrollLayout extends ViewGroup
float scrollAmount = newTopAmount < 0 ? -newTopAmount : 0.0f;
float newScrollY = mOwnScrollY + scrollAmount;
if (newScrollY > range) {
- float currentBottomPixels = getCurrentOverScrolledPixels(false);
- // We overScroll on the top
- setOverScrolledPixels(currentBottomPixels + newScrollY - range,
- false /* onTop */,
- false /* animate */);
+ if (!mExpandedInThisMotion) {
+ float currentBottomPixels = getCurrentOverScrolledPixels(false);
+ // We overScroll on the top
+ setOverScrolledPixels(currentBottomPixels + newScrollY - range,
+ false /* onTop */,
+ false /* animate */);
+ }
mOwnScrollY = range;
scrollAmount = 0.0f;
}
@@ -834,7 +960,7 @@ public class NotificationStackScrollLayout extends ViewGroup
* @param animate Should an animation be performed.
*/
public void setOverScrolledPixels(float numPixels, boolean onTop, boolean animate) {
- setOverScrollAmount(numPixels * RUBBER_BAND_FACTOR, onTop, animate, true);
+ setOverScrollAmount(numPixels * getRubberBandFactor(), onTop, animate, true);
}
/**
@@ -870,17 +996,21 @@ public class NotificationStackScrollLayout extends ViewGroup
if (animate) {
mStateAnimator.animateOverScrollToAmount(amount, onTop);
} else {
- setOverScrolledPixels(amount / RUBBER_BAND_FACTOR, onTop);
+ setOverScrolledPixels(amount / getRubberBandFactor(), onTop);
mAmbientState.setOverScrollAmount(amount, onTop);
- requestChildrenUpdate();
if (onTop) {
- float scrollAmount = mOwnScrollY < 0 ? -mOwnScrollY : 0;
- notifyOverscrollTopListener(scrollAmount + amount);
+ notifyOverscrollTopListener(amount);
}
+ requestChildrenUpdate();
}
}
private void notifyOverscrollTopListener(float amount) {
+ mExpandHelper.onlyObserveMovements(amount > 1.0f);
+ if (mDontReportNextOverScroll) {
+ mDontReportNextOverScroll = false;
+ return;
+ }
if (mOverscrollTopChangedListener != null) {
mOverscrollTopChangedListener.onOverscrollTopChanged(amount);
}
@@ -928,7 +1058,7 @@ public class NotificationStackScrollLayout extends ViewGroup
updateChildren();
float overScrollTop = getCurrentOverScrollAmount(true);
if (mOwnScrollY < 0) {
- notifyOverscrollTopListener(-mOwnScrollY + overScrollTop);
+ notifyOverscrollTopListener(-mOwnScrollY);
} else {
notifyOverscrollTopListener(overScrollTop);
}
@@ -950,6 +1080,7 @@ public class NotificationStackScrollLayout extends ViewGroup
onTop = true;
newAmount = -mOwnScrollY;
mOwnScrollY = 0;
+ mDontReportNextOverScroll = true;
} else {
onTop = false;
newAmount = mOwnScrollY - scrollRange;
@@ -1085,13 +1216,14 @@ public class NotificationStackScrollLayout extends ViewGroup
float bottomAmount = getCurrentOverScrollAmount(false);
if (velocityY < 0 && topAmount > 0) {
mOwnScrollY -= (int) topAmount;
+ mDontReportNextOverScroll = true;
setOverScrollAmount(0, true, false);
- mMaxOverScroll = Math.abs(velocityY) / 1000f * RUBBER_BAND_FACTOR
+ mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor()
* mOverflingDistance + topAmount;
} else if (velocityY > 0 && bottomAmount > 0) {
mOwnScrollY += bottomAmount;
setOverScrollAmount(0, false, false);
- mMaxOverScroll = Math.abs(velocityY) / 1000f * RUBBER_BAND_FACTOR
+ mMaxOverScroll = Math.abs(velocityY) / 1000f * getRubberBandFactor()
* mOverflingDistance + bottomAmount;
} else {
// it will be set once we reach the boundary
@@ -1104,6 +1236,44 @@ public class NotificationStackScrollLayout extends ViewGroup
}
}
+ /**
+ * @return Whether a fling performed on the top overscroll edge lead to the expanded
+ * overScroll view (i.e QS).
+ */
+ private boolean shouldOverScrollFling(int initialVelocity) {
+ float topOverScroll = getCurrentOverScrollAmount(true);
+ return mScrolledToTopOnFirstDown
+ && !mExpandedInThisMotion
+ && topOverScroll > mMinTopOverScrollToEscape
+ && initialVelocity > 0;
+ }
+
+ public void updateTopPadding(float qsHeight, int scrollY, boolean animate) {
+ float start = qsHeight - scrollY + mNotificationTopPadding;
+ float stackHeight = getHeight() - start;
+ if (stackHeight <= mMinStackHeight) {
+ float overflow = mMinStackHeight - stackHeight;
+ stackHeight = mMinStackHeight;
+ start = getHeight() - stackHeight;
+ setTranslationY(overflow);
+ } else {
+ setTranslationY(0);
+ }
+ setTopPadding(clampPadding((int) start), animate);
+ }
+
+ private int clampPadding(int desiredPadding) {
+ return Math.max(desiredPadding, mIntrinsicPadding);
+ }
+
+ private float getRubberBandFactor() {
+ return mExpandedInThisMotion
+ ? RUBBER_BAND_FACTOR_AFTER_EXPAND
+ : (mScrolledToTopOnFirstDown
+ ? 1.0f
+ : RUBBER_BAND_FACTOR_NORMAL);
+ }
+
private void endDrag() {
setIsBeingDragged(false);
@@ -1119,23 +1289,37 @@ public class NotificationStackScrollLayout extends ViewGroup
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
+ initDownStates(ev);
+ boolean expandWantsIt = false;
+ if (!mSwipingInProgress && !mOnlyScrollingInThisMotion) {
+ expandWantsIt = mExpandHelper.onInterceptTouchEvent(ev);
+ }
boolean scrollWantsIt = false;
- if (!mSwipingInProgress) {
+ if (!mSwipingInProgress && !mExpandingNotification) {
scrollWantsIt = onInterceptTouchEventScroll(ev);
}
boolean swipeWantsIt = false;
- if (!mIsBeingDragged) {
+ if (!mIsBeingDragged
+ && !mExpandingNotification
+ && !mExpandedInThisMotion
+ && !mOnlyScrollingInThisMotion) {
swipeWantsIt = mSwipeHelper.onInterceptTouchEvent(ev);
}
- return swipeWantsIt || scrollWantsIt ||
- super.onInterceptTouchEvent(ev);
+ return swipeWantsIt || scrollWantsIt || expandWantsIt || super.onInterceptTouchEvent(ev);
+ }
+
+ private void initDownStates(MotionEvent ev) {
+ if (ev.getAction() == MotionEvent.ACTION_DOWN) {
+ mExpandedInThisMotion = false;
+ mOnlyScrollingInThisMotion = !mScroller.isFinished();
+ }
}
@Override
protected void onViewRemoved(View child) {
super.onViewRemoved(child);
mStackScrollAlgorithm.notifyChildrenChanged(this);
- if (mChildrenChangingPositions.contains(child)) {
+ if (mChangePositionInProgress) {
// This is only a position change, don't do anything special
return;
}
@@ -1230,7 +1414,7 @@ public class NotificationStackScrollLayout extends ViewGroup
* @param child The view to be added.
*/
public void generateAddAnimation(View child) {
- if (mIsExpanded && mAnimationsEnabled && !mChildrenChangingPositions.contains(child)) {
+ if (mIsExpanded && mAnimationsEnabled && !mChangePositionInProgress) {
// Generate Animations
mChildrenToAddAnimated.add(child);
mNeedsAnimation = true;
@@ -1245,10 +1429,14 @@ public class NotificationStackScrollLayout extends ViewGroup
*/
public void changeViewPosition(View child, int newIndex) {
if (child != null && child.getParent() == this) {
- mChildrenChangingPositions.add(child);
+ mChangePositionInProgress = true;
removeView(child);
addView(child, newIndex);
- mNeedsAnimation = true;
+ mChangePositionInProgress = false;
+ if (mIsExpanded && mAnimationsEnabled) {
+ mChildrenChangingPositions.add(child);
+ mNeedsAnimation = true;
+ }
}
}
@@ -1350,6 +1538,9 @@ public class NotificationStackScrollLayout extends ViewGroup
}
private boolean onInterceptTouchEventScroll(MotionEvent ev) {
+ if (!isScrollingEnabled()) {
+ return false;
+ }
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onMotionEvent will be called and we do the actual
@@ -1366,13 +1557,6 @@ public class NotificationStackScrollLayout extends ViewGroup
return true;
}
- /*
- * Don't try to intercept touch if we can't scroll anyway.
- */
- if (mOwnScrollY == 0 && getScrollRange() == 0) {
- return false;
- }
-
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_MOVE: {
/*
@@ -1398,10 +1582,13 @@ public class NotificationStackScrollLayout extends ViewGroup
}
final int y = (int) ev.getY(pointerIndex);
+ final int x = (int) ev.getX(pointerIndex);
final int yDiff = Math.abs(y - mLastMotionY);
- if (yDiff > mTouchSlop) {
+ final int xDiff = Math.abs(x - mDownX);
+ if (yDiff > mTouchSlop && yDiff > xDiff) {
setIsBeingDragged(true);
mLastMotionY = y;
+ mDownX = x;
initVelocityTrackerIfNotExists();
mVelocityTracker.addMovement(ev);
}
@@ -1421,7 +1608,9 @@ public class NotificationStackScrollLayout extends ViewGroup
* ACTION_DOWN always refers to pointer index 0.
*/
mLastMotionY = y;
+ mDownX = (int) ev.getX();
mActivePointerId = ev.getPointerId(0);
+ mScrolledToTopOnFirstDown = isScrolledToTop();
initOrResetVelocityTracker();
mVelocityTracker.addMovement(ev);
@@ -1468,7 +1657,7 @@ public class NotificationStackScrollLayout extends ViewGroup
mIsBeingDragged = isDragged;
if (isDragged) {
requestDisallowInterceptTouchEvent(true);
- mSwipeHelper.removeLongPressCallback();
+ removeLongPressCallback();
}
}
@@ -1476,10 +1665,14 @@ public class NotificationStackScrollLayout extends ViewGroup
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (!hasWindowFocus) {
- mSwipeHelper.removeLongPressCallback();
+ removeLongPressCallback();
}
}
+ public void removeLongPressCallback() {
+ mSwipeHelper.removeLongPressCallback();
+ }
+
@Override
public boolean isScrolledToTop() {
return mOwnScrollY == 0;
@@ -1608,6 +1801,33 @@ public class NotificationStackScrollLayout extends ViewGroup
updateSpeedBump(true);
}
+ public void cancelExpandHelper() {
+ mExpandHelper.cancel();
+ }
+
+ public void setIntrinsicPadding(int intrinsicPadding) {
+ mIntrinsicPadding = intrinsicPadding;
+ }
+
+ /**
+ * @return the y position of the first notification
+ */
+ public float getNotificationsTopY() {
+ return mTopPadding + getTranslationY();
+ }
+
+ public void setTouchEnabled(boolean touchEnabled) {
+ mTouchEnabled = touchEnabled;
+ }
+
+ @Override
+ public boolean dispatchTouchEvent(MotionEvent ev) {
+ if (!mTouchEnabled) {
+ return false;
+ }
+ return super.dispatchTouchEvent(ev);
+ }
+
/**
* A listener that is notified when some child locations might have changed.
*/
@@ -1620,6 +1840,15 @@ public class NotificationStackScrollLayout extends ViewGroup
*/
public interface OnOverscrollTopChangedListener {
public void onOverscrollTopChanged(float amount);
+
+ /**
+ * Notify a listener that the scroller wants to escape from the scrolling motion and
+ * start a fling animation to the expanded or collapsed overscroll view (e.g expand the QS)
+ *
+ * @param velocity The velocity that the Scroller had when over flinging
+ * @param open Should the fling open or close the overscroll view.
+ */
+ public void flingTopOverscroll(float velocity, boolean open);
}
static class AnimationEvent {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 2b52c7e..a48cab8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -131,10 +131,14 @@ public class StackScrollAlgorithm {
algorithmState.scrolledPixelsTop = 0;
algorithmState.itemsInBottomStack = 0.0f;
algorithmState.partialInBottom = 0.0f;
- float topOverScroll = ambientState.getOverScrollAmount(true /* onTop */);
float bottomOverScroll = ambientState.getOverScrollAmount(false /* onTop */);
- algorithmState.scrollY = (int) (ambientState.getScrollY() + mCollapsedSize
- + bottomOverScroll - topOverScroll);
+
+ int scrollY = ambientState.getScrollY();
+
+ // Due to the overScroller, the stackscroller can have negative scroll state. This is
+ // already accounted for by the top padding and doesn't need an additional adaption
+ scrollY = Math.max(0, scrollY);
+ algorithmState.scrollY = (int) (scrollY + mCollapsedSize + bottomOverScroll);
updateVisibleChildren(resultState, algorithmState);
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
index 898b46e..80a14b3 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumePanel.java
@@ -602,7 +602,7 @@ public class VolumePanel extends Handler {
if (LOGD) Log.d(mTag, "expand mZenPanel=" + mZenPanel);
if (mZenPanel == null) {
mZenPanel = (ZenModePanel) mZenPanelStub.inflate();
- mZenPanel.init(mZenController);
+ mZenPanel.init(mZenController, mDialog != null ? 'D' : 'E');
mZenPanel.setCallback(new ZenModePanel.Callback() {
@Override
public void onMoreSettings() {
@@ -651,6 +651,13 @@ public class VolumePanel extends Handler {
mExpandDivider.setVisibility(show ? View.VISIBLE : View.GONE);
mExpandButton.setImageResource(zen ? com.android.systemui.R.drawable.ic_vol_zen_on
: com.android.systemui.R.drawable.ic_vol_zen_off);
+ if (show) {
+ if (zen) {
+ expand();
+ } else {
+ collapse();
+ }
+ }
} else {
mExpandButton.setVisibility(View.GONE);
mExpandDivider.setVisibility(View.GONE);
@@ -882,10 +889,6 @@ public class VolumePanel extends Handler {
// when the stream is for remote playback, use -1 to reset the stream type evaluation
mAudioManager.forceVolumeControlStream(stream);
- // Showing dialog - use collapsed state
- if (mZenModeCapable) {
- collapse();
- }
if (mDialog != null) {
mDialog.show();
}
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
index c338563..1000352 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenModePanel.java
@@ -18,16 +18,21 @@ package com.android.systemui.volume;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.provider.Settings;
import android.service.notification.Condition;
+import android.service.notification.ZenModeConfig;
import android.util.AttributeSet;
+import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ImageView;
@@ -39,26 +44,47 @@ import com.android.systemui.R;
import com.android.systemui.statusbar.policy.ZenModeController;
import java.util.Arrays;
-import java.util.HashSet;
+import java.util.Objects;
public class ZenModePanel extends LinearLayout {
- private static final int[] MINUTES = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+ private static final boolean DEBUG = false;
+
+ private static final int[] MINUTE_BUCKETS = new int[] { 15, 30, 45, 60, 120, 180, 240, 480 };
+ private static final int MIN_BUCKET_MINUTES = MINUTE_BUCKETS[0];
+ private static final int MAX_BUCKET_MINUTES = MINUTE_BUCKETS[MINUTE_BUCKETS.length - 1];
+ private static final int DEFAULT_BUCKET_INDEX = Arrays.binarySearch(MINUTE_BUCKETS, 60);
+
+ private static final int SECONDS_MS = 1000;
+ private static final int MINUTES_MS = 60 * SECONDS_MS;
+
public static final Intent ZEN_SETTINGS = new Intent(Settings.ACTION_ZEN_MODE_SETTINGS);
private final Context mContext;
private final LayoutInflater mInflater;
- private final HashSet<RadioButton> mRadioButtons = new HashSet<RadioButton>();
private final H mHandler = new H();
+ private final Favorites mFavorites;
+
+ private char mLogTag = '?';
+ private String mTag;
private LinearLayout mConditions;
- private int mMinutesIndex = Arrays.binarySearch(MINUTES, 60); // default to one hour
private Callback mCallback;
private ZenModeController mController;
private boolean mRequestingConditions;
+ private Uri mExitConditionId;
+ private int mBucketIndex = -1;
+ private boolean mShowing;
public ZenModePanel(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
+ mFavorites = new Favorites();
mInflater = LayoutInflater.from(new ContextThemeWrapper(context, R.style.QSWhiteTheme));
+ updateTag();
+ if (DEBUG) Log.d(mTag, "new ZenModePanel");
+ }
+
+ private void updateTag() {
+ mTag = "ZenModePanel/" + mLogTag + "/" + Integer.toHexString(System.identityHashCode(this));
}
@Override
@@ -74,44 +100,97 @@ public class ZenModePanel extends LinearLayout {
}
@Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ if (DEBUG) Log.d(mTag, "onAttachedToWindow");
+ final ViewGroup p = (ViewGroup) getParent();
+ updateShowing(p != null && p.getVisibility() == VISIBLE);
+ }
+
+ @Override
+ protected void onDetachedFromWindow() {
+ super.onDetachedFromWindow();
+ if (DEBUG) Log.d(mTag, "onDetachedFromWindow");
+ updateShowing(false);
+ }
+
+ @Override
public void setVisibility(int visibility) {
super.setVisibility(visibility);
- setRequestingConditions(visibility == VISIBLE);
+ final boolean vis = visibility == VISIBLE;
+ updateShowing(isAttachedToWindow() && vis);
+ }
+
+ private void updateShowing(boolean showing) {
+ if (showing == mShowing) return;
+ mShowing = showing;
+ if (DEBUG) Log.d(mTag, "mShowing=" + mShowing);
+ if (mController != null) {
+ setRequestingConditions(mShowing);
+ }
}
/** Start or stop requesting relevant zen mode exit conditions */
private void setRequestingConditions(boolean requesting) {
if (mRequestingConditions == requesting) return;
+ if (DEBUG) Log.d(mTag, "setRequestingConditions " + requesting);
mRequestingConditions = requesting;
+ if (mController != null) {
+ mController.requestConditions(mRequestingConditions);
+ }
if (mRequestingConditions) {
- mController.addCallback(mZenCallback);
+ Condition timeCondition = parseExistingTimeCondition(mExitConditionId);
+ if (timeCondition != null) {
+ mBucketIndex = -1;
+ } else {
+ mBucketIndex = DEFAULT_BUCKET_INDEX;
+ timeCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ }
+ if (DEBUG) Log.d(mTag, "Initial bucket index: " + mBucketIndex);
+ bind(timeCondition, mConditions.getChildAt(0));
+ handleUpdateConditions(new Condition[0]);
} else {
- mController.removeCallback(mZenCallback);
+ mConditions.removeAllViews();
}
- mController.requestConditions(mRequestingConditions);
}
- public void init(ZenModeController controller) {
+ public void init(ZenModeController controller, char logTag) {
mController = controller;
+ mLogTag = logTag;
+ updateTag();
+ mExitConditionId = mController.getExitConditionId();
+ if (DEBUG) Log.d(mTag, "init mExitConditionId=" + mExitConditionId);
mConditions.removeAllViews();
- bind(updateTimeCondition(), mConditions.getChildAt(0));
- handleUpdateConditions(new Condition[0]);
+ mController.addCallback(mZenCallback);
+ if (mShowing) {
+ setRequestingConditions(true);
+ }
}
public void setCallback(Callback callback) {
mCallback = callback;
}
- private Condition updateTimeCondition() {
- final int minutes = MINUTES[mMinutesIndex];
- final long millis = System.currentTimeMillis() + minutes * 60 * 1000;
- final Uri id = new Uri.Builder().scheme(Condition.SCHEME).authority("android")
- .appendPath("countdown").appendPath(Long.toString(millis)).build();
- final int num = minutes < 60 ? minutes : minutes / 60;
+ private Condition parseExistingTimeCondition(Uri conditionId) {
+ final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
+ if (time == 0) return null;
+ final long span = time - System.currentTimeMillis();
+ if (span <= 0 || span > MAX_BUCKET_MINUTES * MINUTES_MS) return null;
+ return timeCondition(time, Math.round(span / (float)MINUTES_MS));
+ }
+
+ private Condition newTimeCondition(int minutesFromNow) {
+ final long now = System.currentTimeMillis();
+ return timeCondition(now + minutesFromNow * MINUTES_MS, minutesFromNow);
+ }
+
+ private Condition timeCondition(long time, int minutes) {
+ final int num = minutes < 60 ? minutes : Math.round(minutes / 60f);
final int resId = minutes < 60
? R.plurals.zen_mode_duration_minutes
: R.plurals.zen_mode_duration_hours;
final String caption = mContext.getResources().getQuantityString(resId, num, num);
+ final Uri id = ZenModeConfig.toCountdownConditionId(time);
return new Condition(id, caption, "", "", 0, Condition.STATE_TRUE,
Condition.FLAG_RELEVANT_NOW);
}
@@ -125,14 +204,40 @@ public class ZenModePanel extends LinearLayout {
bind(conditions[i], mConditions.getChildAt(i + 1));
}
bind(null, mConditions.getChildAt(newCount + 1));
+ checkForDefault();
+ }
+
+ private ConditionTag getConditionTagAt(int index) {
+ return (ConditionTag) mConditions.getChildAt(index).getTag();
+ }
+
+ private void checkForDefault() {
+ // are we left without anything selected? if so, set a default
+ for (int i = 0; i < mConditions.getChildCount(); i++) {
+ if (getConditionTagAt(i).rb.isChecked()) {
+ return;
+ }
+ }
+ if (DEBUG) Log.d(mTag, "Selecting a default");
+ final int favoriteIndex = mFavorites.getMinuteIndex();
+ if (favoriteIndex == -1) {
+ getConditionTagAt(mConditions.getChildCount() - 1).rb.setChecked(true);
+ } else {
+ final Condition c = newTimeCondition(MINUTE_BUCKETS[favoriteIndex]);
+ mBucketIndex = favoriteIndex;
+ bind(c, mConditions.getChildAt(0));
+ getConditionTagAt(0).rb.setChecked(true);
+ }
}
- private void editTimeCondition(int delta) {
- final int i = mMinutesIndex + delta;
- if (i < 0 || i >= MINUTES.length) return;
- mMinutesIndex = i;
- final Condition c = updateTimeCondition();
- bind(c, mConditions.getChildAt(0));
+ private void handleExitConditionChanged(Uri exitCondition) {
+ mExitConditionId = exitCondition;
+ if (DEBUG) Log.d(mTag, "handleExitConditionChanged " + mExitConditionId);
+ final int N = mConditions.getChildCount();
+ for (int i = 0; i < N; i++) {
+ final ConditionTag tag = getConditionTagAt(i);
+ tag.rb.setChecked(Objects.equals(tag.conditionId, exitCondition));
+ }
}
private void bind(final Condition condition, View convertView) {
@@ -140,23 +245,31 @@ public class ZenModePanel extends LinearLayout {
final View row;
if (convertView == null) {
row = mInflater.inflate(R.layout.zen_mode_condition, this, false);
+ if (DEBUG) Log.d(mTag, "Adding new condition view for: " + condition);
mConditions.addView(row);
} else {
row = convertView;
}
- final int position = mConditions.indexOfChild(row);
- final RadioButton rb = (RadioButton) row.findViewById(android.R.id.checkbox);
- mRadioButtons.add(rb);
- rb.setEnabled(enabled);
- rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
+ final ConditionTag tag =
+ row.getTag() != null ? (ConditionTag) row.getTag() : new ConditionTag();
+ row.setTag(tag);
+ if (tag.rb == null) {
+ tag.rb = (RadioButton) row.findViewById(android.R.id.checkbox);
+ }
+ tag.conditionId = condition != null ? condition.id : null;
+ tag.rb.setEnabled(enabled);
+ tag.rb.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
- if (isChecked) {
- for (RadioButton otherButton : mRadioButtons) {
- if (otherButton == rb) continue;
- otherButton.setChecked(false);
+ if (mShowing && isChecked) {
+ if (DEBUG) Log.d(mTag, "onCheckedChanged " + tag.conditionId);
+ final int N = mConditions.getChildCount();
+ for (int i = 0; i < N; i++) {
+ ConditionTag childTag = getConditionTagAt(i);
+ if (childTag == tag) continue;
+ childTag.rb.setChecked(false);
}
- mController.select(condition);
+ select(tag.conditionId);
fireInteraction();
}
}
@@ -173,9 +286,7 @@ public class ZenModePanel extends LinearLayout {
button1.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- rb.setChecked(true);
- editTimeCondition(-1);
- fireInteraction();
+ onClickTimeButton(row, tag, false /*down*/);
}
});
@@ -183,29 +294,83 @@ public class ZenModePanel extends LinearLayout {
button2.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- rb.setChecked(true);
- editTimeCondition(1);
- fireInteraction();
+ onClickTimeButton(row, tag, true /*up*/);
}
});
title.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- rb.setChecked(true);
+ tag.rb.setChecked(true);
fireInteraction();
}
});
- if (position == 0) {
- button1.setEnabled(mMinutesIndex > 0);
- button2.setEnabled(mMinutesIndex < MINUTES.length - 1);
- button1.setImageAlpha(button1.isEnabled() ? 0xff : 0x7f);
- button2.setImageAlpha(button2.isEnabled() ? 0xff : 0x7f);
+
+ final long time = ZenModeConfig.tryParseCountdownConditionId(tag.conditionId);
+ if (time > 0) {
+ if (mBucketIndex > -1) {
+ button1.setEnabled(mBucketIndex > 0);
+ button2.setEnabled(mBucketIndex < MINUTE_BUCKETS.length - 1);
+ } else {
+ final long span = time - System.currentTimeMillis();
+ button1.setEnabled(span > MIN_BUCKET_MINUTES * MINUTES_MS);
+ final Condition maxCondition = newTimeCondition(MAX_BUCKET_MINUTES);
+ button2.setEnabled(!Objects.equals(condition.summary, maxCondition.summary));
+ }
+
+ button1.setAlpha(button1.isEnabled() ? 1f : .5f);
+ button2.setAlpha(button2.isEnabled() ? 1f : .5f);
} else {
button1.setVisibility(View.GONE);
button2.setVisibility(View.GONE);
}
- if (position == 0 && mConditions.getChildCount() == 1) {
- rb.setChecked(true);
+ if (mExitConditionId != null && mExitConditionId.equals(tag.conditionId)) {
+ if (DEBUG) Log.d(mTag, "Auto-selecting row with mExitConditionId=" + mExitConditionId);
+ tag.rb.setChecked(true);
+ }
+ }
+
+ private void onClickTimeButton(View row, ConditionTag tag, boolean up) {
+ Condition newCondition = null;
+ final int N = MINUTE_BUCKETS.length;
+ if (mBucketIndex == -1) {
+ // not on a known index, search for the next or prev bucket by time
+ final long time = ZenModeConfig.tryParseCountdownConditionId(tag.conditionId);
+ final long now = System.currentTimeMillis();
+ for (int i = 0; i < N; i++) {
+ int j = up ? i : N - 1 - i;
+ final int bucketMinutes = MINUTE_BUCKETS[j];
+ final long bucketTime = now + bucketMinutes * MINUTES_MS;
+ if (up && bucketTime > time || !up && bucketTime < time) {
+ mBucketIndex = j;
+ newCondition = timeCondition(bucketTime, bucketMinutes);
+ break;
+ }
+ }
+ if (newCondition == null) {
+ mBucketIndex = DEFAULT_BUCKET_INDEX;
+ newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ }
+ } else {
+ // on a known index, simply increment or decrement
+ mBucketIndex = Math.max(0, Math.min(N - 1, mBucketIndex + (up ? 1 : -1)));
+ newCondition = newTimeCondition(MINUTE_BUCKETS[mBucketIndex]);
+ }
+ bind(newCondition, row);
+ tag.rb.setChecked(true);
+ select(newCondition.id);
+ fireInteraction();
+ }
+
+ private void select(Uri conditionId) {
+ if (DEBUG) Log.d(mTag, "select " + conditionId);
+ if (mController != null) {
+ mController.setExitConditionId(conditionId);
+ }
+ mExitConditionId = conditionId;
+ if (conditionId == null) {
+ mFavorites.setMinuteIndex(-1);
+ } else if (ZenModeConfig.isValidCountdownConditionId(conditionId) && mBucketIndex != -1) {
+ mFavorites.setMinuteIndex(mBucketIndex);
}
}
@@ -226,10 +391,16 @@ public class ZenModePanel extends LinearLayout {
public void onConditionsChanged(Condition[] conditions) {
mHandler.obtainMessage(H.UPDATE_CONDITIONS, conditions).sendToTarget();
}
+
+ @Override
+ public void onExitConditionChanged(Uri exitConditionId) {
+ mHandler.obtainMessage(H.EXIT_CONDITION_CHANGED, exitConditionId).sendToTarget();
+ }
};
private final class H extends Handler {
private static final int UPDATE_CONDITIONS = 1;
+ private static final int EXIT_CONDITION_CHANGED = 2;
private H() {
super(Looper.getMainLooper());
@@ -239,6 +410,8 @@ public class ZenModePanel extends LinearLayout {
public void handleMessage(Message msg) {
if (msg.what == UPDATE_CONDITIONS) {
handleUpdateConditions((Condition[])msg.obj);
+ } else if (msg.what == EXIT_CONDITION_CHANGED) {
+ handleExitConditionChanged((Uri)msg.obj);
}
}
}
@@ -247,4 +420,51 @@ public class ZenModePanel extends LinearLayout {
void onMoreSettings();
void onInteraction();
}
+
+ // used as the view tag on condition rows
+ private static class ConditionTag {
+ RadioButton rb;
+ Uri conditionId;
+ }
+
+ private final class Favorites implements OnSharedPreferenceChangeListener {
+ private static final String KEY_MINUTE_INDEX = "minuteIndex";
+
+ private int mMinuteIndex;
+
+ private Favorites() {
+ prefs().registerOnSharedPreferenceChangeListener(this);
+ updateMinuteIndex();
+ }
+
+ public int getMinuteIndex() {
+ return mMinuteIndex;
+ }
+
+ public void setMinuteIndex(int minuteIndex) {
+ minuteIndex = clamp(minuteIndex);
+ if (minuteIndex == mMinuteIndex) return;
+ mMinuteIndex = clamp(minuteIndex);
+ if (DEBUG) Log.d(mTag, "Setting favorite minute index: " + mMinuteIndex);
+ prefs().edit().putInt(KEY_MINUTE_INDEX, mMinuteIndex).apply();
+ }
+
+ @Override
+ public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
+ updateMinuteIndex();
+ }
+
+ private SharedPreferences prefs() {
+ return mContext.getSharedPreferences(ZenModePanel.class.getSimpleName(), 0);
+ }
+
+ private void updateMinuteIndex() {
+ mMinuteIndex = clamp(prefs().getInt(KEY_MINUTE_INDEX, DEFAULT_BUCKET_INDEX));
+ if (DEBUG) Log.d(mTag, "Favorite minute index: " + mMinuteIndex);
+ }
+
+ private int clamp(int index) {
+ return Math.max(-1, Math.min(MINUTE_BUCKETS.length - 1, index));
+ }
+ }
}
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 762d3df..0c16b78 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -35,6 +35,7 @@ import android.database.ContentObserver;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.net.ConnectivityManager;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
@@ -51,6 +52,7 @@ import android.service.dreams.IDreamManager;
import android.telephony.PhoneStateListener;
import android.telephony.ServiceState;
import android.telephony.TelephonyManager;
+import android.text.TextUtils;
import android.util.ArraySet;
import android.util.Log;
import android.util.TypedValue;
@@ -345,8 +347,8 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
}
private Action getBugReportAction() {
- return new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
- R.string.global_action_bug_report) {
+ return new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport,
+ R.string.bugreport_title) {
public void onPress() {
AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
@@ -383,6 +385,14 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
public boolean showBeforeProvisioning() {
return false;
}
+
+ @Override
+ public String getStatus() {
+ return mContext.getString(
+ com.android.internal.R.string.bugreport_status,
+ Build.VERSION.RELEASE,
+ Build.ID);
+ }
};
}
@@ -640,6 +650,10 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
return true;
}
+ public String getStatus() {
+ return null;
+ }
+
abstract public void onPress();
public View create(
@@ -649,7 +663,13 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
ImageView icon = (ImageView) v.findViewById(R.id.icon);
TextView messageView = (TextView) v.findViewById(R.id.message);
- v.findViewById(R.id.status).setVisibility(View.GONE);
+ TextView statusView = (TextView) v.findViewById(R.id.status);
+ final String status = getStatus();
+ if (!TextUtils.isEmpty(status)) {
+ statusView.setText(status);
+ } else {
+ statusView.setVisibility(View.GONE);
+ }
if (mIcon != null) {
icon.setImageDrawable(mIcon);
icon.setScaleType(ScaleType.CENTER_CROP);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 5dc9e58..a8645bc 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -46,6 +46,7 @@ import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
+import android.content.res.Resources.Theme;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
@@ -213,7 +214,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private int mTitleColor = 0;
private boolean mAlwaysReadCloseOnTouchAttr = false;
-
+
private ContextMenuBuilder mContextMenu;
private MenuDialogHelper mContextMenuHelper;
private boolean mClosingActionMenu;
@@ -475,7 +476,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (st.isPrepared) {
return true;
}
-
+
if ((mPreparedPanel != null) && (mPreparedPanel != st)) {
// Another Panel is prepared and possibly open, so close it
closePanel(mPreparedPanel, false);
@@ -528,7 +529,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return false;
}
-
+
st.refreshMenuContent = false;
}
@@ -620,7 +621,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// Causes the decor view to be recreated
st.refreshDecorView = true;
-
+
st.clearMenuPresenters();
}
@@ -872,7 +873,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
st.refreshMenuContent = true;
st.refreshDecorView = true;
-
+
// Prepare the options panel if we have an action bar
if ((featureId == FEATURE_ACTION_BAR || featureId == FEATURE_OPTIONS_PANEL)
&& mDecorContentParent != null) {
@@ -883,7 +884,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
}
-
+
/**
* Called when the panel key is pushed down.
* @param featureId The feature ID of the relevant panel (defaults to FEATURE_OPTIONS_PANEL}.
@@ -892,7 +893,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
*/
public final boolean onKeyDownPanel(int featureId, KeyEvent event) {
final int keyCode = event.getKeyCode();
-
+
if (event.getRepeatCount() == 0) {
// The panel key was pushed, so set the chording key
mPanelChordingKey = keyCode;
@@ -919,7 +920,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (event.isCanceled() || (mDecor != null && mDecor.mActionMode != null)) {
return;
}
-
+
boolean playSoundEffect = false;
final PanelFeatureState st = getPanelState(featureId, true);
if (featureId == FEATURE_OPTIONS_PANEL && mDecorContentParent != null &&
@@ -1159,22 +1160,40 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
protected boolean initializePanelMenu(final PanelFeatureState st) {
Context context = getContext();
- // If we have an action bar, initialize the menu with a context themed for it.
+ // If we have an action bar, initialize the menu with the right theme.
if ((st.featureId == FEATURE_OPTIONS_PANEL || st.featureId == FEATURE_ACTION_BAR) &&
mDecorContentParent != null) {
- TypedValue outValue = new TypedValue();
- Resources.Theme currentTheme = context.getTheme();
- currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
- outValue, true);
- final int targetThemeRes = outValue.resourceId;
+ final TypedValue outValue = new TypedValue();
+ final Theme baseTheme = context.getTheme();
+ baseTheme.resolveAttribute(com.android.internal.R.attr.actionBarTheme, outValue, true);
+
+ Theme widgetTheme = null;
+ if (outValue.resourceId != 0) {
+ widgetTheme = context.getResources().newTheme();
+ widgetTheme.setTo(baseTheme);
+ widgetTheme.applyStyle(outValue.resourceId, true);
+ widgetTheme.resolveAttribute(
+ com.android.internal.R.attr.actionBarWidgetTheme, outValue, true);
+ } else {
+ baseTheme.resolveAttribute(
+ com.android.internal.R.attr.actionBarWidgetTheme, outValue, true);
+ }
- if (targetThemeRes != 0 && context.getThemeResId() != targetThemeRes) {
- context = new ContextThemeWrapper(context, targetThemeRes);
+ if (outValue.resourceId != 0) {
+ if (widgetTheme == null) {
+ widgetTheme = context.getResources().newTheme();
+ widgetTheme.setTo(baseTheme);
+ }
+ widgetTheme.applyStyle(outValue.resourceId, true);
+ }
+
+ if (widgetTheme != null) {
+ context = new ContextThemeWrapper(context, 0);
+ context.getTheme().setTo(widgetTheme);
}
}
final MenuBuilder menu = new MenuBuilder(context);
-
menu.setCallback(this);
st.setMenu(menu);
@@ -1665,7 +1684,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mDecor != null ? mDecor.getKeyDispatcherState() : null;
//Log.i(TAG, "Key down: repeat=" + event.getRepeatCount()
// + " flags=0x" + Integer.toHexString(event.getFlags()));
-
+
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
@@ -1727,7 +1746,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
//Log.i(TAG, "Key up: repeat=" + event.getRepeatCount()
// + " flags=0x" + Integer.toHexString(event.getFlags()));
-
+
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_UP:
case KeyEvent.KEYCODE_VOLUME_DOWN:
@@ -2278,7 +2297,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
return;
}
-
+
// if we are showing a feature that should be announced and one child
// make this child the event source since this is the feature itself
// otherwise the callback will take over and announce its client
@@ -2829,13 +2848,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
hackTurnOffWindowResizeAnim(bg == null || bg.getOpacity()
!= PixelFormat.OPAQUE);
}
-
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
-
+
updateWindowResizeState();
-
+
final Callback cb = getCallback();
if (cb != null && !isDestroyed() && mFeatureId < 0) {
cb.onAttachedToWindow();
@@ -2856,7 +2875,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
-
+
final Callback cb = getCallback();
if (cb != null && mFeatureId < 0) {
cb.onDetachedFromWindow();
@@ -2890,19 +2909,19 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
public android.view.SurfaceHolder.Callback2 willYouTakeTheSurface() {
return mFeatureId < 0 ? mTakeSurfaceCallback : null;
}
-
+
public InputQueue.Callback willYouTakeTheInputQueue() {
return mFeatureId < 0 ? mTakeInputQueueCallback : null;
}
-
+
public void setSurfaceType(int type) {
PhoneWindow.this.setType(type);
}
-
+
public void setSurfaceFormat(int format) {
PhoneWindow.this.setFormat(format);
}
-
+
public void setSurfaceKeepScreenOn(boolean keepOn) {
if (keepOn) PhoneWindow.this.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
else PhoneWindow.this.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
@@ -3119,7 +3138,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
setCloseOnTouchOutsideIfNotSet(true);
}
}
-
+
WindowManager.LayoutParams params = getAttributes();
if (!hasSoftInputMode()) {
@@ -3419,9 +3438,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
private Drawable loadImageURI(Uri uri) {
try {
- final Context context = getContext();
- return Drawable.createFromStreamThemed(
- context.getContentResolver().openInputStream(uri), null, context.getTheme());
+ return Drawable.createFromStream(
+ getContext().getContentResolver().openInputStream(uri), null);
} catch (Exception e) {
Log.w(TAG, "Unable to open content: " + uri);
}
@@ -3898,11 +3916,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
boolean refreshDecorView;
boolean refreshMenuContent;
-
+
boolean wasLastOpen;
-
+
boolean wasLastExpanded;
-
+
/**
* Contains the state of the menu when told to freeze.
*/
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 0d39586..b883c5f 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -91,6 +91,7 @@ import android.view.ViewConfiguration;
import android.view.Window;
import android.view.WindowManager;
import android.view.WindowManagerGlobal;
+import android.view.WindowManagerInternal;
import android.view.WindowManagerPolicy;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -102,14 +103,17 @@ import com.android.internal.policy.IKeyguardService;
import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
+import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
import com.android.internal.statusbar.IStatusBarService;
import com.android.internal.telephony.ITelephony;
import com.android.internal.widget.PointerLocationView;
+import com.android.server.LocalServices;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
+import java.util.ArrayList;
import java.util.HashSet;
import static android.view.WindowManager.LayoutParams.*;
@@ -131,6 +135,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_INPUT = false;
static final boolean DEBUG_STARTING_WINDOW = false;
+ static final boolean DEBUG_WAKEUP = false;
static final boolean SHOW_STARTING_ANIMATIONS = true;
static final boolean SHOW_PROCESSES_ON_ALT_MENU = false;
@@ -223,6 +228,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Context mContext;
IWindowManager mWindowManager;
WindowManagerFuncs mWindowManagerFuncs;
+ WindowManagerInternal mWindowManagerInternal;
PowerManager mPowerManager;
IStatusBarService mStatusBarService;
boolean mPreloadedRecentApps;
@@ -264,6 +270,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int[] mNavigationBarWidthForRotation = new int[4];
KeyguardServiceDelegate mKeyguardDelegate;
+ // The following are only accessed on the mHandler thread.
+ boolean mKeyguardDrawComplete;
+ boolean mWindowManagerDrawComplete;
+ ArrayList<ScreenOnListener> mScreenOnListeners = new ArrayList<ScreenOnListener>();
+ final IRemoteCallback mWindowManagerDrawCallback = new IRemoteCallback.Stub() {
+ @Override
+ public void sendResult(Bundle data) {
+ if (DEBUG_WAKEUP) Slog.i(TAG, "All windows ready for display!");
+ mHandler.sendEmptyMessage(MSG_WINDOW_MANAGER_DRAWN_COMPLETE);
+ }
+ };
+ final ShowListener mKeyguardDelegateCallback = new ShowListener() {
+ @Override
+ public void onShown(IBinder windowToken) {
+ if (DEBUG_WAKEUP) Slog.d(TAG, "mKeyguardDelegate.ShowListener.onShown.");
+ mHandler.sendEmptyMessage(MSG_KEYGUARD_DRAWN_COMPLETE);
+ }
+ };
+
GlobalActions mGlobalActions;
volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
boolean mPendingPowerKeyUpCanceled;
@@ -486,6 +511,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_DISABLE_POINTER_LOCATION = 2;
private static final int MSG_DISPATCH_MEDIA_KEY_WITH_WAKE_LOCK = 3;
private static final int MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK = 4;
+ private static final int MSG_KEYGUARD_DRAWN_COMPLETE = 5;
+ private static final int MSG_KEYGUARD_DRAWN_TIMEOUT = 6;
+ private static final int MSG_WINDOW_MANAGER_DRAWN_COMPLETE = 7;
+ private static final int MSG_WAKING_UP = 8;
private class PolicyHandler extends Handler {
@Override
@@ -503,6 +532,25 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case MSG_DISPATCH_MEDIA_KEY_REPEAT_WITH_WAKE_LOCK:
dispatchMediaKeyRepeatWithWakeLock((KeyEvent)msg.obj);
break;
+ case MSG_KEYGUARD_DRAWN_COMPLETE:
+ if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mKeyguardDrawComplete");
+ mKeyguardDrawComplete = true;
+ finishScreenTurningOn();
+ break;
+ case MSG_KEYGUARD_DRAWN_TIMEOUT:
+ Slog.w(TAG, "Keyguard drawn timeout. Setting mKeyguardDrawComplete");
+ mKeyguardDrawComplete = true;
+ finishScreenTurningOn();
+ break;
+ case MSG_WINDOW_MANAGER_DRAWN_COMPLETE:
+ if (DEBUG_WAKEUP) Slog.w(TAG, "Setting mWindowManagerDrawComplete");
+ mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
+ mWindowManagerDrawComplete = true;
+ finishScreenTurningOn();
+ break;
+ case MSG_WAKING_UP:
+ handleWakingUp((ScreenOnListener) msg.obj);
+ break;
}
}
}
@@ -876,6 +924,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mContext = context;
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
+ mWindowManagerInternal = LocalServices.getService(WindowManagerInternal.class);
+
mHandler = new PolicyHandler();
mWakeGestureListener = new MyWakeGestureListener(mContext, mHandler);
mOrientationListener = new MyOrientationListener(mContext, mHandler);
@@ -3045,7 +3095,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
WindowState attached) {
// we've already done the status bar
- if (win == mStatusBar || win == mNavigationBar) {
+ if ((win == mStatusBar && !doesForceHide(attrs)) || win == mNavigationBar) {
return;
}
final boolean isDefaultDisplay = win.isDefaultDisplay();
@@ -3323,7 +3373,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
= mOverscanScreenTop + mOverscanScreenHeight;
} else if (canHideNavigationBar()
&& (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
- && (attrs.type == TYPE_TOAST
+ && (attrs.type == TYPE_STATUS_BAR
+ || attrs.type == TYPE_TOAST
|| (attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
&& attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
// Asking for layout as if the nav bar is hidden, lets the
@@ -4464,10 +4515,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void wakingUp(final ScreenOnListener screenOnListener) {
EventLog.writeEvent(70000, 1);
- if (false) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.i(TAG, "Screen turning on...", here);
+ if (DEBUG_WAKEUP) Slog.i(TAG, "Screen turning on...",
+ new RuntimeException("here").fillInStackTrace());
+ mHandler.obtainMessage(MSG_WAKING_UP, screenOnListener).sendToTarget();
+ }
+
+ // Called on the mHandler thread.
+ private void handleWakingUp(final ScreenOnListener screenOnListener) {
+ if (screenOnListener != null) {
+ mScreenOnListeners.add(screenOnListener);
}
synchronized (mLock) {
@@ -4477,51 +4533,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateLockScreenTimeout();
}
- waitForKeyguard(screenOnListener);
- }
-
- private void waitForKeyguard(final ScreenOnListener screenOnListener) {
+ mKeyguardDrawComplete = false;
+ mWindowManagerDrawComplete = false;
if (mKeyguardDelegate != null) {
- mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
- @Override
- public void onShown(IBinder windowToken) {
- waitForKeyguardWindowDrawn(windowToken, screenOnListener);
- }
- });
+ mHandler.removeMessages(MSG_KEYGUARD_DRAWN_TIMEOUT);
+ mHandler.sendEmptyMessageDelayed(MSG_KEYGUARD_DRAWN_TIMEOUT, 1000);
+ mKeyguardDelegate.onScreenTurnedOn(mKeyguardDelegateCallback);
} else {
- Slog.i(TAG, "No keyguard interface!");
- finishScreenTurningOn(screenOnListener);
+ if (DEBUG_WAKEUP) Slog.d(TAG, "null mKeyguardDelegate: setting mKeyguardDrawComplete.");
+ mKeyguardDrawComplete = true;
}
+ mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, 500);
}
- private void waitForKeyguardWindowDrawn(IBinder windowToken,
- final ScreenOnListener screenOnListener) {
- if (windowToken != null && !mHideLockScreen) {
- try {
- if (mWindowManager.waitForWindowDrawn(
- windowToken, new IRemoteCallback.Stub() {
- @Override
- public void sendResult(Bundle data) {
- Slog.i(TAG, "Lock screen displayed!");
- finishScreenTurningOn(screenOnListener);
- setKeyguardDrawn();
- }
- })) {
- return;
- }
- Slog.i(TAG, "No lock screen! waitForWindowDrawn false");
-
- } catch (RemoteException ex) {
- // Can't happen in system process.
- }
+ // Called on the mHandler thread.
+ private void finishScreenTurningOn() {
+ if (DEBUG_WAKEUP) Slog.d(TAG,
+ "finishScreenTurningOn: mKeyguardDrawComplete=" + mKeyguardDrawComplete
+ + " mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
+ if (!mKeyguardDrawComplete || !mWindowManagerDrawComplete) {
+ return;
}
- Slog.i(TAG, "No lock screen! windowToken=" + windowToken);
- finishScreenTurningOn(screenOnListener);
- setKeyguardDrawn();
- }
-
- private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
synchronized (mLock) {
mScreenOnFully = true;
}
@@ -4531,9 +4564,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} catch (RemoteException unhandled) {
}
- if (screenOnListener != null) {
- screenOnListener.onScreenOn();
+ for (int i = mScreenOnListeners.size() - 1; i >=0; --i) {
+ mScreenOnListeners.remove(i).onScreenOn();
}
+
+ setKeyguardDrawn();
}
@Override
@@ -4906,7 +4941,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
synchronized (mLock) {
mSystemBooted = true;
}
- waitForKeyguard(null);
+ wakingUp(null);
}
ProgressDialog mBootMsgDialog = null;
diff --git a/rs/java/android/renderscript/FieldPacker.java b/rs/java/android/renderscript/FieldPacker.java
index 723ab24..0e57232 100644
--- a/rs/java/android/renderscript/FieldPacker.java
+++ b/rs/java/android/renderscript/FieldPacker.java
@@ -231,10 +231,18 @@ public class FieldPacker {
public void addObj(BaseObj obj) {
if (obj != null) {
- // FIXME: this is fine for 32-bit but needs a path for 64-bit
- addI32((int)obj.getID(null));
+ if (RenderScript.sPointerSize == 8) {
+ addI64(obj.getID(null));
+ }
+ else {
+ addI32((int)obj.getID(null));
+ }
} else {
- addI32(0);
+ if (RenderScript.sPointerSize == 8) {
+ addI64(0);
+ } else {
+ addI32(0);
+ }
}
}
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 2222d2c..8cac22d 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -82,6 +82,12 @@ public class RenderScript {
*/
public static final long CREATE_FLAG_LOW_POWER = 0x0004;
+ /*
+ * Detect the bitness of the VM to allow FieldPacker to do the right thing.
+ */
+ static native int rsnSystemGetPointerSize();
+ static int sPointerSize;
+
static {
sInitialized = false;
if (!SystemProperties.getBoolean("config.disable_renderscript", false)) {
@@ -99,6 +105,7 @@ public class RenderScript {
System.loadLibrary("rs_jni");
_nInit();
sInitialized = true;
+ sPointerSize = rsnSystemGetPointerSize();
} catch (UnsatisfiedLinkError e) {
Log.e(LOG_TAG, "Error loading RS jni library: " + e);
throw new RSRuntimeException("Error loading RS jni library: " + e);
diff --git a/rs/java/android/renderscript/ScriptC.java b/rs/java/android/renderscript/ScriptC.java
index 9e76f52..3176e28 100644
--- a/rs/java/android/renderscript/ScriptC.java
+++ b/rs/java/android/renderscript/ScriptC.java
@@ -67,6 +67,26 @@ public class ScriptC extends Script {
}
/**
+ * Only intended for use by the generated derived classes.
+ *
+ * @param rs
+ * @hide
+ */
+ protected ScriptC(RenderScript rs, String resName, byte[] bitcode32, byte[] bitcode64) {
+ super(0, rs);
+ long id = 0;
+ if (RenderScript.sPointerSize == 4) {
+ id = internalStringCreate(rs, resName, bitcode32);
+ } else {
+ id = internalStringCreate(rs, resName, bitcode64);
+ }
+ if (id == 0) {
+ throw new RSRuntimeException("Loading of ScriptC script failed.");
+ }
+ setID(id);
+ }
+
+ /**
* Name of the file that holds the object cache.
*/
private static final String CACHE_PATH = "com.android.renderscript.cache";
@@ -113,4 +133,17 @@ public class ScriptC extends Script {
// Log.v(TAG, "Create script for resource = " + resName);
return rs.nScriptCCreate(resName, mCachePath, pgm, pgmLength);
}
+
+ private static synchronized long internalStringCreate(RenderScript rs, String resName, byte[] bitcode) {
+ // Create the RS cache path if we haven't done so already.
+ if (mCachePath == null) {
+ File f = new File(rs.mCacheDir, CACHE_PATH);
+ mCachePath = f.getAbsolutePath();
+ f.mkdirs();
+ }
+ // Log.v(TAG, "Create script for resource = " + resName);
+ return rs.nScriptCCreate(resName, mCachePath, bitcode, bitcode.length);
+ }
+
+
}
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 18a2e31..ae39b05 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -1573,6 +1573,12 @@ nMeshGetIndices(JNIEnv *_env, jobject _this, jlong con, jlong mesh, jlongArray _
free(prims);
}
+static jint
+nSystemGetPointerSize(JNIEnv *_env, jobject _this) {
+ return (jint)sizeof(void*);
+}
+
+
// ---------------------------------------------------------------------------
@@ -1708,6 +1714,7 @@ static JNINativeMethod methods[] = {
{"rsnMeshGetVertices", "(JJ[JI)V", (void*)nMeshGetVertices },
{"rsnMeshGetIndices", "(JJ[J[II)V", (void*)nMeshGetIndices },
+{"rsnSystemGetPointerSize", "()I", (void*)nSystemGetPointerSize },
};
static int registerFuncs(JNIEnv *_env)
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 0082b1e..14c15a7 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -26,6 +26,7 @@ import android.app.PendingIntent;
import android.app.backup.BackupAgent;
import android.app.backup.BackupDataInput;
import android.app.backup.BackupDataOutput;
+import android.app.backup.BackupTransport;
import android.app.backup.FullBackup;
import android.app.backup.RestoreSet;
import android.app.backup.IBackupManager;
@@ -82,7 +83,6 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.StringBuilderPrinter;
-import com.android.internal.backup.BackupConstants;
import com.android.internal.backup.IBackupTransport;
import com.android.internal.backup.IObbBackupService;
import com.android.server.AppWidgetBackupBridge;
@@ -2098,7 +2098,7 @@ public class BackupManagerService extends IBackupManager.Stub {
}
mAgentBinder = null;
- mStatus = BackupConstants.TRANSPORT_OK;
+ mStatus = BackupTransport.TRANSPORT_OK;
// Sanity check: if the queue is empty we have no work to do.
if (mOriginalQueue.isEmpty()) {
@@ -2121,14 +2121,14 @@ public class BackupManagerService extends IBackupManager.Stub {
EventLog.writeEvent(EventLogTags.BACKUP_START, transportName);
// If we haven't stored package manager metadata yet, we must init the transport.
- if (mStatus == BackupConstants.TRANSPORT_OK && pmState.length() <= 0) {
+ if (mStatus == BackupTransport.TRANSPORT_OK && pmState.length() <= 0) {
Slog.i(TAG, "Initializing (wiping) backup state and transport storage");
addBackupTrace("initializing transport " + transportName);
resetBackupState(mStateDir); // Just to make sure.
mStatus = mTransport.initializeDevice();
addBackupTrace("transport.initializeDevice() == " + mStatus);
- if (mStatus == BackupConstants.TRANSPORT_OK) {
+ if (mStatus == BackupTransport.TRANSPORT_OK) {
EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
} else {
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, "(initialize)");
@@ -2141,7 +2141,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// directly and use a synthetic BackupRequest. We always run this pass
// because it's cheap and this way we guarantee that we don't get out of
// step even if we're selecting among various transports at run time.
- if (mStatus == BackupConstants.TRANSPORT_OK) {
+ if (mStatus == BackupTransport.TRANSPORT_OK) {
PackageManagerBackupAgent pmAgent = new PackageManagerBackupAgent(
mPackageManager, allAgentPackages());
mStatus = invokeAgentForBackup(PACKAGE_MANAGER_SENTINEL,
@@ -2149,7 +2149,7 @@ public class BackupManagerService extends IBackupManager.Stub {
addBackupTrace("PMBA invoke: " + mStatus);
}
- if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
+ if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
// The backend reports that our dataset has been wiped. Note this in
// the event log; the no-success code below will reset the backup
// state as well.
@@ -2158,13 +2158,13 @@ public class BackupManagerService extends IBackupManager.Stub {
} catch (Exception e) {
Slog.e(TAG, "Error in backup thread", e);
addBackupTrace("Exception in backup thread: " + e);
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
} finally {
// If we've succeeded so far, invokeAgentForBackup() will have run the PM
// metadata and its completion/timeout callback will continue the state
// machine chain. If it failed that won't happen; we handle that now.
addBackupTrace("exiting prelim: " + mStatus);
- if (mStatus != BackupConstants.TRANSPORT_OK) {
+ if (mStatus != BackupTransport.TRANSPORT_OK) {
// if things went wrong at this point, we need to
// restage everything and try again later.
resetBackupState(mStateDir); // Just to make sure.
@@ -2176,7 +2176,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// Transport has been initialized and the PM metadata submitted successfully
// if that was warranted. Now we process the single next thing in the queue.
void invokeNextAgent() {
- mStatus = BackupConstants.TRANSPORT_OK;
+ mStatus = BackupTransport.TRANSPORT_OK;
addBackupTrace("invoke q=" + mQueue.size());
// Sanity check that we have work to do. If not, skip to the end where
@@ -2236,39 +2236,39 @@ public class BackupManagerService extends IBackupManager.Stub {
// done here as long as we're successful so far.
} else {
// Timeout waiting for the agent
- mStatus = BackupConstants.AGENT_ERROR;
+ mStatus = BackupTransport.AGENT_ERROR;
}
} catch (SecurityException ex) {
// Try for the next one.
Slog.d(TAG, "error in bind/backup", ex);
- mStatus = BackupConstants.AGENT_ERROR;
+ mStatus = BackupTransport.AGENT_ERROR;
addBackupTrace("agent SE");
}
} catch (NameNotFoundException e) {
Slog.d(TAG, "Package does not exist; skipping");
addBackupTrace("no such package");
- mStatus = BackupConstants.AGENT_UNKNOWN;
+ mStatus = BackupTransport.AGENT_UNKNOWN;
} finally {
mWakelock.setWorkSource(null);
// If there was an agent error, no timeout/completion handling will occur.
// That means we need to direct to the next state ourselves.
- if (mStatus != BackupConstants.TRANSPORT_OK) {
+ if (mStatus != BackupTransport.TRANSPORT_OK) {
BackupState nextState = BackupState.RUNNING_QUEUE;
mAgentBinder = null;
// An agent-level failure means we reenqueue this one agent for
// a later retry, but otherwise proceed normally.
- if (mStatus == BackupConstants.AGENT_ERROR) {
+ if (mStatus == BackupTransport.AGENT_ERROR) {
if (MORE_DEBUG) Slog.i(TAG, "Agent failure for " + request.packageName
+ " - restaging");
dataChangedImpl(request.packageName);
- mStatus = BackupConstants.TRANSPORT_OK;
+ mStatus = BackupTransport.TRANSPORT_OK;
if (mQueue.isEmpty()) nextState = BackupState.FINAL;
- } else if (mStatus == BackupConstants.AGENT_UNKNOWN) {
+ } else if (mStatus == BackupTransport.AGENT_UNKNOWN) {
// Failed lookup of the app, so we couldn't bring up an agent, but
// we're otherwise fine. Just drop it and go on to the next as usual.
- mStatus = BackupConstants.TRANSPORT_OK;
+ mStatus = BackupTransport.TRANSPORT_OK;
} else {
// Transport-level failure means we reenqueue everything
revertAndEndBackup();
@@ -2297,7 +2297,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// If everything actually went through and this is the first time we've
// done a backup, we can now record what the current backup dataset token
// is.
- if ((mCurrentToken == 0) && (mStatus == BackupConstants.TRANSPORT_OK)) {
+ if ((mCurrentToken == 0) && (mStatus == BackupTransport.TRANSPORT_OK)) {
addBackupTrace("success; recording token");
try {
mCurrentToken = mTransport.getCurrentRestoreSet();
@@ -2314,7 +2314,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// state machine sequence and the wakelock is refcounted.
synchronized (mQueueLock) {
mBackupRunning = false;
- if (mStatus == BackupConstants.TRANSPORT_NOT_INITIALIZED) {
+ if (mStatus == BackupTransport.TRANSPORT_NOT_INITIALIZED) {
// Make sure we back up everything and perform the one-time init
clearMetadata();
if (DEBUG) Slog.d(TAG, "Server requires init; rerunning");
@@ -2395,7 +2395,7 @@ public class BackupManagerService extends IBackupManager.Stub {
EventLog.writeEvent(EventLogTags.BACKUP_AGENT_FAILURE, packageName,
e.toString());
agentErrorCleanup();
- return BackupConstants.AGENT_ERROR;
+ return BackupTransport.AGENT_ERROR;
}
// At this point the agent is off and running. The next thing to happen will
@@ -2403,7 +2403,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// for transport, or a timeout. Either way the next phase will happen in
// response to the TimeoutHandler interface callbacks.
addBackupTrace("invoke success");
- return BackupConstants.TRANSPORT_OK;
+ return BackupTransport.TRANSPORT_OK;
}
public void failAgent(IBackupAgent agent, String message) {
@@ -2484,11 +2484,11 @@ public class BackupManagerService extends IBackupManager.Stub {
addBackupTrace("operation complete");
ParcelFileDescriptor backupData = null;
- mStatus = BackupConstants.TRANSPORT_OK;
+ mStatus = BackupTransport.TRANSPORT_OK;
try {
int size = (int) mBackupDataName.length();
if (size > 0) {
- if (mStatus == BackupConstants.TRANSPORT_OK) {
+ if (mStatus == BackupTransport.TRANSPORT_OK) {
backupData = ParcelFileDescriptor.open(mBackupDataName,
ParcelFileDescriptor.MODE_READ_ONLY);
addBackupTrace("sending data to transport");
@@ -2501,7 +2501,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// renaming *all* the output state files (see below) until that happens.
addBackupTrace("data delivered: " + mStatus);
- if (mStatus == BackupConstants.TRANSPORT_OK) {
+ if (mStatus == BackupTransport.TRANSPORT_OK) {
addBackupTrace("finishing op on transport");
mStatus = mTransport.finishBackup();
addBackupTrace("finished: " + mStatus);
@@ -2514,7 +2514,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// After successful transport, delete the now-stale data
// and juggle the files so that next time we supply the agent
// with the new state file it just created.
- if (mStatus == BackupConstants.TRANSPORT_OK) {
+ if (mStatus == BackupTransport.TRANSPORT_OK) {
mBackupDataName.delete();
mNewStateName.renameTo(mSavedStateName);
EventLog.writeEvent(EventLogTags.BACKUP_PACKAGE, pkgName, size);
@@ -2525,7 +2525,7 @@ public class BackupManagerService extends IBackupManager.Stub {
} catch (Exception e) {
Slog.e(TAG, "Transport error backing up " + pkgName, e);
EventLog.writeEvent(EventLogTags.BACKUP_TRANSPORT_FAILURE, pkgName);
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
} finally {
try { if (backupData != null) backupData.close(); } catch (IOException e) {}
}
@@ -2533,7 +2533,7 @@ public class BackupManagerService extends IBackupManager.Stub {
// If we encountered an error here it's a transport-level failure. That
// means we need to halt everything and reschedule everything for next time.
final BackupState nextState;
- if (mStatus != BackupConstants.TRANSPORT_OK) {
+ if (mStatus != BackupTransport.TRANSPORT_OK) {
revertAndEndBackup();
nextState = BackupState.FINAL;
} else {
@@ -4847,7 +4847,7 @@ public class BackupManagerService extends IBackupManager.Stub {
mBackupHandler.removeMessages(MSG_RESTORE_TIMEOUT);
// Assume error until we successfully init everything
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
try {
// TODO: Log this before getAvailableRestoreSets, somehow
@@ -4902,7 +4902,7 @@ public class BackupManagerService extends IBackupManager.Stub {
return;
}
- mStatus = BackupConstants.TRANSPORT_OK;
+ mStatus = BackupTransport.TRANSPORT_OK;
executeNextState(RestoreState.DOWNLOAD_DATA);
}
@@ -4917,7 +4917,7 @@ public class BackupManagerService extends IBackupManager.Stub {
try {
mStatus = mTransport.startRestore(mToken,
mRestorePackages.toArray(new PackageInfo[0]));
- if (mStatus != BackupConstants.TRANSPORT_OK) {
+ if (mStatus != BackupTransport.TRANSPORT_OK) {
Slog.e(TAG, "Error starting restore operation");
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
executeNextState(RestoreState.FINAL);
@@ -4926,7 +4926,7 @@ public class BackupManagerService extends IBackupManager.Stub {
} catch (RemoteException e) {
Slog.e(TAG, "Error communicating with transport for restore");
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
executeNextState(RestoreState.FINAL);
return;
}
@@ -4941,14 +4941,14 @@ public class BackupManagerService extends IBackupManager.Stub {
if (packageName == null) {
Slog.e(TAG, "Error getting first restore package");
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
executeNextState(RestoreState.FINAL);
return;
} else if (packageName.equals("")) {
Slog.i(TAG, "No restore data available");
int millis = (int) (SystemClock.elapsedRealtime() - mStartRealtime);
EventLog.writeEvent(EventLogTags.RESTORE_SUCCESS, 0, millis);
- mStatus = BackupConstants.TRANSPORT_OK;
+ mStatus = BackupTransport.TRANSPORT_OK;
executeNextState(RestoreState.FINAL);
return;
} else if (!packageName.equals(PACKAGE_MANAGER_SENTINEL)) {
@@ -4979,7 +4979,7 @@ public class BackupManagerService extends IBackupManager.Stub {
Slog.e(TAG, "No restore metadata available, so not restoring settings");
EventLog.writeEvent(EventLogTags.RESTORE_AGENT_FAILURE, PACKAGE_MANAGER_SENTINEL,
"Package manager restore metadata missing");
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
executeNextState(RestoreState.FINAL);
return;
@@ -4987,7 +4987,7 @@ public class BackupManagerService extends IBackupManager.Stub {
} catch (RemoteException e) {
Slog.e(TAG, "Error communicating with transport for restore");
EventLog.writeEvent(EventLogTags.RESTORE_TRANSPORT_FAILURE);
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
mBackupHandler.removeMessages(MSG_BACKUP_RESTORE_STEP, this);
executeNextState(RestoreState.FINAL);
return;
@@ -5118,7 +5118,7 @@ public class BackupManagerService extends IBackupManager.Stub {
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to fetch restore data from transport");
- mStatus = BackupConstants.TRANSPORT_ERROR;
+ mStatus = BackupTransport.TRANSPORT_ERROR;
executeNextState(RestoreState.FINAL);
}
}
@@ -5206,7 +5206,7 @@ public class BackupManagerService extends IBackupManager.Stub {
Slog.e(TAG, "SElinux restorecon failed for " + downloadFile);
}
- if (mTransport.getRestoreData(stage) != BackupConstants.TRANSPORT_OK) {
+ if (mTransport.getRestoreData(stage) != BackupTransport.TRANSPORT_OK) {
// Transport-level failure, so we wind everything up and
// terminate the restore operation.
Slog.e(TAG, "Error getting restore data for " + packageName);
@@ -5450,12 +5450,12 @@ public class BackupManagerService extends IBackupManager.Stub {
long startRealtime = SystemClock.elapsedRealtime();
int status = transport.initializeDevice();
- if (status == BackupConstants.TRANSPORT_OK) {
+ if (status == BackupTransport.TRANSPORT_OK) {
status = transport.finishBackup();
}
// Okay, the wipe really happened. Clean up our local bookkeeping.
- if (status == BackupConstants.TRANSPORT_OK) {
+ if (status == BackupTransport.TRANSPORT_OK) {
Slog.i(TAG, "Device init successful");
int millis = (int) (SystemClock.elapsedRealtime() - startRealtime);
EventLog.writeEvent(EventLogTags.BACKUP_INITIALIZE);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index d7a19ad..bd45761 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -38,7 +38,6 @@ import static android.net.ConnectivityManager.TYPE_WIMAX;
import static android.net.ConnectivityManager.TYPE_PROXY;
import static android.net.ConnectivityManager.getNetworkTypeName;
import static android.net.ConnectivityManager.isNetworkTypeValid;
-import static android.net.ConnectivityServiceProtocol.NetworkFactoryProtocol;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
@@ -80,6 +79,7 @@ import android.net.NetworkCapabilities;
import android.net.NetworkConfig;
import android.net.NetworkInfo;
import android.net.NetworkInfo.DetailedState;
+import android.net.NetworkFactory;
import android.net.NetworkQuotaInfo;
import android.net.NetworkRequest;
import android.net.NetworkState;
@@ -258,17 +258,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
*/
private NetworkStateTracker mNetTrackers[];
- /**
- * Holds references to all NetworkAgentInfos claiming to support the legacy
- * NetworkType. We used to have a static set of of NetworkStateTrackers
- * for each network type. This is the new model.
- * Supports synchronous inspection of state.
- * These are built out at startup such that an unsupported network
- * doesn't get an ArrayList instance, making this a tristate:
- * unsupported, supported but not active and active.
- */
- private ArrayList<NetworkAgentInfo> mNetworkAgentInfoForType[];
-
/* Handles captive portal check on a network */
private CaptivePortalTracker mCaptivePortalTracker;
@@ -516,6 +505,118 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private static final int UID_UNUSED = -1;
+ /**
+ * Implements support for the legacy "one network per network type" model.
+ *
+ * We used to have a static array of NetworkStateTrackers, one for each
+ * network type, but that doesn't work any more now that we can have,
+ * for example, more that one wifi network. This class stores all the
+ * NetworkAgentInfo objects that support a given type, but the legacy
+ * API will only see the first one.
+ *
+ * It serves two main purposes:
+ *
+ * 1. Provide information about "the network for a given type" (since this
+ * API only supports one).
+ * 2. Send legacy connectivity change broadcasts. Broadcasts are sent if
+ * the first network for a given type changes, or if the default network
+ * changes.
+ */
+ private class LegacyTypeTracker {
+ /**
+ * Array of lists, one per legacy network type (e.g., TYPE_MOBILE_MMS).
+ * Each list holds references to all NetworkAgentInfos that are used to
+ * satisfy requests for that network type.
+ *
+ * This array is built out at startup such that an unsupported network
+ * doesn't get an ArrayList instance, making this a tristate:
+ * unsupported, supported but not active and active.
+ *
+ * The actual lists are populated when we scan the network types that
+ * are supported on this device.
+ */
+ private ArrayList<NetworkAgentInfo> mTypeLists[];
+
+ public LegacyTypeTracker() {
+ mTypeLists = (ArrayList<NetworkAgentInfo>[])
+ new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
+ }
+
+ public void addSupportedType(int type) {
+ if (mTypeLists[type] != null) {
+ throw new IllegalStateException(
+ "legacy list for type " + type + "already initialized");
+ }
+ mTypeLists[type] = new ArrayList<NetworkAgentInfo>();
+ }
+
+ private boolean isDefaultNetwork(NetworkAgentInfo nai) {
+ return mNetworkForRequestId.get(mDefaultRequest.requestId) == nai;
+ }
+
+ public boolean isTypeSupported(int type) {
+ return isNetworkTypeValid(type) && mTypeLists[type] != null;
+ }
+
+ public NetworkAgentInfo getNetworkForType(int type) {
+ if (isTypeSupported(type) && !mTypeLists[type].isEmpty()) {
+ return mTypeLists[type].get(0);
+ } else {
+ return null;
+ }
+ }
+
+ public void add(int type, NetworkAgentInfo nai) {
+ if (!isTypeSupported(type)) {
+ return; // Invalid network type.
+ }
+ if (VDBG) log("Adding agent " + nai + " for legacy network type " + type);
+
+ ArrayList<NetworkAgentInfo> list = mTypeLists[type];
+ if (list.contains(nai)) {
+ loge("Attempting to register duplicate agent for type " + type + ": " + nai);
+ return;
+ }
+
+ if (list.isEmpty() || isDefaultNetwork(nai)) {
+ if (VDBG) log("Sending connected broadcast for type " + type +
+ "isDefaultNetwork=" + isDefaultNetwork(nai));
+ sendLegacyNetworkBroadcast(nai, true, type);
+ }
+ list.add(nai);
+ }
+
+ public void remove(NetworkAgentInfo nai) {
+ if (VDBG) log("Removing agent " + nai);
+ for (int type = 0; type < mTypeLists.length; type++) {
+ ArrayList<NetworkAgentInfo> list = mTypeLists[type];
+ if (list == null || list.isEmpty()) {
+ continue;
+ }
+
+ boolean wasFirstNetwork = false;
+ if (list.get(0).equals(nai)) {
+ // This network was the first in the list. Send broadcast.
+ wasFirstNetwork = true;
+ }
+ list.remove(nai);
+
+ if (wasFirstNetwork || isDefaultNetwork(nai)) {
+ if (VDBG) log("Sending disconnected broadcast for type " + type +
+ "isDefaultNetwork=" + isDefaultNetwork(nai));
+ sendLegacyNetworkBroadcast(nai, false, type);
+ }
+
+ if (!list.isEmpty() && wasFirstNetwork) {
+ if (VDBG) log("Other network available for type " + type +
+ ", sending connected broadcast");
+ sendLegacyNetworkBroadcast(list.get(0), false, type);
+ }
+ }
+ }
+ }
+ private LegacyTypeTracker mLegacyTypeTracker = new LegacyTypeTracker();
+
public ConnectivityService(Context context, INetworkManagementService netd,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
// Currently, omitting a NetworkFactory will create one internally
@@ -531,7 +632,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
NetworkCapabilities netCap = new NetworkCapabilities();
netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
netCap.addNetworkCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED);
- mDefaultRequest = new NetworkRequest(netCap, true, nextNetworkRequestId());
+ mDefaultRequest = new NetworkRequest(netCap, TYPE_NONE, nextNetworkRequestId());
NetworkRequestInfo nri = new NetworkRequestInfo(null, mDefaultRequest, new Binder(),
NetworkRequestInfo.REQUEST);
mNetworkRequests.put(mDefaultRequest, nri);
@@ -587,9 +688,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mNetTransitionWakeLockTimeout = mContext.getResources().getInteger(
com.android.internal.R.integer.config_networkTransitionTimeout);
- mNetworkAgentInfoForType = (ArrayList<NetworkAgentInfo>[])
- new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE + 1];
-
mNetTrackers = new NetworkStateTracker[
ConnectivityManager.MAX_NETWORK_TYPE+1];
mCurrentLinkProperties = new LinkProperties[ConnectivityManager.MAX_NETWORK_TYPE+1];
@@ -644,7 +742,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
"radio " + n.radio + " in network type " + n.type);
continue;
}
- mNetworkAgentInfoForType[n.type] = new ArrayList<NetworkAgentInfo>();
+ mLegacyTypeTracker.addSupportedType(n.type);
mNetConfigs[n.type] = n;
mNetworksDefined++;
@@ -1656,31 +1754,34 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (DBG) log("requestRouteToHostAddress on invalid network: " + networkType);
return false;
}
- NetworkStateTracker tracker = mNetTrackers[networkType];
- DetailedState netState = DetailedState.DISCONNECTED;
- if (tracker != null) {
- netState = tracker.getNetworkInfo().getDetailedState();
+
+ NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+ if (nai == null) {
+ if (mLegacyTypeTracker.isTypeSupported(networkType) == false) {
+ if (DBG) log("requestRouteToHostAddress on unsupported network: " + networkType);
+ } else {
+ if (DBG) log("requestRouteToHostAddress on down network: " + networkType);
+ }
+ return false;
}
+ DetailedState netState = nai.networkInfo.getDetailedState();
+
if ((netState != DetailedState.CONNECTED &&
- netState != DetailedState.CAPTIVE_PORTAL_CHECK) ||
- tracker.isTeardownRequested()) {
+ netState != DetailedState.CAPTIVE_PORTAL_CHECK)) {
if (VDBG) {
log("requestRouteToHostAddress on down network "
+ "(" + networkType + ") - dropped"
- + " tracker=" + tracker
- + " netState=" + netState
- + " isTeardownRequested="
- + ((tracker != null) ? tracker.isTeardownRequested() : "tracker:null"));
+ + " netState=" + netState);
}
return false;
}
final int uid = Binder.getCallingUid();
final long token = Binder.clearCallingIdentity();
try {
- LinkProperties lp = tracker.getLinkProperties();
+ LinkProperties lp = nai.linkProperties;
boolean ok = modifyRouteToAddress(lp, addr, ADD, TO_DEFAULT_TABLE, exempt,
- tracker.getNetwork().netId, uid);
+ nai.network.netId, uid);
if (DBG) log("requestRouteToHostAddress ok=" + ok);
return ok;
} finally {
@@ -2843,7 +2944,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
- private int getRestoreDefaultNetworkDelay(int networkType) {
+ @Override
+ public int getRestoreDefaultNetworkDelay(int networkType) {
String restoreDefaultNetworkDelayStr = SystemProperties.get(
NETWORK_RESTORE_DELAY_PROP_NAME);
if(restoreDefaultNetworkDelayStr != null &&
@@ -2994,6 +3096,16 @@ public class ConnectivityService extends IConnectivityManager.Stub {
updateNetworkInfo(nai, info);
break;
}
+ case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
+ NetworkAgentInfo nai = mNetworkAgentInfos.get(msg.replyTo);
+ if (nai == null) {
+ loge("EVENT_NETWORK_SCORE_CHANGED from unknown NetworkAgent");
+ break;
+ }
+ Integer score = (Integer) msg.obj;
+ if (score != null) updateNetworkScore(nai, score.intValue());
+ break;
+ }
case NetworkMonitor.EVENT_NETWORK_VALIDATED: {
NetworkAgentInfo nai = (NetworkAgentInfo)msg.obj;
handleConnectionValidated(nai);
@@ -3098,7 +3210,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
for (NetworkRequestInfo nri : mNetworkRequests.values()) {
if (nri.isRequest == false) continue;
NetworkAgentInfo nai = mNetworkForRequestId.get(nri.request.requestId);
- ac.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK,
+ ac.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK,
(nai != null ? nai.currentScore : 0), 0, nri.request);
}
} else {
@@ -3114,11 +3226,9 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} else {
loge("Error connecting NetworkAgent");
NetworkAgentInfo nai = mNetworkAgentInfos.remove(msg.replyTo);
- try {
- mNetworkAgentInfoForType[nai.networkInfo.getType()].remove(nai);
- } catch (NullPointerException e) {}
if (nai != null) {
mNetworkForNetId.remove(nai.network.netId);
+ mLegacyTypeTracker.remove(nai);
}
}
}
@@ -3137,14 +3247,19 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} catch (Exception e) {
loge("Exception removing network: " + e);
}
+ // TODO - if we move the logic to the network agent (have them disconnect
+ // because they lost all their requests or because their score isn't good)
+ // then they would disconnect organically, report their new state and then
+ // disconnect the channel.
+ if (nai.networkInfo.isConnected()) {
+ nai.networkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED,
+ null, null);
+ }
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_LOST);
nai.networkMonitor.sendMessage(NetworkMonitor.CMD_NETWORK_DISCONNECTED);
mNetworkAgentInfos.remove(msg.replyTo);
updateClat(null, nai.linkProperties, nai);
- try {
- mNetworkAgentInfoForType[nai.networkInfo.getType()].remove(nai);
- } catch (NullPointerException e) {}
-
+ mLegacyTypeTracker.remove(nai);
mNetworkForNetId.remove(nai.network.netId);
// Since we've lost the network, go through all the requests that
// it was satisfying and see if any other factory can satisfy them.
@@ -3154,7 +3269,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
NetworkAgentInfo currentNetwork = mNetworkForRequestId.get(request.requestId);
if (VDBG) {
log(" checking request " + request + ", currentNetwork = " +
- currentNetwork != null ? currentNetwork.name() : "null");
+ (currentNetwork != null ? currentNetwork.name() : "null"));
}
if (currentNetwork != null && currentNetwork.network.netId == nai.network.netId) {
mNetworkForRequestId.remove(request.requestId);
@@ -3203,7 +3318,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
if (bestNetwork != null) {
if (VDBG) log("using " + bestNetwork.name());
- bestNetwork.networkRequests.put(nri.request.requestId, nri.request);
+ bestNetwork.addRequest(nri.request);
+ mNetworkForRequestId.put(nri.request.requestId, bestNetwork);
+ int legacyType = nri.request.legacyType;
+ if (legacyType != TYPE_NONE) {
+ mLegacyTypeTracker.add(legacyType, bestNetwork);
+ }
notifyNetworkCallback(bestNetwork, nri);
score = bestNetwork.currentScore;
}
@@ -3211,7 +3331,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (msg.what == EVENT_REGISTER_NETWORK_REQUEST) {
if (DBG) log("sending new NetworkRequest to factories");
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, nri.request);
+ nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score,
+ 0, nri.request);
}
}
}
@@ -3233,7 +3354,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (nri.isRequest) {
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_CANCEL_REQUEST, nri.request);
+ nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_CANCEL_REQUEST,
+ nri.request);
}
if (affectedNetwork != null) {
@@ -5279,7 +5401,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
@Override
public NetworkRequest requestNetwork(NetworkCapabilities networkCapabilities,
- Messenger messenger, int timeoutSec, IBinder binder) {
+ Messenger messenger, int timeoutSec, IBinder binder, int legacyType) {
if (networkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
== false) {
enforceConnectivityInternalPermission();
@@ -5291,7 +5413,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
throw new IllegalArgumentException("Bad timeout specified");
}
NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
- networkCapabilities), false, nextNetworkRequestId());
+ networkCapabilities), legacyType, nextNetworkRequestId());
if (DBG) log("requestNetwork for " + networkRequest);
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
NetworkRequestInfo.REQUEST);
@@ -5317,7 +5439,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
enforceAccessPermission();
NetworkRequest networkRequest = new NetworkRequest(new NetworkCapabilities(
- networkCapabilities), false, nextNetworkRequestId());
+ networkCapabilities), TYPE_NONE, nextNetworkRequestId());
if (DBG) log("listenForNetwork for " + networkRequest);
NetworkRequestInfo nri = new NetworkRequestInfo(messenger, networkRequest, binder,
NetworkRequestInfo.LISTEN);
@@ -5392,18 +5514,13 @@ public class ConnectivityService extends IConnectivityManager.Stub {
NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(), nextNetId(),
new NetworkInfo(networkInfo), new LinkProperties(linkProperties),
new NetworkCapabilities(networkCapabilities), currentScore, mContext, mTrackerHandler);
-
+ if (VDBG) log("registerNetworkAgent " + nai);
mHandler.sendMessage(mHandler.obtainMessage(EVENT_REGISTER_NETWORK_AGENT, nai));
}
private void handleRegisterNetworkAgent(NetworkAgentInfo na) {
if (VDBG) log("Got NetworkAgent Messenger");
mNetworkAgentInfos.put(na.messenger, na);
- try {
- mNetworkAgentInfoForType[na.networkInfo.getType()].add(na);
- } catch (NullPointerException e) {
- loge("registered NetworkAgent for unsupported type: " + na);
- }
mNetworkForNetId.put(na.network.netId, na);
na.asyncChannel.connect(mContext, mTrackerHandler, na.messenger);
NetworkInfo networkInfo = na.networkInfo;
@@ -5439,7 +5556,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
mClat.stopClat();
}
// If the link requires clat to be running, then start the daemon now.
- if (newLp != null && na.networkInfo.isConnected()) {
+ if (na.networkInfo.isConnected()) {
mClat.startClat(na);
} else {
mClat.stopClat();
@@ -5555,7 +5672,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
private void sendUpdatedScoreToFactories(NetworkRequest networkRequest, int score) {
if (VDBG) log("sending new Min Network Score(" + score + "): " + networkRequest.toString());
for (NetworkFactoryInfo nfi : mNetworkFactoryInfos.values()) {
- nfi.asyncChannel.sendMessage(NetworkFactoryProtocol.CMD_REQUEST_NETWORK, score, 0, networkRequest);
+ nfi.asyncChannel.sendMessage(android.net.NetworkFactory.CMD_REQUEST_NETWORK, score, 0,
+ networkRequest);
}
}
@@ -5658,7 +5776,11 @@ public class ConnectivityService extends IConnectivityManager.Stub {
if (VDBG) log(" accepting network in place of null");
}
mNetworkForRequestId.put(nri.request.requestId, newNetwork);
- newNetwork.networkRequests.put(nri.request.requestId, nri.request);
+ newNetwork.addRequest(nri.request);
+ int legacyType = nri.request.legacyType;
+ if (legacyType != TYPE_NONE) {
+ mLegacyTypeTracker.add(legacyType, newNetwork);
+ }
keep = true;
// TODO - this could get expensive if we have alot of requests for this
// network. Think about if there is a way to reduce this. Push
@@ -5672,6 +5794,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
} else {
setDefaultDnsSystemProperties(new ArrayList<InetAddress>());
}
+ mLegacyTypeTracker.add(newNetwork.networkInfo.getType(), newNetwork);
}
}
}
@@ -5792,6 +5915,32 @@ public class ConnectivityService extends IConnectivityManager.Stub {
}
}
+ private void updateNetworkScore(NetworkAgentInfo nai, int score) {
+ if (DBG) log("updateNetworkScore for " + nai.name() + " to " + score);
+
+ nai.currentScore = score;
+
+ // TODO - This will not do the right thing if this network is lowering
+ // its score and has requests that can be served by other
+ // currently-active networks, or if the network is increasing its
+ // score and other networks have requests that can be better served
+ // by this network.
+ //
+ // Really we want to see if any of our requests migrate to other
+ // active/lingered networks and if any other requests migrate to us (depending
+ // on increasing/decreasing currentScore. That's a bit of work and probably our
+ // score checking/network allocation code needs to be modularized so we can understand
+ // (see handleConnectionValided for an example).
+ //
+ // As a first order approx, lets just advertise the new score to factories. If
+ // somebody can beat it they will nominate a network and our normal net replacement
+ // code will fire.
+ for (int i = 0; i < nai.networkRequests.size(); i++) {
+ NetworkRequest nr = nai.networkRequests.valueAt(i);
+ sendUpdatedScoreToFactories(nr, score);
+ }
+ }
+
// notify only this one new request of the current state
protected void notifyNetworkCallback(NetworkAgentInfo nai, NetworkRequestInfo nri) {
int notifyType = ConnectivityManager.CALLBACK_AVAILABLE;
@@ -5801,93 +5950,88 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// } else if (nai.networkMonitor.isEvaluating()) {
// notifyType = NetworkCallbacks.callCallbackForRequest(request, nai, notifyType);
// }
- if (nri.request.needsBroadcasts) {
- // TODO
-// sendNetworkBroadcast(nai, notifyType);
- }
callCallbackForRequest(nri, nai, notifyType);
}
+ private void sendLegacyNetworkBroadcast(NetworkAgentInfo nai, boolean connected, int type) {
+ if (connected) {
+ NetworkInfo info = new NetworkInfo(nai.networkInfo);
+ info.setType(type);
+ sendConnectedBroadcastDelayed(info, getConnectivityChangeDelay());
+ } else {
+ NetworkInfo info = new NetworkInfo(nai.networkInfo);
+ info.setType(type);
+ Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
+ intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
+ if (info.isFailover()) {
+ intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
+ nai.networkInfo.setFailover(false);
+ }
+ if (info.getReason() != null) {
+ intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
+ }
+ if (info.getExtraInfo() != null) {
+ intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
+ }
+ NetworkAgentInfo newDefaultAgent = null;
+ if (nai.networkRequests.get(mDefaultRequest.requestId) != null) {
+ newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId);
+ if (newDefaultAgent != null) {
+ intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
+ newDefaultAgent.networkInfo);
+ } else {
+ intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
+ }
+ }
+ intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
+ mDefaultInetConditionPublished);
+ final Intent immediateIntent = new Intent(intent);
+ immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
+ sendStickyBroadcast(immediateIntent);
+ sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
+ if (newDefaultAgent != null) {
+ sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo,
+ getConnectivityChangeDelay());
+ }
+ }
+ }
+
protected void notifyNetworkCallbacks(NetworkAgentInfo networkAgent, int notifyType) {
if (VDBG) log("notifyType " + notifyType + " for " + networkAgent.name());
- boolean needsBroadcasts = false;
for (int i = 0; i < networkAgent.networkRequests.size(); i++) {
NetworkRequest nr = networkAgent.networkRequests.valueAt(i);
NetworkRequestInfo nri = mNetworkRequests.get(nr);
if (VDBG) log(" sending notification for " + nr);
- if (nr.needsBroadcasts) needsBroadcasts = true;
callCallbackForRequest(nri, networkAgent, notifyType);
}
- if (needsBroadcasts) {
- if (notifyType == ConnectivityManager.CALLBACK_AVAILABLE) {
- sendConnectedBroadcastDelayed(networkAgent.networkInfo,
- getConnectivityChangeDelay());
- } else if (notifyType == ConnectivityManager.CALLBACK_LOST) {
- NetworkInfo info = new NetworkInfo(networkAgent.networkInfo);
- Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
- intent.putExtra(ConnectivityManager.EXTRA_NETWORK_TYPE, info.getType());
- if (info.isFailover()) {
- intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
- networkAgent.networkInfo.setFailover(false);
- }
- if (info.getReason() != null) {
- intent.putExtra(ConnectivityManager.EXTRA_REASON, info.getReason());
- }
- if (info.getExtraInfo() != null) {
- intent.putExtra(ConnectivityManager.EXTRA_EXTRA_INFO, info.getExtraInfo());
- }
- NetworkAgentInfo newDefaultAgent = null;
- if (networkAgent.networkRequests.get(mDefaultRequest.requestId) != null) {
- newDefaultAgent = mNetworkForRequestId.get(mDefaultRequest.requestId);
- if (newDefaultAgent != null) {
- intent.putExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO,
- newDefaultAgent.networkInfo);
- } else {
- intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
- }
- }
- intent.putExtra(ConnectivityManager.EXTRA_INET_CONDITION,
- mDefaultInetConditionPublished);
- final Intent immediateIntent = new Intent(intent);
- immediateIntent.setAction(CONNECTIVITY_ACTION_IMMEDIATE);
- sendStickyBroadcast(immediateIntent);
- sendStickyBroadcastDelayed(intent, getConnectivityChangeDelay());
- if (newDefaultAgent != null) {
- sendConnectedBroadcastDelayed(newDefaultAgent.networkInfo,
- getConnectivityChangeDelay());
- }
- }
- }
}
private LinkProperties getLinkPropertiesForTypeInternal(int networkType) {
- ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType];
- if (list == null) return null;
- try {
- return new LinkProperties(list.get(0).linkProperties);
- } catch (IndexOutOfBoundsException e) {
- return new LinkProperties();
- }
+ NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+ return (nai != null) ?
+ new LinkProperties(nai.linkProperties) :
+ new LinkProperties();
}
private NetworkInfo getNetworkInfoForType(int networkType) {
- ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType];
- if (list == null) return null;
- try {
- return new NetworkInfo(list.get(0).networkInfo);
- } catch (IndexOutOfBoundsException e) {
- return new NetworkInfo(networkType, 0, "Unknown", "");
+ if (!mLegacyTypeTracker.isTypeSupported(networkType))
+ return null;
+
+ NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+ if (nai != null) {
+ NetworkInfo result = new NetworkInfo(nai.networkInfo);
+ result.setType(networkType);
+ return result;
+ } else {
+ return new NetworkInfo(networkType, 0, "Unknown", "");
}
}
private NetworkCapabilities getNetworkCapabilitiesForType(int networkType) {
- ArrayList<NetworkAgentInfo> list = mNetworkAgentInfoForType[networkType];
- if (list == null) return null;
- try {
- return new NetworkCapabilities(list.get(0).networkCapabilities);
- } catch (IndexOutOfBoundsException e) {
- return new NetworkCapabilities();
- }
+ NetworkAgentInfo nai = mLegacyTypeTracker.getNetworkForType(networkType);
+ return (nai != null) ?
+ new NetworkCapabilities(nai.networkCapabilities) :
+ new NetworkCapabilities();
}
}
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 3a8f767..11d6a55 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -961,6 +961,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return false;
}
+
+ /**
+ * Returns true iff the caller is identified to be the current input method with the token.
+ * @param token The window token given to the input method when it was started.
+ * @return true if and only if non-null valid token is specified.
+ */
+ private boolean calledWithValidToken(IBinder token) {
+ if (token == null || mCurToken != token) {
+ return false;
+ }
+ return true;
+ }
+
private boolean bindCurrentInputMethodService(
Intent service, ServiceConnection conn, int flags) {
if (service == null || conn == null) {
@@ -1429,15 +1442,15 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
@Override
public void updateStatusIcon(IBinder token, String packageName, int iconId) {
- int uid = Binder.getCallingUid();
long ident = Binder.clearCallingIdentity();
try {
- if (token == null || mCurToken != token) {
- Slog.w(TAG, "Ignoring setInputMethod of uid " + uid + " token: " + token);
- return;
- }
-
synchronized (mMethodMap) {
+ if (!calledWithValidToken(token)) {
+ final int uid = Binder.getCallingUid();
+ Slog.e(TAG, "Ignoring updateStatusIcon due to an invalid token. uid:" + uid
+ + " token:" + token);
+ return;
+ }
if (iconId == 0) {
if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
if (mStatusBar != null) {
@@ -1527,9 +1540,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
final long ident = Binder.clearCallingIdentity();
try {
- if (token == null || mCurToken != token) {
- int uid = Binder.getCallingUid();
- Slog.w(TAG, "Ignoring setImeWindowStatus of uid " + uid + " token: " + token);
+ if (!calledWithValidToken(token)) {
+ final int uid = Binder.getCallingUid();
+ Slog.e(TAG, "Ignoring setImeWindowStatus due to an invalid token. uid:" + uid
+ + " token:" + token);
return;
}
synchronized (mMethodMap) {
@@ -2085,8 +2099,9 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
}
synchronized (mMethodMap) {
if (subtype != null) {
- setInputMethodWithSubtypeId(token, id, InputMethodUtils.getSubtypeIdFromHashCode(
- mMethodMap.get(id), subtype.hashCode()));
+ setInputMethodWithSubtypeIdLocked(token, id,
+ InputMethodUtils.getSubtypeIdFromHashCode(mMethodMap.get(id),
+ subtype.hashCode()));
} else {
setInputMethod(token, id);
}
@@ -2173,7 +2188,7 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
+ ", from: " + mCurMethodId + ", " + subtypeId);
}
- setInputMethodWithSubtypeId(token, targetLastImiId, subtypeId);
+ setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
return true;
} else {
return false;
@@ -2187,12 +2202,19 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return false;
}
synchronized (mMethodMap) {
+ if (!calledWithValidToken(token)) {
+ final int uid = Binder.getCallingUid();
+ Slog.e(TAG, "Ignoring switchToNextInputMethod due to an invalid token. uid:" + uid
+ + " token:" + token);
+ return false;
+ }
final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
if (nextSubtype == null) {
return false;
}
- setInputMethodWithSubtypeId(token, nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
+ setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
+ nextSubtype.mSubtypeId);
return true;
}
}
@@ -2203,6 +2225,12 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return false;
}
synchronized (mMethodMap) {
+ if (!calledWithValidToken(token)) {
+ final int uid = Binder.getCallingUid();
+ Slog.e(TAG, "Ignoring shouldOfferSwitchingToNextInputMethod due to an invalid "
+ + "token. uid:" + uid + " token:" + token);
+ return false;
+ }
final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
if (nextSubtype == null) {
@@ -2303,11 +2331,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return;
}
synchronized (mMethodMap) {
- if (token == null || mCurToken != token) {
- if (DEBUG) {
- Slog.w(TAG, "Ignoring setCursorAnchorMonitorMode from uid "
- + Binder.getCallingUid() + " token: " + token);
- }
+ if (!calledWithValidToken(token)) {
+ final int uid = Binder.getCallingUid();
+ Slog.e(TAG, "Ignoring setCursorAnchorMonitorMode due to an invalid token. uid:"
+ + uid + " token:" + token);
return;
}
executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
@@ -2317,26 +2344,30 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
synchronized (mMethodMap) {
- if (token == null) {
- if (mContext.checkCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException(
- "Using null token requires permission "
- + android.Manifest.permission.WRITE_SECURE_SETTINGS);
- }
- } else if (mCurToken != token) {
- Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
- + " token: " + token);
- return;
- }
+ setInputMethodWithSubtypeIdLocked(token, id, subtypeId);
+ }
+ }
- final long ident = Binder.clearCallingIdentity();
- try {
- setInputMethodLocked(id, subtypeId);
- } finally {
- Binder.restoreCallingIdentity(ident);
+ private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
+ if (token == null) {
+ if (mContext.checkCallingOrSelfPermission(
+ android.Manifest.permission.WRITE_SECURE_SETTINGS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException(
+ "Using null token requires permission "
+ + android.Manifest.permission.WRITE_SECURE_SETTINGS);
}
+ } else if (mCurToken != token) {
+ Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
+ + " token: " + token);
+ return;
+ }
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setInputMethodLocked(id, subtypeId);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
@@ -2346,9 +2377,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return;
}
synchronized (mMethodMap) {
- if (token == null || mCurToken != token) {
- if (DEBUG) Slog.w(TAG, "Ignoring hideInputMethod of uid "
- + Binder.getCallingUid() + " token: " + token);
+ if (!calledWithValidToken(token)) {
+ final int uid = Binder.getCallingUid();
+ Slog.e(TAG, "Ignoring hideInputMethod due to an invalid token. uid:"
+ + uid + " token:" + token);
return;
}
long ident = Binder.clearCallingIdentity();
@@ -2366,9 +2398,10 @@ public class InputMethodManagerService extends IInputMethodManager.Stub
return;
}
synchronized (mMethodMap) {
- if (token == null || mCurToken != token) {
- Slog.w(TAG, "Ignoring showMySoftInput of uid "
- + Binder.getCallingUid() + " token: " + token);
+ if (!calledWithValidToken(token)) {
+ final int uid = Binder.getCallingUid();
+ Slog.e(TAG, "Ignoring showMySoftInput due to an invalid token. uid:"
+ + uid + " token:" + token);
return;
}
long ident = Binder.clearCallingIdentity();
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 11fc941..98fa522 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -427,8 +427,9 @@ public class LocationManagerService extends ILocationManager.Stub {
}
// bind to fused provider if supported
- if (FlpHardwareProvider.getInstance(mContext).isSupported()) {
- FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
+ if (FlpHardwareProvider.isSupported()) {
+ FlpHardwareProvider flpHardwareProvider =
+ FlpHardwareProvider.getInstance(mContext);
FusedProxy fusedProxy = FusedProxy.createAndBind(
mContext,
mLocationHandler,
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 61ba6e0..fa26d56 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -2883,16 +2883,17 @@ public final class ActivityManagerService extends ActivityManagerNative
}
/*
- * Add shared application GID so applications can share some
- * resources like shared libraries
+ * Add shared application and profile GIDs so applications can share some
+ * resources like shared libraries and access user-wide resources
*/
if (permGids == null) {
- gids = new int[1];
+ gids = new int[2];
} else {
- gids = new int[permGids.length + 1];
- System.arraycopy(permGids, 0, gids, 1, permGids.length);
+ gids = new int[permGids.length + 2];
+ System.arraycopy(permGids, 0, gids, 2, permGids.length);
}
gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid));
+ gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid));
}
if (mFactoryTest != FactoryTest.FACTORY_TEST_OFF) {
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
@@ -2978,6 +2979,10 @@ public final class ActivityManagerService extends ActivityManagerNative
}
}
buf.append("}");
+ if (requiredAbi != null) {
+ buf.append(" abi=");
+ buf.append(requiredAbi);
+ }
Slog.i(TAG, buf.toString());
app.setPid(startResult.pid);
app.usingWrapper = startResult.usingWrapper;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 249422b..eb253eb 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -623,10 +623,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
pw.println(" --charged: only output data since last charged.");
pw.println(" --reset: reset the stats, clearing all current data.");
pw.println(" --write: force write current collected stats to disk.");
- pw.println(" --enable: enable an option: full-wake-history, no-auto-reset.");
- pw.println(" --disable: disable an option: full-wake-history, no-auto-reset.");
- pw.println(" -h: print this help text.");
pw.println(" <package.name>: optional name of package to filter output by.");
+ pw.println(" -h: print this help text.");
+ pw.println("Battery stats (batterystats) commands:");
+ pw.println(" enable|disable <option>");
+ pw.println(" Enable or disable a running option. Option state is not saved across boots.");
+ pw.println(" Options are:");
+ pw.println(" full-wake-history: include wake_lock_in battery history, full wake details.");
+ pw.println(" no-auto-reset: don't automatically reset stats when unplugged");
}
private int doEnableOrDisable(PrintWriter pw, int i, String[] args, boolean enable) {
@@ -665,6 +669,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
int flags = 0;
boolean isCheckin = false;
boolean noOutput = false;
+ boolean writeData = false;
long historyStart = -1;
int reqUid = -1;
if (args != null) {
@@ -683,6 +688,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub
return;
}
historyStart = Long.parseLong(args[i]);
+ writeData = true;
} else if ("-c".equals(arg)) {
isCheckin = true;
flags |= BatteryStats.DUMP_INCLUDE_HISTORY;
@@ -702,14 +708,14 @@ public final class BatteryStatsService extends IBatteryStats.Stub
pw.println("Battery stats written.");
noOutput = true;
}
- } else if ("--enable".equals(arg)) {
+ } else if ("--enable".equals(arg) || "enable".equals(arg)) {
i = doEnableOrDisable(pw, i, args, true);
if (i < 0) {
return;
}
pw.println("Enabled: " + args[i]);
return;
- } else if ("--disable".equals(arg)) {
+ } else if ("--disable".equals(arg) || "disable".equals(arg)) {
i = doEnableOrDisable(pw, i, args, false);
if (i < 0) {
return;
@@ -745,10 +751,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub
List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
synchronized (mStats) {
mStats.dumpCheckinLocked(mContext, pw, apps, flags, historyStart);
+ if (writeData) {
+ mStats.writeAsyncLocked();
+ }
}
} else {
synchronized (mStats) {
mStats.dumpLocked(mContext, pw, flags, reqUid, historyStart);
+ if (writeData) {
+ mStats.writeAsyncLocked();
+ }
}
}
}
diff --git a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
index 8102591..b03c247 100644
--- a/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
+++ b/services/core/java/com/android/server/connectivity/NetworkAgentInfo.java
@@ -45,7 +45,6 @@ public class NetworkAgentInfo {
public int currentScore;
public final NetworkMonitor networkMonitor;
-
// The list of NetworkRequests being satisfied by this Network.
public final SparseArray<NetworkRequest> networkRequests = new SparseArray<NetworkRequest>();
public final ArrayList<NetworkRequest> networkLingered = new ArrayList<NetworkRequest>();
@@ -66,6 +65,10 @@ public class NetworkAgentInfo {
networkMonitor = new NetworkMonitor(context, handler, this);
}
+ public void addRequest(NetworkRequest networkRequest) {
+ networkRequests.put(networkRequest.requestId, networkRequest);
+ }
+
public String toString() {
return "NetworkAgentInfo{ ni{" + networkInfo + "} network{" +
network + "} lp{" +
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 8fd55e7..3b55bfc 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -365,15 +365,8 @@ public final class ContentService extends IContentService.Stub {
Manifest.permission.WRITE_SYNC_SETTINGS,
"no permission to write the sync settings");
SyncStorageEngine.EndPoint info;
- if (!request.hasAuthority()) {
- // Extra permissions checking for sync service.
- verifySignatureForPackage(callerUid,
- request.getService().getPackageName(), "sync");
- info = new SyncStorageEngine.EndPoint(request.getService(), userId);
- } else {
- info = new SyncStorageEngine.EndPoint(
- request.getAccount(), request.getProvider(), userId);
- }
+ info = new SyncStorageEngine.EndPoint(
+ request.getAccount(), request.getProvider(), userId);
if (runAtTime < 60) {
Slog.w(TAG, "Requested poll frequency of " + runAtTime
+ " seconds being rounded up to 60 seconds.");
@@ -385,17 +378,10 @@ public final class ContentService extends IContentService.Stub {
} else {
long beforeRuntimeMillis = (flextime) * 1000;
long runtimeMillis = runAtTime * 1000;
- if (request.hasAuthority()) {
syncManager.scheduleSync(
request.getAccount(), userId, callerUid, request.getProvider(), extras,
beforeRuntimeMillis, runtimeMillis,
false /* onlyThoseWithUnknownSyncableState */);
- } else {
- syncManager.scheduleSync(
- request.getService(), userId, callerUid, extras,
- beforeRuntimeMillis,
- runtimeMillis); // Empty function.
- }
}
} finally {
restoreCallingIdentity(identityToken);
@@ -442,22 +428,14 @@ public final class ContentService extends IContentService.Stub {
SyncManager syncManager = getSyncManager();
if (syncManager == null) return;
int userId = UserHandle.getCallingUserId();
- int callerUid = Binder.getCallingUid();
long identityToken = clearCallingIdentity();
try {
SyncStorageEngine.EndPoint info;
Bundle extras = new Bundle(request.getBundle());
- if (request.hasAuthority()) {
- Account account = request.getAccount();
- String provider = request.getProvider();
- info = new SyncStorageEngine.EndPoint(account, provider, userId);
- } else {
- // Only allowed to manipulate syncs for a service which you own.
- ComponentName service = request.getService();
- verifySignatureForPackage(callerUid, service.getPackageName(), "cancel");
- info = new SyncStorageEngine.EndPoint(service, userId);
- }
+ Account account = request.getAccount();
+ String provider = request.getProvider();
+ info = new SyncStorageEngine.EndPoint(account, provider, userId);
if (request.isPeriodic()) {
// Remove periodic sync.
mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
@@ -599,20 +577,11 @@ public final class ContentService extends IContentService.Stub {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
"no permission to read the sync settings");
- int callerUid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
long identityToken = clearCallingIdentity();
try {
- if (cname == null) {
- return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
- new SyncStorageEngine.EndPoint(account, providerName, userId));
- } else if (account == null && providerName == null) {
- verifySignatureForPackage(callerUid, cname.getPackageName(), "getPeriodicSyncs");
- return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
- new SyncStorageEngine.EndPoint(cname, userId));
- } else {
- throw new IllegalArgumentException("Invalid authority specified");
- }
+ return getSyncManager().getSyncStorageEngine().getPeriodicSyncs(
+ new SyncStorageEngine.EndPoint(account, providerName, userId));
} finally {
restoreCallingIdentity(identityToken);
}
@@ -656,45 +625,6 @@ public final class ContentService extends IContentService.Stub {
}
}
- public void setServiceActive(ComponentName cname, boolean active) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.WRITE_SYNC_SETTINGS,
- "no permission to write the sync settings");
- verifySignatureForPackage(Binder.getCallingUid(), cname.getPackageName(),
- "setServiceActive");
-
- int userId = UserHandle.getCallingUserId();
- long identityToken = clearCallingIdentity();
- try {
- SyncManager syncManager = getSyncManager();
- if (syncManager != null) {
- syncManager.getSyncStorageEngine().setIsTargetServiceActive(
- cname, userId, active);
- }
- } finally {
- restoreCallingIdentity(identityToken);
- }
- }
-
- public boolean isServiceActive(ComponentName cname) {
- mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
- "no permission to read the sync settings");
- verifySignatureForPackage(Binder.getCallingUid(), cname.getPackageName(),
- "isServiceActive");
-
- int userId = UserHandle.getCallingUserId();
- long identityToken = clearCallingIdentity();
- try {
- SyncManager syncManager = getSyncManager();
- if (syncManager != null) {
- return syncManager.getSyncStorageEngine()
- .getIsTargetServiceActive(cname, userId);
- }
- } finally {
- restoreCallingIdentity(identityToken);
- }
- return false;
- }
-
@Override
public boolean getMasterSyncAutomatically() {
mContext.enforceCallingOrSelfPermission(Manifest.permission.READ_SYNC_SETTINGS,
@@ -741,18 +671,11 @@ public final class ContentService extends IContentService.Stub {
if (syncManager == null) {
return false;
}
- if (cname == null) {
- return syncManager.getSyncStorageEngine().isSyncActive(
- new SyncStorageEngine.EndPoint(account, authority, userId));
- } else if (account == null && authority == null) {
- verifySignatureForPackage(callingUid, cname.getPackageName(), "isSyncActive");
- return syncManager.getSyncStorageEngine().isSyncActive(
- new SyncStorageEngine.EndPoint(cname, userId));
- }
+ return syncManager.getSyncStorageEngine().isSyncActive(
+ new SyncStorageEngine.EndPoint(account, authority, userId));
} finally {
restoreCallingIdentity(identityToken);
}
- return false;
}
public List<SyncInfo> getCurrentSyncs() {
@@ -784,11 +707,8 @@ public final class ContentService extends IContentService.Stub {
return null;
}
SyncStorageEngine.EndPoint info;
- if (cname == null) {
+ if (!(account == null || authority == null)) {
info = new SyncStorageEngine.EndPoint(account, authority, userId);
- } else if (account == null && authority == null) {
- verifySignatureForPackage(callerUid, cname.getPackageName(), "getSyncStatus");
- info = new SyncStorageEngine.EndPoint(cname, userId);
} else {
throw new IllegalArgumentException("Must call sync status with valid authority");
}
@@ -810,11 +730,8 @@ public final class ContentService extends IContentService.Stub {
try {
SyncStorageEngine.EndPoint info;
- if (cname == null) {
+ if (!(account == null || authority == null)) {
info = new SyncStorageEngine.EndPoint(account, authority, userId);
- } else if (account == null && authority == null) {
- verifySignatureForPackage(callerUid, cname.getPackageName(), "isSyncPending");
- info = new SyncStorageEngine.EndPoint(cname, userId);
} else {
throw new IllegalArgumentException("Invalid authority specified");
}
@@ -855,30 +772,6 @@ public final class ContentService extends IContentService.Stub {
}
/**
- * Helper to verify that the provided package name shares the same cert as the caller.
- * @param callerUid uid of the calling process.
- * @param packageName package to verify against package of calling application.
- * @param tag a tag to use when throwing an exception if the signatures don't
- * match. Cannot be null.
- * @return true if the calling application and the provided package are signed with the same
- * certificate.
- */
- private boolean verifySignatureForPackage(int callerUid, String packageName, String tag) {
- PackageManager pm = mContext.getPackageManager();
- try {
- int serviceUid = pm.getApplicationInfo(packageName, 0).uid;
- if (pm.checkSignatures(callerUid, serviceUid) == PackageManager.SIGNATURE_MATCH) {
- return true;
- } else {
- throw new SecurityException(tag + ": Caller certificate does not match that for - "
- + packageName);
- }
- } catch (PackageManager.NameNotFoundException e) {
- throw new IllegalArgumentException(tag + ": " + packageName + " package not found.");
- }
- }
-
- /**
* Hide this class since it is not part of api,
* but current unittest framework requires it to be public
* @hide
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 35c494d..9499370 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -925,10 +925,7 @@ public class SyncStorageEngine extends Handler {
period,
flextime);
} else {
- toUpdate = new PeriodicSync(info.service,
- extras,
- period,
- flextime);
+ return;
}
AuthorityInfo authority =
getOrCreateAuthorityLocked(info, -1, false);
@@ -1246,7 +1243,6 @@ public class SyncStorageEngine extends Handler {
authorityInfo.ident,
authorityInfo.target.account,
authorityInfo.target.provider,
- authorityInfo.target.service,
activeSyncContext.mStartTime);
getCurrentSyncs(authorityInfo.target.userId).add(syncInfo);
}
@@ -1262,8 +1258,7 @@ public class SyncStorageEngine extends Handler {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "removeActiveSync: account=" + syncInfo.account
+ " user=" + userId
- + " auth=" + syncInfo.authority
- + " service=" + syncInfo.service);
+ + " auth=" + syncInfo.authority);
}
getCurrentSyncs(userId).remove(syncInfo);
}
@@ -2109,12 +2104,8 @@ public class SyncStorageEngine extends Handler {
extras,
period, flextime);
} else {
- periodicSync =
- new PeriodicSync(
- authorityInfo.target.service,
- extras,
- period,
- flextime);
+ Log.e(TAG, "Unknown target.");
+ return null;
}
authorityInfo.periodicSyncs.add(periodicSync);
return periodicSync;
@@ -2700,7 +2691,10 @@ public class SyncStorageEngine extends Handler {
if (authorityInfo.target.target_provider) {
req.setSyncAdapter(authorityInfo.target.account, authorityInfo.target.provider);
} else {
- req.setSyncAdapter(authorityInfo.target.service);
+ if (Log.isLoggable(TAG, Log.DEBUG)) {
+ Log.d(TAG, "Unknown target, skipping sync request.");
+ }
+ return;
}
ContentResolver.requestSync(req.build());
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
index d0b716d..5141d16 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecController.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -505,7 +505,7 @@ final class HdmiCecController {
// Reply <Feature Abort> to initiator (source) for all requests.
HdmiCecMessage cecMessage = HdmiCecMessageBuilder.buildFeatureAbortCommand(
sourceAddress, message.getSource(), message.getOpcode(),
- HdmiCecMessageBuilder.ABORT_REFUSED);
+ HdmiConstants.ABORT_REFUSED);
sendCommand(cecMessage, null);
}
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
index 9a76734..6c2be34 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecMessageBuilder.java
@@ -26,15 +26,6 @@ import java.util.Arrays;
* A helper class to build {@link HdmiCecMessage} from various cec commands.
*/
public class HdmiCecMessageBuilder {
- // TODO: move these values to HdmiCec.java once make it internal constant class.
- // CEC's ABORT reason values.
- static final int ABORT_UNRECOGNIZED_MODE = 0;
- static final int ABORT_NOT_IN_CORRECT_MODE = 1;
- static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
- static final int ABORT_INVALID_OPERAND = 3;
- static final int ABORT_REFUSED = 4;
- static final int ABORT_UNABLE_TO_DETERMINE = 5;
-
private static final int OSD_NAME_MAX_LENGTH = 13;
private HdmiCecMessageBuilder() {}
@@ -290,6 +281,64 @@ public class HdmiCecMessageBuilder {
}
/**
+ * Build &lt;System Audio Mode Request&gt; command.
+ *
+ * @param src source address of command
+ * @param avr destination address of command, it should be AVR
+ * @param avrPhysicalAddress physical address of AVR
+ * @param enableSystemAudio whether to enable System Audio Mode or not
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildSystemAudioModeRequest(int src, int avr, int avrPhysicalAddress,
+ boolean enableSystemAudio) {
+ if (enableSystemAudio) {
+ return buildCommand(src, avr, HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST,
+ physicalAddressToParam(avrPhysicalAddress));
+ } else {
+ return buildCommand(src, avr, HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_REQUEST);
+ }
+ }
+
+ /**
+ * Build &lt;Give Audio Status&gt; command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildGiveAudioStatus(int src, int dest) {
+ return buildCommand(src, dest, HdmiCec.MESSAGE_GIVE_AUDIO_STATUS);
+ }
+
+ /**
+ * Build &lt;User Control Pressed&gt; command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @param uiCommand keycode that user pressed
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildUserControlPressed(int src, int dest, int uiCommand) {
+ byte[] params = new byte[] {
+ (byte) uiCommand
+ };
+ return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_PRESSED, params);
+ }
+
+ /**
+ * Build &lt;User Control Released&gt; command.
+ *
+ * @param src source address of command
+ * @param dest destination address of command
+ * @return newly created {@link HdmiCecMessage}
+ */
+ static HdmiCecMessage buildUserControlReleased(int src, int dest) {
+ return buildCommand(src, dest, HdmiCec.MESSAGE_USER_CONTROL_RELEASED);
+ }
+
+ /***** Please ADD new buildXXX() methods above. ******/
+
+ /**
* Build a {@link HdmiCecMessage} without extra parameter.
*
* @param src source address of command
diff --git a/services/core/java/com/android/server/hdmi/HdmiConstants.java b/services/core/java/com/android/server/hdmi/HdmiConstants.java
new file mode 100644
index 0000000..a83d1ed
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiConstants.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+/**
+ * Defines constants related to HDMI-CEC protocol internal implementation.
+ * If a constant will be used in the public api, it should be located in
+ * {@link android.hardware.hdmi.HdmiCec}.
+ */
+final class HdmiConstants {
+
+ // Constants related to operands of HDMI CEC commands.
+ // Refer to CEC Table 29 in HDMI Spec v1.4b.
+ // [Abort Reason]
+ static final int ABORT_UNRECOGNIZED_MODE = 0;
+ static final int ABORT_NOT_IN_CORRECT_MODE = 1;
+ static final int ABORT_CANNOT_PROVIDE_SOURCE = 2;
+ static final int ABORT_INVALID_OPERAND = 3;
+ static final int ABORT_REFUSED = 4;
+ static final int ABORT_UNABLE_TO_DETERMINE = 5;
+
+ // [Audio Status]
+ static final int SYSTEM_AUDIO_STATUS_OFF = 0;
+ static final int SYSTEM_AUDIO_STATUS_ON = 1;
+
+ // Constants related to UI Command Codes.
+ // Refer to CEC Table 30 in HDMI Spec v1.4b.
+ static final int UI_COMMAND_MUTE = 0x43;
+ static final int UI_COMMAND_MUTE_FUNCTION = 0x65;
+ static final int UI_COMMAND_RESTORE_VOLUME_FUNCTION = 0x66;
+
+ private HdmiConstants() { /* cannot be instantiated */ }
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index d775733..0f3fc21 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -118,8 +118,11 @@ public final class HdmiControlService extends SystemService {
// TODO: it may need to hold lock if it's accessed from others.
private boolean mArcStatusEnabled = false;
+ // Whether SystemAudioMode is "On" or not.
+ private boolean mSystemAudioMode;
+
// Handler running on service thread. It's used to run a task in service thread.
- private Handler mHandler = new Handler();
+ private final Handler mHandler = new Handler();
public HdmiControlService(Context context) {
super(context);
@@ -158,6 +161,9 @@ public final class HdmiControlService extends SystemService {
}
publishBinderService(Context.HDMI_CONTROL_SERVICE, new BinderService());
+
+ // TODO: Read the preference for SystemAudioMode and initialize mSystemAudioMode and
+ // start to monitor the preference value and invoke SystemAudioActionFromTv if needed.
}
/**
@@ -211,35 +217,43 @@ public final class HdmiControlService extends SystemService {
* @param action {@link FeatureAction} to remove
*/
void removeAction(final FeatureAction action) {
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
- mActions.remove(action);
- }
- });
+ assertRunOnServiceThread();
+ mActions.remove(action);
}
// Remove all actions matched with the given Class type.
private <T extends FeatureAction> void removeAction(final Class<T> clazz) {
- runOnServiceThread(new Runnable() {
- @Override
- public void run() {
- Iterator<FeatureAction> iter = mActions.iterator();
- while (iter.hasNext()) {
- FeatureAction action = iter.next();
- if (action.getClass().equals(clazz)) {
- action.clear();
- mActions.remove(action);
- }
- }
+ removeActionExcept(clazz, null);
+ }
+
+ // Remove all actions matched with the given Class type besides |exception|.
+ <T extends FeatureAction> void removeActionExcept(final Class<T> clazz,
+ final FeatureAction exception) {
+ assertRunOnServiceThread();
+ Iterator<FeatureAction> iter = mActions.iterator();
+ while (iter.hasNext()) {
+ FeatureAction action = iter.next();
+ if (action != exception && action.getClass().equals(clazz)) {
+ action.clear();
+ mActions.remove(action);
}
- });
+ }
}
private void runOnServiceThread(Runnable runnable) {
mHandler.post(runnable);
}
+ void runOnServiceThreadAtFrontOfQueue(Runnable runnable) {
+ mHandler.postAtFrontOfQueue(runnable);
+ }
+
+ private void assertRunOnServiceThread() {
+ if (Looper.myLooper() != mHandler.getLooper()) {
+ throw new IllegalStateException("Should run on service thread.");
+ }
+ }
+
/**
* Change ARC status into the given {@code enabled} status.
*
@@ -306,8 +320,12 @@ public final class HdmiControlService extends SystemService {
case HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS:
handleReportPhysicalAddress(message);
return true;
- // TODO: Add remaining system information query such as
- // <Give Device Power Status> and <Request Active Source> handler.
+ case HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE:
+ handleSetSystemAudioMode(message);
+ return true;
+ case HdmiCec.MESSAGE_SYSTEM_AUDIO_MODE_STATUS:
+ handleSystemAudioModeStatus(message);
+ return true;
default:
return dispatchMessageToAction(message);
}
@@ -413,7 +431,7 @@ public final class HdmiControlService extends SystemService {
sendCecCommand(
HdmiCecMessageBuilder.buildFeatureAbortCommand(message.getDestination(),
message.getSource(), HdmiCec.MESSAGE_GET_MENU_LANGUAGE,
- HdmiCecMessageBuilder.ABORT_UNRECOGNIZED_MODE));
+ HdmiConstants.ABORT_UNRECOGNIZED_MODE));
return;
}
@@ -438,6 +456,33 @@ public final class HdmiControlService extends SystemService {
return false;
}
+ private void handleSetSystemAudioMode(HdmiCecMessage message) {
+ if (dispatchMessageToAction(message) || !isMessageForSystemAudio(message)) {
+ return;
+ }
+ SystemAudioActionFromAvr action = new SystemAudioActionFromAvr(this,
+ message.getDestination(), message.getSource(),
+ HdmiUtils.parseCommandParamSystemAudioStatus(message));
+ addAndStartAction(action);
+ }
+
+ private void handleSystemAudioModeStatus(HdmiCecMessage message) {
+ if (!isMessageForSystemAudio(message)) {
+ return;
+ }
+ setSystemAudioMode(HdmiUtils.parseCommandParamSystemAudioStatus(message));
+ }
+
+ private boolean isMessageForSystemAudio(HdmiCecMessage message) {
+ if (message.getSource() != HdmiCec.ADDR_AUDIO_SYSTEM
+ || message.getDestination() != HdmiCec.ADDR_TV
+ || getAvrDeviceInfo() == null) {
+ Slog.w(TAG, "Skip abnormal CecMessage: " + message);
+ return false;
+ }
+ return true;
+ }
+
// Record class that monitors the event of the caller of being killed. Used to clean up
// the listener list and record list accordingly.
private final class HotplugEventListenerRecord implements IBinder.DeathRecipient {
@@ -627,4 +672,32 @@ public final class HdmiControlService extends SystemService {
Slog.e(TAG, "Invoking callback failed:" + e);
}
}
+
+ HdmiCecDeviceInfo getAvrDeviceInfo() {
+ return mCecController.getDeviceInfo(HdmiCec.ADDR_AUDIO_SYSTEM);
+ }
+
+ void setSystemAudioMode(boolean newMode) {
+ assertRunOnServiceThread();
+ if (newMode != mSystemAudioMode) {
+ // TODO: Need to set the preference for SystemAudioMode.
+ // TODO: Need to handle the notification of changing the mode and
+ // to identify the notification should be handled in the service or TvSettings.
+ mSystemAudioMode = newMode;
+ }
+ }
+
+ boolean getSystemAudioMode() {
+ assertRunOnServiceThread();
+ return mSystemAudioMode;
+ }
+
+ void setAudioStatus(boolean mute, int volume) {
+ // TODO: Hook up with AudioManager.
+ }
+
+ boolean isInPresetInstallationMode() {
+ // TODO: Implement this.
+ return false;
+ }
}
diff --git a/services/core/java/com/android/server/hdmi/HdmiUtils.java b/services/core/java/com/android/server/hdmi/HdmiUtils.java
new file mode 100644
index 0000000..ef128ed1
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiUtils.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+import android.util.Slog;
+
+/**
+ * Various utilities to handle HDMI CEC messages.
+ */
+final class HdmiUtils {
+
+ private HdmiUtils() { /* cannot be instantiated */ }
+
+ /**
+ * Verify if the given address is for the given device type. If not it will throw
+ * {@link IllegalArgumentException}.
+ *
+ * @param logicalAddress the logical address to verify
+ * @param deviceType the device type to check
+ * @throw IllegalArgumentException
+ */
+ static void verifyAddressType(int logicalAddress, int deviceType) {
+ int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
+ if (actualDeviceType != deviceType) {
+ throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
+ + ", Actual:" + actualDeviceType);
+ }
+ }
+
+ /**
+ * Check if the given CEC message come from the given address.
+ *
+ * @param cmd the CEC message to check
+ * @param expectedAddress the expected source address of the given message
+ * @param tag the tag of caller module (for log message)
+ * @return true if the CEC message comes from the given address
+ */
+ static boolean checkCommandSource(HdmiCecMessage cmd, int expectedAddress, String tag) {
+ int src = cmd.getSource();
+ if (src != expectedAddress) {
+ Slog.w(tag, "Invalid source [Expected:" + expectedAddress + ", Actual:" + src + "]");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Parse the parameter block of CEC message as [System Audio Status].
+ *
+ * @param cmd the CEC message to parse
+ * @return true if the given parameter has [ON] value
+ */
+ static boolean parseCommandParamSystemAudioStatus(HdmiCecMessage cmd) {
+ // TODO: Handle the exception when the length is wrong.
+ return cmd.getParams().length > 0
+ && cmd.getParams()[0] == HdmiConstants.SYSTEM_AUDIO_STATUS_ON;
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/RequestArcAction.java b/services/core/java/com/android/server/hdmi/RequestArcAction.java
index 05614a4..08ca306 100644
--- a/services/core/java/com/android/server/hdmi/RequestArcAction.java
+++ b/services/core/java/com/android/server/hdmi/RequestArcAction.java
@@ -44,28 +44,15 @@ abstract class RequestArcAction extends FeatureAction {
*/
RequestArcAction(HdmiControlService service, int sourceAddress, int avrAddress) {
super(service, sourceAddress);
- verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
- verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+ HdmiUtils.verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+ HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
mAvrAddress = avrAddress;
}
- private static void verifyAddressType(int logicalAddress, int deviceType) {
- int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
- if (actualDeviceType != deviceType) {
- throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
- + ", Actual:" + actualDeviceType);
- }
- }
-
@Override
boolean processCommand(HdmiCecMessage cmd) {
- if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE) {
- return false;
- }
-
- int src = cmd.getSource();
- if (src != mAvrAddress) {
- Slog.w(TAG, "Invalid source [Expected:" + mAvrAddress + ", Actual:" + src + "]");
+ if (mState != STATE_WATING_FOR_REQUEST_ARC_REQUEST_RESPONSE
+ || !HdmiUtils.checkCommandSource(cmd, mAvrAddress, TAG)) {
return false;
}
int opcode = cmd.getOpcode();
diff --git a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
index e3525d8..d53d88d 100644
--- a/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
+++ b/services/core/java/com/android/server/hdmi/SetArcTransmissionStateAction.java
@@ -46,21 +46,12 @@ final class SetArcTransmissionStateAction extends FeatureAction {
SetArcTransmissionStateAction(HdmiControlService service, int sourceAddress, int avrAddress,
boolean enabled) {
super(service, sourceAddress);
- verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
- verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+ HdmiUtils.verifyAddressType(sourceAddress, HdmiCec.DEVICE_TV);
+ HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
mAvrAddress = avrAddress;
mEnabled = enabled;
}
- // TODO: extract it as separate utility class.
- private static void verifyAddressType(int logicalAddress, int deviceType) {
- int actualDeviceType = HdmiCec.getTypeFromAddress(logicalAddress);
- if (actualDeviceType != deviceType) {
- throw new IllegalArgumentException("Device type missmatch:[Expected:" + deviceType
- + ", Actual:" + actualDeviceType);
- }
- }
-
@Override
boolean start() {
if (mEnabled) {
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioAction.java b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
new file mode 100644
index 0000000..dde3342
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SystemAudioAction.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+import android.hardware.hdmi.HdmiCecMessage;
+
+/**
+ * Base feature action class for SystemAudioActionFromTv and SystemAudioActionFromAvr.
+ */
+abstract class SystemAudioAction extends FeatureAction {
+ private static final String TAG = "SystemAudioAction";
+
+ // State in which waits for <SetSystemAudioMode>.
+ private static final int STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE = 1;
+
+ // State in which waits for <ReportAudioStatus>.
+ private static final int STATE_WAIT_FOR_REPORT_AUDIO_STATUS = 2;
+
+ private static final int MAX_SEND_RETRY_COUNT = 2;
+
+ private static final int ON_TIMEOUT_MS = 5000;
+ private static final int OFF_TIMEOUT_MS = TIMEOUT_MS;
+
+ // Logical address of AV Receiver.
+ protected final int mAvrLogicalAddress;
+
+ // The target audio status of the action, whether to enable the system audio mode or not.
+ protected boolean mTargetAudioStatus;
+
+ private int mSendRetryCount = 0;
+
+ /**
+ * Constructor
+ *
+ * @param service {@link HdmiControlService} instance
+ * @param sourceAddress logical address of source device (TV or STB).
+ * @param avrAddress logical address of AVR device
+ * @param targetStatus Whether to enable the system audio mode or not
+ * @throw IllegalArugmentException if device type of sourceAddress and avrAddress is invalid
+ */
+ SystemAudioAction(HdmiControlService service, int sourceAddress, int avrAddress,
+ boolean targetStatus) {
+ super(service, sourceAddress);
+ HdmiUtils.verifyAddressType(avrAddress, HdmiCec.DEVICE_AUDIO_SYSTEM);
+ mAvrLogicalAddress = avrAddress;
+ mTargetAudioStatus = targetStatus;
+ }
+
+ protected void sendSystemAudioModeRequest() {
+ int avrPhysicalAddress = mService.getAvrDeviceInfo().getPhysicalAddress();
+ HdmiCecMessage command = HdmiCecMessageBuilder.buildSystemAudioModeRequest(mSourceAddress,
+ mAvrLogicalAddress, avrPhysicalAddress, mTargetAudioStatus);
+ sendCommand(command, new HdmiControlService.SendMessageCallback() {
+ @Override
+ public void onSendCompleted(int error) {
+ if (error == HdmiControlService.SEND_RESULT_SUCCESS) {
+ mState = STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE;
+ addTimer(mState, mTargetAudioStatus ? ON_TIMEOUT_MS : OFF_TIMEOUT_MS);
+ } else {
+ setSystemAudioMode(false);
+ finish();
+ }
+ }
+ });
+ }
+
+ private void handleSendSystemAudioModeRequestTimeout() {
+ if (!mTargetAudioStatus // Don't retry for Off case.
+ || mSendRetryCount++ >= MAX_SEND_RETRY_COUNT) {
+ setSystemAudioMode(false);
+ finish();
+ return;
+ }
+ sendSystemAudioModeRequest();
+ }
+
+ protected void setSystemAudioMode(boolean mode) {
+ mService.setSystemAudioMode(mode);
+ }
+
+ protected void sendGiveAudioStatus() {
+ HdmiCecMessage command = HdmiCecMessageBuilder.buildGiveAudioStatus(mSourceAddress,
+ mAvrLogicalAddress);
+ sendCommand(command, new HdmiControlService.SendMessageCallback() {
+ @Override
+ public void onSendCompleted(int error) {
+ if (error == HdmiControlService.SEND_RESULT_SUCCESS) {
+ mState = STATE_WAIT_FOR_REPORT_AUDIO_STATUS;
+ addTimer(mState, TIMEOUT_MS);
+ } else {
+ handleSendGiveAudioStatusFailure();
+ }
+ }
+ });
+ }
+
+ private void handleSendGiveAudioStatusFailure() {
+ // TODO: Notify the failure status.
+
+ int uiCommand = mService.getSystemAudioMode()
+ ? HdmiConstants.UI_COMMAND_RESTORE_VOLUME_FUNCTION // SystemAudioMode: ON
+ : HdmiConstants.UI_COMMAND_MUTE_FUNCTION; // SystemAudioMode: OFF
+ sendUserControlPressedAndReleased(uiCommand);
+ finish();
+ }
+
+ private void sendUserControlPressedAndReleased(int uiCommand) {
+ sendCommand(HdmiCecMessageBuilder.buildUserControlPressed(
+ mSourceAddress, mAvrLogicalAddress, uiCommand));
+ sendCommand(HdmiCecMessageBuilder.buildUserControlReleased(
+ mSourceAddress, mAvrLogicalAddress));
+ }
+
+ @Override
+ final boolean processCommand(HdmiCecMessage cmd) {
+ switch (mState) {
+ case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
+ // TODO: Handle <FeatureAbort> of <SystemAudioModeRequest>
+ if (cmd.getOpcode() != HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE
+ || !HdmiUtils.checkCommandSource(cmd, mAvrLogicalAddress, TAG)) {
+ return false;
+ }
+ boolean receivedStatus = HdmiUtils.parseCommandParamSystemAudioStatus(cmd);
+ if (receivedStatus == mTargetAudioStatus) {
+ setSystemAudioMode(receivedStatus);
+ sendGiveAudioStatus();
+ } else {
+ // Unexpected response, consider the request is newly initiated by AVR.
+ // To return 'false' will initiate new SystemAudioActionFromAvr by the control
+ // service.
+ finish();
+ return false;
+ }
+ return true;
+
+ case STATE_WAIT_FOR_REPORT_AUDIO_STATUS:
+ // TODO: Handle <FeatureAbort> of <GiveAudioStatus>
+ if (cmd.getOpcode() != HdmiCec.MESSAGE_REPORT_AUDIO_STATUS
+ || !HdmiUtils.checkCommandSource(cmd, mAvrLogicalAddress, TAG)) {
+ return false;
+ }
+ byte[] params = cmd.getParams();
+ if (params.length > 0) {
+ boolean mute = (params[0] & 0x80) == 0x80;
+ int volume = params[0] & 0x7F;
+ mService.setAudioStatus(mute, volume);
+ if (mTargetAudioStatus && mute || !mTargetAudioStatus && !mute) {
+ // Toggle AVR's mute status to match with the system audio status.
+ sendUserControlPressedAndReleased(HdmiConstants.UI_COMMAND_MUTE);
+ }
+ }
+ finish();
+ return true;
+ }
+ return false;
+ }
+
+ protected void removeSystemAudioActionInProgress() {
+ mService.removeActionExcept(SystemAudioActionFromTv.class, this);
+ mService.removeActionExcept(SystemAudioActionFromAvr.class, this);
+ }
+
+ @Override
+ final void handleTimerEvent(int state) {
+ if (mState != state) {
+ return;
+ }
+ switch (mState) {
+ case STATE_WAIT_FOR_SET_SYSTEM_AUDIO_MODE:
+ handleSendSystemAudioModeRequestTimeout();
+ return;
+ case STATE_WAIT_FOR_REPORT_AUDIO_STATUS:
+ handleSendGiveAudioStatusFailure();
+ return;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
new file mode 100644
index 0000000..c5eb44b
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromAvr.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+
+/**
+ * Feature action that handles System Audio initiated by AVR devices.
+ */
+final class SystemAudioActionFromAvr extends SystemAudioAction {
+ /**
+ * Constructor
+ *
+ * @param service {@link HdmiControlService} instance
+ * @param tvAddress logical address of TV device
+ * @param avrAddress logical address of AVR device
+ * @param targetStatus Whether to enable the system audio mode or not
+ * @throw IllegalArugmentException if device type of tvAddress and avrAddress is invalid
+ */
+ SystemAudioActionFromAvr(HdmiControlService service, int tvAddress, int avrAddress,
+ boolean targetStatus) {
+ super(service, tvAddress, avrAddress, targetStatus);
+ HdmiUtils.verifyAddressType(tvAddress, HdmiCec.DEVICE_TV);
+ }
+
+ @Override
+ boolean start() {
+ removeSystemAudioActionInProgress();
+ handleSystemAudioActionFromAvr();
+ return true;
+ }
+
+ private void handleSystemAudioActionFromAvr() {
+ if (mTargetAudioStatus == mService.getSystemAudioMode()) {
+ finish();
+ return;
+ }
+ if (mService.isInPresetInstallationMode()) {
+ sendCommand(HdmiCecMessageBuilder.buildFeatureAbortCommand(
+ mSourceAddress, mAvrLogicalAddress,
+ HdmiCec.MESSAGE_SET_SYSTEM_AUDIO_MODE, HdmiConstants.ABORT_REFUSED));
+ mTargetAudioStatus = false;
+ sendSystemAudioModeRequest();
+ return;
+ }
+ // TODO: Stop the action for System Audio Mode initialization if it is running.
+ if (mTargetAudioStatus) {
+ setSystemAudioMode(true);
+ sendGiveAudioStatus();
+ } else {
+ setSystemAudioMode(false);
+ finish();
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
new file mode 100644
index 0000000..9994de6
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/SystemAudioActionFromTv.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.hardware.hdmi.HdmiCec;
+
+
+/**
+ * Feature action that handles System Audio initiated by TV devices.
+ */
+final class SystemAudioActionFromTv extends SystemAudioAction {
+ /**
+ * Constructor
+ *
+ * @param service {@link HdmiControlService} instance
+ * @param tvAddress logical address of TV device
+ * @param avrAddress logical address of AVR device
+ * @param targetStatus Whether to enable the system audio mode or not
+ * @throw IllegalArugmentException if device type of tvAddress is invalid
+ */
+ SystemAudioActionFromTv(HdmiControlService service, int tvAddress, int avrAddress,
+ boolean targetStatus) {
+ super(service, tvAddress, avrAddress, targetStatus);
+ HdmiUtils.verifyAddressType(tvAddress, HdmiCec.DEVICE_TV);
+ }
+
+ @Override
+ boolean start() {
+ // TODO: Check HDMI-CEC is enabled.
+ // TODO: Move to the waiting state if currently a routing change is in progress.
+
+ removeSystemAudioActionInProgress();
+ sendSystemAudioModeRequest();
+ return true;
+ }
+}
diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java
index 51ee93b..2699fea 100644
--- a/services/core/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java
@@ -96,7 +96,7 @@ public class FlpHardwareProvider {
Looper.myLooper());
}
- public boolean isSupported() {
+ public static boolean isSupported() {
return nativeIsSupported();
}
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
index dbfb1cf..15f0ebf 100644
--- a/services/core/java/com/android/server/notification/ConditionProviders.java
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -16,18 +16,14 @@
package com.android.server.notification;
-import android.app.AlarmManager;
-import android.app.PendingIntent;
-import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
import android.net.Uri;
import android.os.Handler;
import android.os.IBinder;
import android.os.IInterface;
import android.os.RemoteException;
+import android.os.UserHandle;
import android.provider.Settings;
import android.provider.Settings.Global;
import android.service.notification.Condition;
@@ -35,7 +31,6 @@ import android.service.notification.ConditionProviderService;
import android.service.notification.IConditionListener;
import android.service.notification.IConditionProvider;
import android.service.notification.ZenModeConfig;
-import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Slog;
@@ -45,7 +40,7 @@ import com.android.internal.R;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Date;
+import java.util.Objects;
public class ConditionProviders extends ManagedServices {
private static final Condition[] NO_CONDITIONS = new Condition[0];
@@ -54,7 +49,9 @@ public class ConditionProviders extends ManagedServices {
private final ArrayMap<IBinder, IConditionListener> mListeners
= new ArrayMap<IBinder, IConditionListener>();
private final ArrayList<ConditionRecord> mRecords = new ArrayList<ConditionRecord>();
- private final CountdownConditionHelper mCountdownHelper = new CountdownConditionHelper();
+ private final CountdownConditionProvider mCountdown = new CountdownConditionProvider();
+
+ private Uri mExitConditionId;
public ConditionProviders(Context context, Handler handler,
UserProfiles userProfiles, ZenModeHelper zenModeHelper) {
@@ -86,10 +83,13 @@ public class ConditionProviders extends ManagedServices {
}
pw.print(" mRecords("); pw.print(mRecords.size()); pw.println("):");
for (int i = 0; i < mRecords.size(); i++) {
- pw.print(" "); pw.println(mRecords.get(i));
+ final ConditionRecord r = mRecords.get(i);
+ pw.print(" "); pw.println(r);
+ final String countdownDesc = CountdownConditionProvider.tryParseDescription(r.id);
+ if (countdownDesc != null) {
+ pw.print(" ("); pw.print(countdownDesc); pw.println(")");
+ }
}
- pw.print(" mCountdownHelper: ");
- pw.println(mCountdownHelper.getCurrentConditionDescription());
}
}
@@ -99,6 +99,14 @@ public class ConditionProviders extends ManagedServices {
}
@Override
+ public void onBootPhaseAppsCanStart() {
+ super.onBootPhaseAppsCanStart();
+ mCountdown.attachBase(mContext);
+ registerService(mCountdown.asInterface(), CountdownConditionProvider.COMPONENT,
+ UserHandle.USER_OWNER);
+ }
+
+ @Override
protected void onServiceAdded(ManagedServiceInfo info) {
Slog.d(TAG, "onServiceAdded " + info);
final IConditionProvider provider = provider(info);
@@ -262,6 +270,15 @@ public class ConditionProviders extends ManagedServices {
public void setZenModeCondition(Uri conditionId) {
if (DEBUG) Slog.d(TAG, "setZenModeCondition " + conditionId);
synchronized(mMutex) {
+ if (ZenModeConfig.isValidCountdownConditionId(conditionId)) {
+ // constructed by the client, make sure the record exists...
+ final ConditionRecord r = getRecordLocked(conditionId,
+ CountdownConditionProvider.COMPONENT);
+ if (r.info == null) {
+ // ... and is associated with the in-process service
+ r.info = checkServiceTokenLocked(mCountdown.asInterface());
+ }
+ }
final int N = mRecords.size();
for (int i = 0; i < N; i++) {
final ConditionRecord r = mRecords.get(i);
@@ -276,8 +293,11 @@ public class ConditionProviders extends ManagedServices {
r.isManual = true;
}
}
+ if (!Objects.equals(mExitConditionId, conditionId)) {
+ mExitConditionId = conditionId;
+ saveZenConfigLocked();
+ }
}
- mCountdownHelper.setZenModeCondition(conditionId);
}
private void subscribeLocked(ConditionRecord r) {
@@ -395,6 +415,7 @@ public class ConditionProviders extends ManagedServices {
return;
}
synchronized (mMutex) {
+ mExitConditionId = config.exitConditionId;
if (config.conditionComponents == null || config.conditionIds == null
|| config.conditionComponents.length != config.conditionIds.length) {
if (DEBUG) Slog.d(TAG, "loadZenConfig: no conditions");
@@ -441,82 +462,11 @@ public class ConditionProviders extends ManagedServices {
config.conditionIds[i] = r.id;
}
}
+ config.exitConditionId = mExitConditionId;
if (DEBUG) Slog.d(TAG, "Setting zen config to: " + config);
mZenModeHelper.setConfig(config);
}
- private final class CountdownConditionHelper extends BroadcastReceiver {
- private static final String ACTION = "CountdownConditionHelper";
- private static final int REQUEST_CODE = 100;
- private static final String EXTRA_TIME = "time";
-
- private long mCurrent;
-
- public CountdownConditionHelper() {
- mContext.registerReceiver(this, new IntentFilter(ACTION));
- }
-
- public void setZenModeCondition(Uri conditionId) {
- final long time = tryParseCondition(conditionId);
- final AlarmManager alarms = (AlarmManager)
- mContext.getSystemService(Context.ALARM_SERVICE);
- final Intent intent = new Intent(ACTION).putExtra(EXTRA_TIME, time)
- .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
- final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, REQUEST_CODE,
- intent, PendingIntent.FLAG_UPDATE_CURRENT);
- alarms.cancel(pendingIntent);
- mCurrent = time;
- if (time > 0) {
- final long now = System.currentTimeMillis();
- final CharSequence span =
- DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
- Slog.d(TAG, String.format("Scheduling %s for %s, %s in the future (%s), now=%s",
- ACTION, ts(time), time - now, span, ts(now)));
- alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
- }
- }
-
- public String getCurrentConditionDescription() {
- if (mCurrent == 0) return null;
- final long time = mCurrent;
- final long now = System.currentTimeMillis();
- final CharSequence span =
- DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
- return String.format("Scheduled for %s, %s in the future (%s), now=%s",
- ts(time), time - now, span, ts(now));
- }
-
- private String ts(long time) {
- return new Date(time) + " (" + time + ")";
- }
-
- @Override
- public void onReceive(Context context, Intent intent) {
- if (ACTION.equals(intent.getAction())) {
- final long time = intent.getLongExtra(EXTRA_TIME, 0);
- Slog.d(TAG, "Countdown condition fired. time=" + time + " mCurrent=" + mCurrent);
- if (time > 0 && time == mCurrent) {
- // countdown condition is still the manual condition, leave zen
- mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF);
- ConditionProviders.this.setZenModeCondition(null);
- }
- }
- }
-
- private long tryParseCondition(Uri conditionId) {
- // condition://android/countdown/1399917958951
- if (!Condition.isValidId(conditionId, "android")) return 0;
- if (conditionId.getPathSegments().size() != 2
- || !"countdown".equals(conditionId.getPathSegments().get(0))) return 0;
- try {
- return Long.parseLong(conditionId.getPathSegments().get(1));
- } catch (RuntimeException e) {
- Slog.w(TAG, "Error parsing countdown condition: " + conditionId, e);
- return 0;
- }
- }
- }
-
private class ZenModeHelperCallback extends ZenModeHelper.Callback {
@Override
void onConfigChanged() {
diff --git a/services/core/java/com/android/server/notification/CountdownConditionProvider.java b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
new file mode 100644
index 0000000..0884f76
--- /dev/null
+++ b/services/core/java/com/android/server/notification/CountdownConditionProvider.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.app.AlarmManager;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.service.notification.ConditionProviderService;
+import android.service.notification.IConditionProvider;
+import android.service.notification.ZenModeConfig;
+import android.text.format.DateUtils;
+import android.util.Slog;
+
+import java.util.Date;
+
+/** Built-in zen condition provider for simple time-based conditions */
+public class CountdownConditionProvider extends ConditionProviderService {
+ private static final String TAG = "CountdownConditionProvider";
+ private static final boolean DEBUG = false;
+
+ public static final ComponentName COMPONENT =
+ new ComponentName("android", CountdownConditionProvider.class.getName());
+
+ private static final String ACTION = CountdownConditionProvider.class.getName();
+ private static final int REQUEST_CODE = 100;
+ private static final String EXTRA_CONDITION_ID = "condition_id";
+
+ private final Context mContext = this;
+ private final Receiver mReceiver = new Receiver();
+
+ private boolean mConnected;
+
+ public CountdownConditionProvider() {
+ if (DEBUG) Slog.d(TAG, "new CountdownConditionProvider()");
+ }
+
+ @Override
+ public void onConnected() {
+ if (DEBUG) Slog.d(TAG, "onConnected");
+ mContext.registerReceiver(mReceiver, new IntentFilter(ACTION));
+ mConnected = true;
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (DEBUG) Slog.d(TAG, "onDestroy");
+ if (mConnected) {
+ mContext.unregisterReceiver(mReceiver);
+ }
+ mConnected = false;
+ }
+
+ @Override
+ public void onRequestConditions(int relevance) {
+ // by convention
+ }
+
+ @Override
+ public void onSubscribe(Uri conditionId) {
+ if (DEBUG) Slog.d(TAG, "onSubscribe " + conditionId);
+ final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
+ final AlarmManager alarms = (AlarmManager)
+ mContext.getSystemService(Context.ALARM_SERVICE);
+ final Intent intent = new Intent(ACTION).putExtra(EXTRA_CONDITION_ID, conditionId)
+ .setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+ final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, REQUEST_CODE,
+ intent, PendingIntent.FLAG_UPDATE_CURRENT);
+ alarms.cancel(pendingIntent);
+ if (time > 0) {
+ final long now = System.currentTimeMillis();
+ final CharSequence span =
+ DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
+ if (DEBUG) Slog.d(TAG, String.format(
+ "Scheduling %s for %s, %s in the future (%s), now=%s",
+ ACTION, ts(time), time - now, span, ts(now)));
+ alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
+ }
+ }
+
+ @Override
+ public void onUnsubscribe(Uri conditionId) {
+ // noop
+ }
+
+ private final class Receiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (ACTION.equals(intent.getAction())) {
+ final Uri conditionId = intent.getParcelableExtra(EXTRA_CONDITION_ID);
+ final long time = ZenModeConfig.tryParseCountdownConditionId(conditionId);
+ if (DEBUG) Slog.d(TAG, "Countdown condition fired: " + conditionId);
+ if (time > 0) {
+ notifyCondition(newCondition(time, Condition.STATE_FALSE));
+ }
+ }
+ }
+ }
+
+ private static final Condition newCondition(long time, int state) {
+ return new Condition(ZenModeConfig.toCountdownConditionId(time),
+ "", "", "", 0, state,Condition.FLAG_RELEVANT_NOW);
+ }
+
+ public static String tryParseDescription(Uri conditionUri) {
+ final long time = ZenModeConfig.tryParseCountdownConditionId(conditionUri);
+ if (time == 0) return null;
+ final long now = System.currentTimeMillis();
+ final CharSequence span =
+ DateUtils.getRelativeTimeSpanString(time, now, DateUtils.MINUTE_IN_MILLIS);
+ return String.format("Scheduled for %s, %s in the future (%s), now=%s",
+ ts(time), time - now, span, ts(now));
+ }
+
+ private static String ts(long time) {
+ return new Date(time) + " (" + time + ")";
+ }
+
+ public void attachBase(Context base) {
+ attachBaseContext(base);
+ }
+
+ public IConditionProvider asInterface() {
+ return (IConditionProvider) onBind(null);
+ }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index cb78a45..495db20 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1238,7 +1238,7 @@ public class NotificationManagerService extends SystemService {
@Override
public ZenModeConfig getZenModeConfig() {
- checkCallerIsSystem();
+ enforceSystemOrSystemUI("INotificationManager.getZenModeConfig");
return mZenModeHelper.getConfig();
}
@@ -1486,6 +1486,11 @@ public class NotificationManagerService extends SystemService {
pkg, opPkg, id, tag, callingUid, callingPid, score, notification,
user);
NotificationRecord r = new NotificationRecord(n);
+ NotificationRecord old = mNotificationsByKey.get(n.getKey());
+ if (old != null) {
+ // Retain ranking information from previous record
+ r.copyRankingInformation(old);
+ }
if (!mSignalExtractors.isEmpty()) {
for (NotificationSignalExtractor extractor : mSignalExtractors) {
try {
@@ -1514,15 +1519,6 @@ public class NotificationManagerService extends SystemService {
}
synchronized (mNotificationList) {
- applyZenModeLocked(r);
-
- // Should this notification make noise, vibe, or use the LED?
- final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) &&
- !r.isIntercepted();
- if (DBG || r.isIntercepted()) Slog.v(TAG,
- "pkg=" + pkg + " canInterrupt=" + canInterrupt +
- " intercept=" + r.isIntercepted());
- NotificationRecord old = null;
int index = indexOfNotificationLocked(n.getKey());
if (index < 0) {
mNotificationList.add(r);
@@ -1534,12 +1530,18 @@ public class NotificationManagerService extends SystemService {
// Make sure we don't lose the foreground service state.
notification.flags |=
old.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE;
- // Retain ranking information from previous record
- r.copyRankingInformation(old);
mNotificationsByKey.remove(old.sbn.getKey());
}
mNotificationsByKey.put(n.getKey(), r);
+ applyZenModeLocked(r);
+ // Should this notification make noise, vibe, or use the LED?
+ final boolean canInterrupt = (score >= SCORE_INTERRUPTION_THRESHOLD) &&
+ !r.isIntercepted();
+ if (DBG || r.isIntercepted()) Slog.v(TAG,
+ "pkg=" + pkg + " canInterrupt=" + canInterrupt +
+ " intercept=" + r.isIntercepted());
+
Collections.sort(mNotificationList, mRankingComparator);
// Ensure if this is a foreground service that the proper additional
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 13cc98c..bb93663 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -40,6 +40,7 @@ import com.android.internal.R;
import com.android.internal.app.IMediaContainerService;
import com.android.internal.app.ResolverActivity;
import com.android.internal.content.NativeLibraryHelper;
+import com.android.internal.content.NativeLibraryHelper.ApkHandle;
import com.android.internal.content.PackageHelper;
import com.android.internal.util.FastPrintWriter;
import com.android.internal.util.FastXmlSerializer;
@@ -4148,7 +4149,7 @@ public class PackageManagerService extends IPackageManager.Stub {
continue;
}
PackageParser.Package pkg = scanPackageLI(file,
- flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null);
+ flags|PackageParser.PARSE_MUST_BE_APK, scanMode, currentTime, null, null);
// Don't mess around with apps in system partition.
if (pkg == null && (flags & PackageParser.PARSE_IS_SYSTEM) == 0 &&
mLastScanError == PackageManager.INSTALL_FAILED_INVALID_APK) {
@@ -4215,7 +4216,7 @@ public class PackageManagerService extends IPackageManager.Stub {
* Returns null in case of errors and the error code is stored in mLastScanError
*/
private PackageParser.Package scanPackageLI(File scanFile,
- int parseFlags, int scanMode, long currentTime, UserHandle user) {
+ int parseFlags, int scanMode, long currentTime, UserHandle user, String abiOverride) {
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
String scanPath = scanFile.getPath();
if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanPath);
@@ -4283,7 +4284,7 @@ public class PackageManagerService extends IPackageManager.Stub {
mLastScanError = PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
return null;
} else {
- // The current app on the system partion is better than
+ // The current app on the system partition is better than
// what we have updated to on the data partition; switch
// back to the system partition version.
// At this point, its safely assumed that package installation for
@@ -4402,7 +4403,7 @@ public class PackageManagerService extends IPackageManager.Stub {
setApplicationInfoPaths(pkg, codePath, resPath);
// Note that we invoke the following method only if we are about to unpack an application
PackageParser.Package scannedPkg = scanPackageLI(pkg, parseFlags, scanMode
- | SCAN_UPDATE_SIGNATURE, currentTime, user);
+ | SCAN_UPDATE_SIGNATURE, currentTime, user, abiOverride);
/*
* If the system app should be overridden by a previously installed
@@ -4945,7 +4946,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
private PackageParser.Package scanPackageLI(PackageParser.Package pkg,
- int parseFlags, int scanMode, long currentTime, UserHandle user) {
+ int parseFlags, int scanMode, long currentTime, UserHandle user, String abiOverride) {
File scanFile = new File(pkg.mScanPath);
if (scanFile == null || pkg.applicationInfo.sourceDir == null ||
pkg.applicationInfo.publicSourceDir == null) {
@@ -5395,7 +5396,22 @@ public class PackageManagerService extends IPackageManager.Stub {
* only for non-system apps and system app upgrades.
*/
if (pkg.applicationInfo.nativeLibraryDir != null) {
+ final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
try {
+ // Enable gross and lame hacks for apps that are built with old
+ // SDK tools. We must scan their APKs for renderscript bitcode and
+ // not launch them if it's present. Don't bother checking on devices
+ // that don't have 64 bit support.
+ String[] abiList = Build.SUPPORTED_ABIS;
+ boolean hasLegacyRenderscriptBitcode = false;
+ if (abiOverride != null) {
+ abiList = new String[] { abiOverride };
+ } else if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
+ NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+ abiList = Build.SUPPORTED_32_BIT_ABIS;
+ hasLegacyRenderscriptBitcode = true;
+ }
+
File nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
final String dataPathString = dataPath.getCanonicalPath();
@@ -5411,21 +5427,26 @@ public class PackageManagerService extends IPackageManager.Stub {
Log.i(TAG, "removed obsolete native libraries for system package "
+ path);
}
-
- setInternalAppAbi(pkg, pkgSetting);
+ if (abiOverride != null || hasLegacyRenderscriptBitcode) {
+ pkg.applicationInfo.cpuAbi = abiList[0];
+ pkgSetting.cpuAbiString = abiList[0];
+ } else {
+ setInternalAppAbi(pkg, pkgSetting);
+ }
} else {
if (!isForwardLocked(pkg) && !isExternal(pkg)) {
/*
- * Update native library dir if it starts with
- * /data/data
- */
+ * Update native library dir if it starts with
+ * /data/data
+ */
if (nativeLibraryDir.getPath().startsWith(dataPathString)) {
setInternalAppNativeLibraryPath(pkg, pkgSetting);
nativeLibraryDir = new File(pkg.applicationInfo.nativeLibraryDir);
}
try {
- int copyRet = copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir);
+ int copyRet = copyNativeLibrariesForInternalApp(handle,
+ nativeLibraryDir, abiList);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
Slog.e(TAG, "Unable to copy native libraries");
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
@@ -5435,7 +5456,9 @@ public class PackageManagerService extends IPackageManager.Stub {
// We've successfully copied native libraries across, so we make a
// note of what ABI we're using
if (copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
- pkg.applicationInfo.cpuAbi = Build.SUPPORTED_ABIS[copyRet];
+ pkg.applicationInfo.cpuAbi = abiList[copyRet];
+ } else if (abiOverride != null || hasLegacyRenderscriptBitcode) {
+ pkg.applicationInfo.cpuAbi = abiList[0];
} else {
pkg.applicationInfo.cpuAbi = null;
}
@@ -5452,20 +5475,22 @@ public class PackageManagerService extends IPackageManager.Stub {
// to clean this up but we'll need to change the interface between this service
// and IMediaContainerService (but doing so will spread this logic out, rather
// than centralizing it).
- final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
- final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+ final int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
if (abi >= 0) {
- pkg.applicationInfo.cpuAbi = Build.SUPPORTED_ABIS[abi];
+ pkg.applicationInfo.cpuAbi = abiList[abi];
} else if (abi == PackageManager.NO_NATIVE_LIBRARIES) {
// Note that (non upgraded) system apps will not have any native
// libraries bundled in their APK, but we're guaranteed not to be
// such an app at this point.
- pkg.applicationInfo.cpuAbi = null;
+ if (abiOverride != null || hasLegacyRenderscriptBitcode) {
+ pkg.applicationInfo.cpuAbi = abiList[0];
+ } else {
+ pkg.applicationInfo.cpuAbi = null;
+ }
} else {
mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
return null;
}
- handle.close();
}
if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
@@ -5482,8 +5507,12 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
}
+
+ pkgSetting.cpuAbiString = pkg.applicationInfo.cpuAbi;
} catch (IOException ioe) {
Slog.e(TAG, "Unable to get canonical file " + ioe.toString());
+ } finally {
+ handle.close();
}
}
pkg.mScanPath = path;
@@ -6175,8 +6204,8 @@ public class PackageManagerService extends IPackageManager.Stub {
}
}
- private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
- throws IOException {
+ private static int copyNativeLibrariesForInternalApp(ApkHandle handle,
+ final File nativeLibraryDir, String[] abiList) throws IOException {
if (!nativeLibraryDir.isDirectory()) {
nativeLibraryDir.delete();
@@ -6198,21 +6227,16 @@ public class PackageManagerService extends IPackageManager.Stub {
* If this is an internal application or our nativeLibraryPath points to
* the app-lib directory, unpack the libraries if necessary.
*/
- final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
- try {
- int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
- if (abi >= 0) {
- int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
- nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
- if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
- return copyRet;
- }
+ int abi = NativeLibraryHelper.findSupportedAbi(handle, abiList);
+ if (abi >= 0) {
+ int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+ nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
+ if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+ return copyRet;
}
-
- return abi;
- } finally {
- handle.close();
}
+
+ return abi;
}
private void killApplication(String pkgName, int appId, String reason) {
@@ -7536,7 +7560,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
p = scanPackageLI(fullPath, flags,
SCAN_MONITOR | SCAN_NO_PATHS | SCAN_UPDATE_TIME,
- System.currentTimeMillis(), UserHandle.ALL);
+ System.currentTimeMillis(), UserHandle.ALL, null);
if (p != null) {
/*
* TODO this seems dangerous as the package may have
@@ -7657,6 +7681,16 @@ public class PackageManagerService extends IPackageManager.Stub {
if (observer == null && observer2 == null) {
throw new IllegalArgumentException("No install observer supplied");
}
+ installPackageWithVerificationEncryptionAndAbiOverrideEtc(packageURI, observer, observer2,
+ flags, installerPackageName, verificationParams, encryptionParams, null);
+ }
+
+ @Override
+ public void installPackageWithVerificationEncryptionAndAbiOverrideEtc(Uri packageURI,
+ IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
+ int flags, String installerPackageName,
+ VerificationParams verificationParams, ContainerEncryptionParams encryptionParams,
+ String packageAbiOverride) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES,
null);
@@ -7696,7 +7730,8 @@ public class PackageManagerService extends IPackageManager.Stub {
final Message msg = mHandler.obtainMessage(INIT_COPY);
msg.obj = new InstallParams(packageURI, observer, observer2, filteredFlags,
- installerPackageName, verificationParams, encryptionParams, user);
+ installerPackageName, verificationParams, encryptionParams, user,
+ packageAbiOverride);
mHandler.sendMessage(msg);
}
@@ -8405,11 +8440,14 @@ public class PackageManagerService extends IPackageManager.Stub {
private int mRet;
private File mTempPackage;
final ContainerEncryptionParams encryptionParams;
+ final String packageAbiOverride;
+ final String packageInstructionSetOverride;
InstallParams(Uri packageURI,
IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
int flags, String installerPackageName, VerificationParams verificationParams,
- ContainerEncryptionParams encryptionParams, UserHandle user) {
+ ContainerEncryptionParams encryptionParams, UserHandle user,
+ String packageAbiOverride) {
super(user);
this.mPackageURI = packageURI;
this.flags = flags;
@@ -8418,6 +8456,9 @@ public class PackageManagerService extends IPackageManager.Stub {
this.installerPackageName = installerPackageName;
this.verificationParams = verificationParams;
this.encryptionParams = encryptionParams;
+ this.packageAbiOverride = packageAbiOverride;
+ this.packageInstructionSetOverride = (packageAbiOverride == null) ?
+ packageAbiOverride : VMRuntime.getInstructionSet(packageAbiOverride);
}
@Override
@@ -8563,7 +8604,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Remote call to find out default install location
final String packageFilePath = packageFile.getAbsolutePath();
pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath, flags,
- lowThreshold);
+ lowThreshold, packageAbiOverride);
/*
* If we have too little free space, try to free cache
@@ -8572,10 +8613,10 @@ public class PackageManagerService extends IPackageManager.Stub {
if (pkgLite.recommendedInstallLocation
== PackageHelper.RECOMMEND_FAILED_INSUFFICIENT_STORAGE) {
final long size = mContainerService.calculateInstalledSize(
- packageFilePath, isForwardLocked());
+ packageFilePath, isForwardLocked(), packageAbiOverride);
if (mInstaller.freeCache(size + lowThreshold) >= 0) {
pkgLite = mContainerService.getMinimalPackageInfo(packageFilePath,
- flags, lowThreshold);
+ flags, lowThreshold, packageAbiOverride);
}
/*
* The cache free must have deleted the file we
@@ -8995,11 +9036,12 @@ public class PackageManagerService extends IPackageManager.Stub {
final ManifestDigest manifestDigest;
final UserHandle user;
final String instructionSet;
+ final String abiOverride;
InstallArgs(Uri packageURI,
IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
int flags, String installerPackageName, ManifestDigest manifestDigest,
- UserHandle user, String instructionSet) {
+ UserHandle user, String instructionSet, String abiOverride) {
this.packageURI = packageURI;
this.flags = flags;
this.observer = observer;
@@ -9008,6 +9050,7 @@ public class PackageManagerService extends IPackageManager.Stub {
this.manifestDigest = manifestDigest;
this.user = user;
this.instructionSet = instructionSet;
+ this.abiOverride = abiOverride;
}
abstract void createCopyFile();
@@ -9063,12 +9106,13 @@ public class PackageManagerService extends IPackageManager.Stub {
FileInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
- params.getUser(), null /* instruction set */);
+ params.getUser(), params.packageInstructionSetOverride,
+ params.packageAbiOverride);
}
FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
String instructionSet) {
- super(null, null, null, 0, null, null, null, instructionSet);
+ super(null, null, null, 0, null, null, null, instructionSet, null);
File codeFile = new File(fullCodePath);
installDir = codeFile.getParentFile();
codeFileName = fullCodePath;
@@ -9077,7 +9121,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) {
- super(packageURI, null, null, 0, null, null, null, instructionSet);
+ super(packageURI, null, null, 0, null, null, null, instructionSet, null);
installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
String apkName = getNextCodePath(null, pkgName, ".apk");
codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -9181,14 +9225,26 @@ public class PackageManagerService extends IPackageManager.Stub {
NativeLibraryHelper.removeNativeBinariesFromDirLI(nativeLibraryFile);
nativeLibraryFile.delete();
}
+
+ final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codeFile);
+ String[] abiList = (abiOverride != null) ?
+ new String[] { abiOverride } : Build.SUPPORTED_ABIS;
try {
- int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
+ if (Build.SUPPORTED_64_BIT_ABIS.length > 0 &&
+ abiOverride == null &&
+ NativeLibraryHelper.hasRenderscriptBitcode(handle)) {
+ abiList = Build.SUPPORTED_32_BIT_ABIS;
+ }
+
+ int copyRet = copyNativeLibrariesForInternalApp(handle, nativeLibraryFile, abiList);
if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
return copyRet;
}
} catch (IOException e) {
Slog.e(TAG, "Copying native libraries failed", e);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+ } finally {
+ handle.close();
}
return ret;
@@ -9403,14 +9459,15 @@ public class PackageManagerService extends IPackageManager.Stub {
AsecInstallArgs(InstallParams params) {
super(params.getPackageUri(), params.observer, params.observer2, params.flags,
params.installerPackageName, params.getManifestDigest(),
- params.getUser(), null /* instruction set */);
+ params.getUser(), params.packageInstructionSetOverride,
+ params.packageAbiOverride);
}
AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
String instructionSet, boolean isExternal, boolean isForwardLocked) {
super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
- null, null, null, instructionSet);
+ null, null, null, instructionSet, null);
// Extract cid from fullCodePath
int eidx = fullCodePath.lastIndexOf("/");
String subStr1 = fullCodePath.substring(0, eidx);
@@ -9422,7 +9479,7 @@ public class PackageManagerService extends IPackageManager.Stub {
AsecInstallArgs(String cid, String instructionSet, boolean isForwardLocked) {
super(null, null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
- null, null, null, instructionSet);
+ null, null, null, instructionSet, null);
this.cid = cid;
setCachePath(PackageHelper.getSdDir(cid));
}
@@ -9431,7 +9488,7 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean isExternal, boolean isForwardLocked) {
super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
| (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
- null, null, null, instructionSet);
+ null, null, null, instructionSet, null);
this.cid = cid;
}
@@ -9443,7 +9500,7 @@ public class PackageManagerService extends IPackageManager.Stub {
try {
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
- return imcs.checkExternalFreeStorage(packageURI, isFwdLocked());
+ return imcs.checkExternalFreeStorage(packageURI, isFwdLocked(), abiOverride);
} finally {
mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
@@ -9469,7 +9526,8 @@ public class PackageManagerService extends IPackageManager.Stub {
mContext.grantUriPermission(DEFAULT_CONTAINER_PACKAGE, packageURI,
Intent.FLAG_GRANT_READ_URI_PERMISSION);
newCachePath = imcs.copyResourceToContainer(packageURI, cid, getEncryptKey(),
- RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked());
+ RES_FILE_NAME, PUBLIC_RES_FILE_NAME, isExternal(), isFwdLocked(),
+ abiOverride);
} finally {
mContext.revokeUriPermission(packageURI, Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
@@ -9777,7 +9835,7 @@ public class PackageManagerService extends IPackageManager.Stub {
*/
private void installNewPackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, UserHandle user,
- String installerPackageName, PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res, String abiOverride) {
// Remember this for later, in case we need to rollback this install
String pkgName = pkg.packageName;
@@ -9805,7 +9863,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
PackageParser.Package newPackage = scanPackageLI(pkg, parseFlags, scanMode,
- System.currentTimeMillis(), user);
+ System.currentTimeMillis(), user, abiOverride);
if (newPackage == null) {
Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -9832,7 +9890,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private void replacePackageLI(PackageParser.Package pkg,
int parseFlags, int scanMode, UserHandle user,
- String installerPackageName, PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res, String abiOverride) {
PackageParser.Package oldPackage;
String pkgName = pkg.packageName;
@@ -9861,17 +9919,19 @@ public class PackageManagerService extends IPackageManager.Stub {
boolean sysPkg = (isSystemApp(oldPackage));
if (sysPkg) {
replaceSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
- user, allUsers, perUserInstalled, installerPackageName, res);
+ user, allUsers, perUserInstalled, installerPackageName, res,
+ abiOverride);
} else {
replaceNonSystemPackageLI(oldPackage, pkg, parseFlags, scanMode,
- user, allUsers, perUserInstalled, installerPackageName, res);
+ user, allUsers, perUserInstalled, installerPackageName, res,
+ abiOverride);
}
}
private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
int[] allUsers, boolean[] perUserInstalled,
- String installerPackageName, PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res, String abiOverride) {
PackageParser.Package newPackage = null;
String pkgName = deletedPackage.packageName;
boolean deletedPkg = true;
@@ -9896,7 +9956,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Successfully deleted the old package. Now proceed with re-installation
mLastScanError = PackageManager.INSTALL_SUCCEEDED;
newPackage = scanPackageLI(pkg, parseFlags, scanMode | SCAN_UPDATE_TIME,
- System.currentTimeMillis(), user);
+ System.currentTimeMillis(), user, abiOverride);
if (newPackage == null) {
Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -9925,7 +9985,7 @@ public class PackageManagerService extends IPackageManager.Stub {
}
// Since we failed to install the new package we need to restore the old
// package that we deleted.
- if(deletedPkg) {
+ if (deletedPkg) {
if (DEBUG_INSTALL) Slog.d(TAG, "Install failed, reinstalling: " + deletedPackage);
File restoreFile = new File(deletedPackage.mPath);
// Parse old package
@@ -9936,7 +9996,7 @@ public class PackageManagerService extends IPackageManager.Stub {
int oldScanMode = (oldOnSd ? 0 : SCAN_MONITOR) | SCAN_UPDATE_SIGNATURE
| SCAN_UPDATE_TIME;
if (scanPackageLI(restoreFile, oldParseFlags, oldScanMode,
- origUpdateTime, null) == null) {
+ origUpdateTime, null, null) == null) {
Slog.e(TAG, "Failed to restore package : " + pkgName + " after failed upgrade");
return;
}
@@ -9956,7 +10016,7 @@ public class PackageManagerService extends IPackageManager.Stub {
private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
PackageParser.Package pkg, int parseFlags, int scanMode, UserHandle user,
int[] allUsers, boolean[] perUserInstalled,
- String installerPackageName, PackageInstalledInfo res) {
+ String installerPackageName, PackageInstalledInfo res, String abiOverride) {
if (DEBUG_INSTALL) Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
+ ", old=" + deletedPackage);
PackageParser.Package newPackage = null;
@@ -10010,7 +10070,7 @@ public class PackageManagerService extends IPackageManager.Stub {
// Successfully disabled the old package. Now proceed with re-installation
res.returnCode = mLastScanError = PackageManager.INSTALL_SUCCEEDED;
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
- newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user);
+ newPackage = scanPackageLI(pkg, parseFlags, scanMode, 0, user, abiOverride);
if (newPackage == null) {
Slog.w(TAG, "Package couldn't be installed in " + pkg.mPath);
if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -10044,7 +10104,7 @@ public class PackageManagerService extends IPackageManager.Stub {
removeInstalledPackageLI(newPackage, true);
}
// Add back the old system package
- scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user);
+ scanPackageLI(oldPkg, parseFlags, SCAN_MONITOR | SCAN_UPDATE_SIGNATURE, 0, user, null);
// Restore the old system information in Settings
synchronized(mPackages) {
if (updatedSettings) {
@@ -10278,10 +10338,10 @@ public class PackageManagerService extends IPackageManager.Stub {
pkg.applicationInfo.nativeLibraryDir = args.getNativeLibraryPath();
if (replace) {
replacePackageLI(pkg, parseFlags, scanMode, args.user,
- installerPackageName, res);
+ installerPackageName, res, args.abiOverride);
} else {
installNewPackageLI(pkg, parseFlags, scanMode | SCAN_DELETE_DATA_ON_FAILURES, args.user,
- installerPackageName, res);
+ installerPackageName, res, args.abiOverride);
}
synchronized (mPackages) {
final PackageSetting ps = mSettings.mPackages.get(pkgName);
@@ -10698,7 +10758,7 @@ public class PackageManagerService extends IPackageManager.Stub {
parseFlags |= PackageParser.PARSE_IS_PRIVILEGED;
}
PackageParser.Package newPkg = scanPackageLI(disabledPs.codePath,
- parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null);
+ parseFlags, SCAN_MONITOR | SCAN_NO_PATHS, 0, null, null);
if (newPkg == null) {
Slog.w(TAG, "Failed to restore system package:" + newPs.name
@@ -12511,7 +12571,7 @@ public class PackageManagerService extends IPackageManager.Stub {
doGc = true;
synchronized (mInstallLock) {
final PackageParser.Package pkg = scanPackageLI(new File(codePath), parseFlags,
- 0, 0, null);
+ 0, 0, null, null);
// Scan the package
if (pkg != null) {
/*
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index 1629a61..32546df 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -50,6 +50,7 @@ import android.os.UserManager;
import android.service.trust.TrustAgentService;
import android.util.ArraySet;
import android.util.AttributeSet;
+import android.util.Log;
import android.util.Slog;
import android.util.SparseBooleanArray;
import android.util.Xml;
@@ -81,6 +82,7 @@ public class TrustManagerService extends SystemService {
private static final Intent TRUST_AGENT_INTENT =
new Intent(TrustAgentService.SERVICE_INTERFACE);
+ private static final String PERMISSION_PROVIDE_AGENT = Manifest.permission.PROVIDE_TRUST_AGENT;
private static final int MSG_REGISTER_LISTENER = 1;
private static final int MSG_UNREGISTER_LISTENER = 2;
@@ -182,6 +184,15 @@ public class TrustManagerService extends SystemService {
PackageManager.GET_META_DATA, userInfo.id);
for (ResolveInfo resolveInfo : resolveInfos) {
if (resolveInfo.serviceInfo == null) continue;
+
+ String packageName = resolveInfo.serviceInfo.packageName;
+ if (pm.checkPermission(PERMISSION_PROVIDE_AGENT, packageName)
+ != PackageManager.PERMISSION_GRANTED) {
+ Log.w(TAG, "Skipping agent because package " + packageName
+ + " does not have permission " + PERMISSION_PROVIDE_AGENT + ".");
+ continue;
+ }
+
ComponentName name = getComponentName(resolveInfo);
if (!enabledAgents.contains(name)) continue;
diff --git a/services/core/java/com/android/server/tv/TvInputHal.java b/services/core/java/com/android/server/tv/TvInputHal.java
index 4bdd2be..34168a8 100644
--- a/services/core/java/com/android/server/tv/TvInputHal.java
+++ b/services/core/java/com/android/server/tv/TvInputHal.java
@@ -16,10 +16,10 @@
package com.android.server.tv;
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvStreamConfig;
import android.os.Handler;
import android.os.HandlerThread;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvStreamConfig;
import android.view.Surface;
/**
diff --git a/services/core/java/com/android/server/tv/TvInputHardwareManager.java b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
index b95b0f0..e34f42b 100644
--- a/services/core/java/com/android/server/tv/TvInputHardwareManager.java
+++ b/services/core/java/com/android/server/tv/TvInputHardwareManager.java
@@ -17,12 +17,12 @@
package com.android.server.tv;
import android.content.Context;
+import android.media.tv.ITvInputHardware;
+import android.media.tv.ITvInputHardwareCallback;
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvStreamConfig;
import android.os.IBinder;
import android.os.RemoteException;
-import android.tv.ITvInputHardware;
-import android.tv.ITvInputHardwareCallback;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvStreamConfig;
import android.util.Slog;
import android.util.SparseArray;
import android.view.KeyEvent;
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index e52f218..1c277a8 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -31,6 +31,18 @@ import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.database.Cursor;
import android.graphics.Rect;
+import android.media.tv.ITvInputClient;
+import android.media.tv.ITvInputHardware;
+import android.media.tv.ITvInputHardwareCallback;
+import android.media.tv.ITvInputManager;
+import android.media.tv.ITvInputService;
+import android.media.tv.ITvInputServiceCallback;
+import android.media.tv.ITvInputSession;
+import android.media.tv.ITvInputSessionCallback;
+import android.media.tv.TvContract;
+import android.media.tv.TvInputHardwareInfo;
+import android.media.tv.TvInputInfo;
+import android.media.tv.TvInputService;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
@@ -41,18 +53,6 @@ import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
-import android.provider.TvContract;
-import android.tv.ITvInputClient;
-import android.tv.ITvInputHardware;
-import android.tv.ITvInputHardwareCallback;
-import android.tv.ITvInputManager;
-import android.tv.ITvInputService;
-import android.tv.ITvInputServiceCallback;
-import android.tv.ITvInputSession;
-import android.tv.ITvInputSessionCallback;
-import android.tv.TvInputHardwareInfo;
-import android.tv.TvInputInfo;
-import android.tv.TvInputService;
import android.util.Slog;
import android.util.SparseArray;
import android.view.InputChannel;
@@ -63,6 +63,10 @@ import com.android.internal.os.SomeArgs;
import com.android.server.IoThread;
import com.android.server.SystemService;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -145,7 +149,8 @@ public final class TvInputManagerService extends SystemService {
if (DEBUG) Slog.d(TAG, "buildTvInputList");
PackageManager pm = mContext.getPackageManager();
List<ResolveInfo> services = pm.queryIntentServices(
- new Intent(TvInputService.SERVICE_INTERFACE), PackageManager.GET_SERVICES);
+ new Intent(TvInputService.SERVICE_INTERFACE),
+ PackageManager.GET_SERVICES | PackageManager.GET_META_DATA);
for (ResolveInfo ri : services) {
ServiceInfo si = ri.serviceInfo;
if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) {
@@ -153,9 +158,13 @@ public final class TvInputManagerService extends SystemService {
+ android.Manifest.permission.BIND_TV_INPUT);
continue;
}
- TvInputInfo info = new TvInputInfo(ri);
- if (DEBUG) Slog.d(TAG, "add " + info.getId());
- userState.inputMap.put(info.getId(), info);
+ try {
+ TvInputInfo info = TvInputInfo.createTvInputInfo(mContext, ri);
+ if (DEBUG) Slog.d(TAG, "add " + info.getId());
+ userState.inputMap.put(info.getId(), info);
+ } catch (IOException | XmlPullParserException e) {
+ Slog.e(TAG, "Can't load TV input " + si.name, e);
+ }
}
}
@@ -204,11 +213,13 @@ public final class TvInputManagerService extends SystemService {
Slog.e(TAG, "error in unregisterCallback", e);
}
}
- serviceState.mClients.clear();
+ serviceState.mClientTokens.clear();
mContext.unbindService(serviceState.mConnection);
}
userState.serviceStateMap.clear();
+ userState.clientStateMap.clear();
+
mUserStates.remove(userId);
}
}
@@ -273,7 +284,7 @@ public final class TvInputManagerService extends SystemService {
}
serviceState.mReconnecting = false;
}
- boolean isStateEmpty = serviceState.mClients.isEmpty()
+ boolean isStateEmpty = serviceState.mClientTokens.isEmpty()
&& serviceState.mSessionTokens.isEmpty();
if (serviceState.mService == null && !isStateEmpty && userId == mCurrentUserId) {
// This means that the service is not yet connected but its state indicates that we
@@ -304,10 +315,22 @@ public final class TvInputManagerService extends SystemService {
}
}
+ private ClientState createClientStateLocked(IBinder clientToken, int userId) {
+ UserState userState = getUserStateLocked(userId);
+ ClientState clientState = new ClientState(clientToken, userId);
+ try {
+ clientToken.linkToDeath(clientState, 0);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Client is already died.");
+ }
+ userState.clientStateMap.put(clientToken, clientState);
+ return clientState;
+ }
+
private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken,
final int userId) {
- final SessionState sessionState =
- getUserStateLocked(userId).sessionStateMap.get(sessionToken);
+ final UserState userState = getUserStateLocked(userId);
+ final SessionState sessionState = userState.sessionStateMap.get(sessionToken);
if (DEBUG) {
Slog.d(TAG, "createSessionInternalLocked(inputId=" + sessionState.mInputId + ")");
}
@@ -333,6 +356,14 @@ public final class TvInputManagerService extends SystemService {
} catch (RemoteException e) {
Slog.e(TAG, "Session is already died.");
}
+
+ IBinder clientToken = sessionState.mClient.asBinder();
+ ClientState clientState = userState.clientStateMap.get(clientToken);
+ if (clientState == null) {
+ clientState = createClientStateLocked(clientToken, userId);
+ }
+ clientState.mSessionTokens.add(sessionState.mSessionToken);
+
sendSessionTokenToClientLocked(sessionState.mClient, sessionState.mInputId,
sessionToken, channels[0], sessionState.mSeq, userId);
}
@@ -341,18 +372,54 @@ public final class TvInputManagerService extends SystemService {
}
@Override
- public void onVideoSizeChanged(int width, int height) throws RemoteException {
+ public void onVideoStreamChanged(int width, int height, boolean interlaced) {
synchronized (mLock) {
if (DEBUG) {
- Slog.d(TAG, "onVideoSizeChanged(" + width + ", " + height + ")");
+ Slog.d(TAG, "onVideoStreamChanged(" + width + ", " + height + ")");
}
if (sessionState.mSession == null || sessionState.mClient == null) {
return;
}
try {
- sessionState.mClient.onVideoSizeChanged(width, height, sessionState.mSeq);
+ sessionState.mClient.onVideoStreamChanged(width, height, interlaced,
+ sessionState.mSeq);
} catch (RemoteException e) {
- Slog.e(TAG, "error in onSessionEvent");
+ Slog.e(TAG, "error in onVideoStreamChanged");
+ }
+ }
+ }
+
+ @Override
+ public void onAudioStreamChanged(int channelCount) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "onAudioStreamChanged(" + channelCount + ")");
+ }
+ if (sessionState.mSession == null || sessionState.mClient == null) {
+ return;
+ }
+ try {
+ sessionState.mClient.onAudioStreamChanged(channelCount, sessionState.mSeq);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in onAudioStreamChanged");
+ }
+ }
+ }
+
+ @Override
+ public void onClosedCaptionStreamChanged(boolean hasClosedCaption) {
+ synchronized (mLock) {
+ if (DEBUG) {
+ Slog.d(TAG, "onClosedCaptionStreamChanged(" + hasClosedCaption + ")");
+ }
+ if (sessionState.mSession == null || sessionState.mClient == null) {
+ return;
+ }
+ try {
+ sessionState.mClient.onClosedCaptionStreamChanged(hasClosedCaption,
+ sessionState.mSeq);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in onClosedCaptionStreamChanged");
}
}
}
@@ -423,7 +490,16 @@ public final class TvInputManagerService extends SystemService {
mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget();
}
- // Also remove the session token from the session token list of the current service.
+ // Also remove the session token from the session token list of the current client and
+ // service.
+ ClientState clientState = userState.clientStateMap.get(sessionState.mClient.asBinder());
+ if (clientState != null) {
+ clientState.mSessionTokens.remove(sessionToken);
+ if (clientState.isEmpty()) {
+ userState.clientStateMap.remove(sessionState.mClient.asBinder());
+ }
+ }
+
ServiceState serviceState = userState.serviceStateMap.get(sessionState.mInputId);
if (serviceState != null) {
serviceState.mSessionTokens.remove(sessionToken);
@@ -431,11 +507,45 @@ public final class TvInputManagerService extends SystemService {
updateServiceConnectionLocked(sessionState.mInputId, userId);
}
+ private void unregisterCallbackInternalLocked(IBinder clientToken, String inputId,
+ int userId) {
+ UserState userState = getUserStateLocked(userId);
+ ClientState clientState = userState.clientStateMap.get(clientToken);
+ if (clientState != null) {
+ clientState.mInputIds.remove(inputId);
+ if (clientState.isEmpty()) {
+ userState.clientStateMap.remove(clientToken);
+ }
+ }
+
+ ServiceState serviceState = userState.serviceStateMap.get(inputId);
+ if (serviceState == null) {
+ return;
+ }
+
+ // Remove this client from the client list and unregister the callback.
+ serviceState.mClientTokens.remove(clientToken);
+ if (!serviceState.mClientTokens.isEmpty()) {
+ // We have other clients who want to keep the callback. Do this later.
+ return;
+ }
+ if (serviceState.mService == null || serviceState.mCallback == null) {
+ return;
+ }
+ try {
+ serviceState.mService.unregisterCallback(serviceState.mCallback);
+ } catch (RemoteException e) {
+ Slog.e(TAG, "error in unregisterCallback", e);
+ } finally {
+ serviceState.mCallback = null;
+ updateServiceConnectionLocked(inputId, userId);
+ }
+ }
+
private void broadcastServiceAvailabilityChangedLocked(ServiceState serviceState) {
- for (IBinder iBinder : serviceState.mClients) {
- ITvInputClient client = ITvInputClient.Stub.asInterface(iBinder);
+ for (IBinder clientToken : serviceState.mClientTokens) {
try {
- client.onAvailabilityChanged(
+ ITvInputClient.Stub.asInterface(clientToken).onAvailabilityChanged(
serviceState.mTvInputInfo.getId(), serviceState.mAvailable);
} catch (RemoteException e) {
Slog.e(TAG, "error in onAvailabilityChanged", e);
@@ -498,10 +608,19 @@ public final class TvInputManagerService extends SystemService {
userState.inputMap.get(inputId), resolvedUserId);
userState.serviceStateMap.put(inputId, serviceState);
}
- IBinder iBinder = client.asBinder();
- if (!serviceState.mClients.contains(iBinder)) {
- serviceState.mClients.add(iBinder);
+ IBinder clientToken = client.asBinder();
+ if (!serviceState.mClientTokens.contains(clientToken)) {
+ serviceState.mClientTokens.add(clientToken);
+ }
+
+ ClientState clientState = userState.clientStateMap.get(clientToken);
+ if (clientState == null) {
+ clientState = createClientStateLocked(clientToken, resolvedUserId);
+ }
+ if (!clientState.mInputIds.contains(inputId)) {
+ clientState.mInputIds.add(inputId);
}
+
if (serviceState.mService != null) {
if (serviceState.mCallback != null) {
// We already handled.
@@ -529,29 +648,7 @@ public final class TvInputManagerService extends SystemService {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mLock) {
- UserState userState = getUserStateLocked(resolvedUserId);
- ServiceState serviceState = userState.serviceStateMap.get(inputId);
- if (serviceState == null) {
- return;
- }
-
- // Remove this client from the client list and unregister the callback.
- serviceState.mClients.remove(client.asBinder());
- if (!serviceState.mClients.isEmpty()) {
- // We have other clients who want to keep the callback. Do this later.
- return;
- }
- if (serviceState.mService == null || serviceState.mCallback == null) {
- return;
- }
- try {
- serviceState.mService.unregisterCallback(serviceState.mCallback);
- } catch (RemoteException e) {
- Slog.e(TAG, "error in unregisterCallback", e);
- } finally {
- serviceState.mCallback = null;
- updateServiceConnectionLocked(inputId, resolvedUserId);
- }
+ unregisterCallbackInternalLocked(client.asBinder(), inputId, resolvedUserId);
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -582,8 +679,8 @@ public final class TvInputManagerService extends SystemService {
// Create a new session token and a session state.
IBinder sessionToken = new Binder();
- SessionState sessionState = new SessionState(
- sessionToken, inputId, client, seq, callingUid, resolvedUserId);
+ SessionState sessionState = new SessionState(sessionToken, inputId, client,
+ seq, callingUid, resolvedUserId);
// Add them to the global session state map of the current user.
userState.sessionStateMap.put(sessionToken, sessionState);
@@ -835,6 +932,10 @@ public final class TvInputManagerService extends SystemService {
// A mapping from the TV input id to its TvInputInfo.
private final Map<String, TvInputInfo> inputMap = new HashMap<String,TvInputInfo>();
+ // A mapping from the token of a client to its state.
+ private final Map<IBinder, ClientState> clientStateMap =
+ new HashMap<IBinder, ClientState>();
+
// A mapping from the name of a TV input service to its state.
private final Map<String, ServiceState> serviceStateMap =
new HashMap<String, ServiceState>();
@@ -844,9 +945,46 @@ public final class TvInputManagerService extends SystemService {
new HashMap<IBinder, SessionState>();
}
+ private final class ClientState implements IBinder.DeathRecipient {
+ private final List<String> mInputIds = new ArrayList<String>();
+ private final List<IBinder> mSessionTokens = new ArrayList<IBinder>();
+
+ private IBinder mClientToken;
+ private final int mUserId;
+
+ ClientState(IBinder clientToken, int userId) {
+ mClientToken = clientToken;
+ mUserId = userId;
+ }
+
+ public boolean isEmpty() {
+ return mInputIds.isEmpty() && mSessionTokens.isEmpty();
+ }
+
+ @Override
+ public void binderDied() {
+ synchronized (mLock) {
+ UserState userState = getUserStateLocked(mUserId);
+ // DO NOT remove the client state of clientStateMap in this method. It will be
+ // removed in releaseSessionLocked() or unregisterCallbackInternalLocked().
+ ClientState clientState = userState.clientStateMap.get(mClientToken);
+ if (clientState != null) {
+ while (clientState.mSessionTokens.size() > 0) {
+ releaseSessionLocked(
+ clientState.mSessionTokens.get(0), Process.SYSTEM_UID, mUserId);
+ }
+ while (clientState.mInputIds.size() > 0) {
+ unregisterCallbackInternalLocked(
+ mClientToken, clientState.mInputIds.get(0), mUserId);
+ }
+ }
+ mClientToken = null;
+ }
+ }
+ }
+
private final class ServiceState {
- // TODO: need to implement DeathRecipient for clients.
- private final List<IBinder> mClients = new ArrayList<IBinder>();
+ private final List<IBinder> mClientTokens = new ArrayList<IBinder>();
private final List<IBinder> mSessionTokens = new ArrayList<IBinder>();
private final ServiceConnection mConnection;
private final TvInputInfo mTvInputInfo;
@@ -869,13 +1007,13 @@ public final class TvInputManagerService extends SystemService {
private final int mSeq;
private final int mCallingUid;
private final int mUserId;
- private final IBinder mToken;
+ private final IBinder mSessionToken;
private ITvInputSession mSession;
private Uri mLogUri;
- private SessionState(IBinder token, String inputId, ITvInputClient client, int seq,
+ private SessionState(IBinder sessionToken, String inputId, ITvInputClient client, int seq,
int callingUid, int userId) {
- mToken = token;
+ mSessionToken = sessionToken;
mInputId = inputId;
mClient = client;
mSeq = seq;
@@ -894,7 +1032,7 @@ public final class TvInputManagerService extends SystemService {
Slog.e(TAG, "error in onSessionReleased", e);
}
}
- removeSessionStateLocked(mToken, mUserId);
+ removeSessionStateLocked(mSessionToken, mUserId);
}
}
}
@@ -918,7 +1056,7 @@ public final class TvInputManagerService extends SystemService {
serviceState.mService = ITvInputService.Stub.asInterface(service);
// Register a callback, if we need to.
- if (!serviceState.mClients.isEmpty() && serviceState.mCallback == null) {
+ if (!serviceState.mClientTokens.isEmpty() && serviceState.mCallback == null) {
serviceState.mCallback = new ServiceCallback(mUserId);
try {
serviceState.mService.registerCallback(serviceState.mCallback);
@@ -1046,7 +1184,7 @@ public final class TvInputManagerService extends SystemService {
TvContract.Programs.COLUMN_TITLE,
TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS,
TvContract.Programs.COLUMN_END_TIME_UTC_MILLIS,
- TvContract.Programs.COLUMN_DESCRIPTION
+ TvContract.Programs.COLUMN_SHORT_DESCRIPTION
};
String selection = TvContract.Programs.COLUMN_CHANNEL_ID + "=? AND "
+ TvContract.Programs.COLUMN_START_TIME_UTC_MILLIS + "<=? AND "
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index 35d19c1..29bab22 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -21,6 +21,7 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.view.Display;
import android.view.Surface;
@@ -32,6 +33,10 @@ class CircularDisplayMask {
private static final String TAG = "CircularDisplayMask";
private static final int STROKE_WIDTH = 2;
+ // half the screen size
+ private static final int CIRCLE_RADIUS = 160;
+ // size of the chin
+ private static final int SCREEN_OFFSET = 30;
private final SurfaceControl mSurfaceControl;
private final Surface mSurface = new Surface();
@@ -40,12 +45,13 @@ class CircularDisplayMask {
private boolean mDrawNeeded;
private Paint mPaint;
private int mRotation;
+ private boolean mVisible;
public CircularDisplayMask(Display display, SurfaceSession session, int zOrder) {
SurfaceControl ctrl = null;
try {
ctrl = new SurfaceControl(session, "CircularDisplayMask",
- 320, 290, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+ 320, 320, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
ctrl.setLayerStack(display.getLayerStack());
ctrl.setLayer(zOrder);
ctrl.setPosition(0, 0);
@@ -63,12 +69,12 @@ class CircularDisplayMask {
}
private void drawIfNeeded() {
- if (!mDrawNeeded) {
+ if (!mDrawNeeded || !mVisible) {
return;
}
mDrawNeeded = false;
- Rect dirty = new Rect(0, 0, mLastDW, mLastDH);
+ Rect dirty = new Rect(0, 0, 320, 320);
Canvas c = null;
try {
c = mSurface.lockCanvas(dirty);
@@ -78,27 +84,23 @@ class CircularDisplayMask {
if (c == null) {
return;
}
- int cx = 160;
- int cy = 160;
+ c.drawColor(Color.TRANSPARENT, PorterDuff.Mode.SRC);
switch (mRotation) {
- case Surface.ROTATION_0:
- case Surface.ROTATION_90:
- // chin bottom or right
- cx = 160;
- cy = 160;
- break;
- case Surface.ROTATION_180:
- // chin top
- cx = 160;
- cy = 145;
- break;
- case Surface.ROTATION_270:
- cx = 145;
- cy = 160;
- break;
+ case Surface.ROTATION_0:
+ case Surface.ROTATION_90:
+ // chin bottom or right
+ mSurfaceControl.setPosition(0, 0);
+ break;
+ case Surface.ROTATION_180:
+ // chin top
+ mSurfaceControl.setPosition(0, -SCREEN_OFFSET);
+ break;
+ case Surface.ROTATION_270:
+ // chin left
+ mSurfaceControl.setPosition(-SCREEN_OFFSET, 0);
+ break;
}
- c.drawCircle(cx, cy, 160, mPaint);
-
+ c.drawCircle(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS, mPaint);
mSurface.unlockCanvasAndPost(c);
}
@@ -108,6 +110,7 @@ class CircularDisplayMask {
if (mSurfaceControl == null) {
return;
}
+ mVisible = on;
drawIfNeeded();
if (on) {
mSurfaceControl.show();
@@ -117,14 +120,14 @@ class CircularDisplayMask {
}
void positionSurface(int dw, int dh, int rotation) {
- if (mLastDW == dw && mLastDH == dh) {
+ if (mLastDW == dw && mLastDH == dh && mRotation == rotation) {
return;
}
mLastDW = dw;
mLastDH = dh;
- mSurfaceControl.setSize(dw, dh);
mDrawNeeded = true;
mRotation = rotation;
+ drawIfNeeded();
}
}
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index 81db8b3..a354c45 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -174,14 +174,14 @@ public class TaskStack {
stackNdx = 0;
} else {
stackNdx = mTasks.size();
- final int currentUserId = mService.mCurrentUserId;
- if (task.mUserId != currentUserId) {
+ if (!mService.isCurrentProfileLocked(task.mUserId)) {
// Place the task below all current user tasks.
while (--stackNdx >= 0) {
- if (currentUserId != mTasks.get(stackNdx).mUserId) {
+ if (!mService.isCurrentProfileLocked(mTasks.get(stackNdx).mUserId)) {
break;
}
}
+ // Put it above first non-current user task.
++stackNdx;
}
}
@@ -352,7 +352,7 @@ public class TaskStack {
int top = mTasks.size();
for (int taskNdx = 0; taskNdx < top; ++taskNdx) {
Task task = mTasks.get(taskNdx);
- if (task.mUserId == userId) {
+ if (mService.isCurrentProfileLocked(task.mUserId)) {
mTasks.remove(taskNdx);
mTasks.add(task);
--top;
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 05502cf..616db42 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -407,8 +407,11 @@ public class WindowManagerService extends IWindowManager.Stub
/**
* Windows that clients are waiting to have drawn.
*/
- ArrayList<Pair<WindowState, IRemoteCallback>> mWaitingForDrawn
- = new ArrayList<Pair<WindowState, IRemoteCallback>>();
+ ArrayList<WindowState> mWaitingForDrawn = new ArrayList<WindowState>();
+ /**
+ * And the callback to make when they've all been drawn.
+ */
+ IRemoteCallback mWaitingForDrawnCallback;
/**
* Windows that have called relayout() while we were running animations,
@@ -814,6 +817,7 @@ public class WindowManagerService extends IWindowManager.Stub
mAnimator = new WindowAnimator(this);
+ LocalServices.addService(WindowManagerInternal.class, new LocalService());
initPolicy();
// Add ourself to the Watchdog monitors.
@@ -828,7 +832,6 @@ public class WindowManagerService extends IWindowManager.Stub
SurfaceControl.closeTransaction();
}
- LocalServices.addService(WindowManagerInternal.class, new LocalService());
showCircularDisplayMaskIfNeeded();
}
@@ -7176,6 +7179,7 @@ public class WindowManagerService extends IWindowManager.Stub
public static final int NOTIFY_ACTIVITY_DRAWN = 32;
public static final int SHOW_DISPLAY_MASK = 33;
+ public static final int ALL_WINDOWS_DRAWN = 34;
@Override
public void handleMessage(Message msg) {
@@ -7552,17 +7556,18 @@ public class WindowManagerService extends IWindowManager.Stub
}
case WAITING_FOR_DRAWN_TIMEOUT: {
- Pair<WindowState, IRemoteCallback> pair;
+ IRemoteCallback callback = null;
synchronized (mWindowMap) {
- pair = (Pair<WindowState, IRemoteCallback>)msg.obj;
- Slog.w(TAG, "Timeout waiting for drawn: " + pair.first);
- if (!mWaitingForDrawn.remove(pair)) {
- return;
- }
+ Slog.w(TAG, "Timeout waiting for drawn: undrawn=" + mWaitingForDrawn);
+ mWaitingForDrawn.clear();
+ callback = mWaitingForDrawnCallback;
+ mWaitingForDrawnCallback = null;
}
- try {
- pair.second.sendResult(null);
- } catch (RemoteException e) {
+ if (callback != null) {
+ try {
+ callback.sendResult(null);
+ } catch (RemoteException e) {
+ }
}
break;
}
@@ -7620,6 +7625,19 @@ public class WindowManagerService extends IWindowManager.Stub
} catch (RemoteException e) {
}
break;
+ case ALL_WINDOWS_DRAWN: {
+ IRemoteCallback callback;
+ synchronized (mWindowMap) {
+ callback = mWaitingForDrawnCallback;
+ mWaitingForDrawnCallback = null;
+ }
+ if (callback != null) {
+ try {
+ callback.sendResult(null);
+ } catch (RemoteException e) {
+ }
+ }
+ }
}
if (DEBUG_WINDOW_TRACE) {
Slog.v(TAG, "handleMessage: exit");
@@ -9558,53 +9576,30 @@ public class WindowManagerService extends IWindowManager.Stub
}
void checkDrawnWindowsLocked() {
- if (mWaitingForDrawn.size() > 0) {
- for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
- Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(j);
- WindowState win = pair.first;
- //Slog.i(TAG, "Waiting for drawn " + win + ": removed="
- // + win.mRemoved + " visible=" + win.isVisibleLw()
- // + " shown=" + win.mSurfaceShown);
- if (win.mRemoved) {
- // Window has been removed; no draw will now happen, so stop waiting.
- Slog.w(TAG, "Aborted waiting for drawn: " + pair.first);
- try {
- pair.second.sendResult(null);
- } catch (RemoteException e) {
- }
- mWaitingForDrawn.remove(pair);
- mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
- } else if (win.mWinAnimator.mSurfaceShown) {
- // Window is now drawn (and shown).
- try {
- pair.second.sendResult(null);
- } catch (RemoteException e) {
- }
- mWaitingForDrawn.remove(pair);
- mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
- }
- }
+ if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) {
+ return;
}
- }
-
- @Override
- public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
- if (token != null && callback != null) {
- synchronized (mWindowMap) {
- WindowState win = windowForClientLocked(null, token, true);
- if (win != null) {
- Pair<WindowState, IRemoteCallback> pair =
- new Pair<WindowState, IRemoteCallback>(win, callback);
- Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
- mH.sendMessageDelayed(m, 2000);
- mWaitingForDrawn.add(pair);
- checkDrawnWindowsLocked();
- return true;
- }
- Slog.i(TAG, "waitForWindowDrawn: win null");
+ for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) {
+ WindowState win = mWaitingForDrawn.get(j);
+ if (DEBUG_SCREEN_ON) Slog.i(TAG, "Waiting for drawn " + win +
+ ": removed=" + win.mRemoved + " visible=" + win.isVisibleLw() +
+ " mHasSurface=" + win.mHasSurface +
+ " drawState=" + win.mWinAnimator.mDrawState);
+ if (win.mRemoved || !win.mHasSurface) {
+ // Window has been removed; no draw will now happen, so stop waiting.
+ if (DEBUG_SCREEN_ON) Slog.w(TAG, "Aborted waiting for drawn: " + win);
+ mWaitingForDrawn.remove(win);
+ } else if (win.hasDrawnLw()) {
+ // Window is now drawn (and shown).
+ if (DEBUG_SCREEN_ON) Slog.d(TAG, "Window drawn win=" + win);
+ mWaitingForDrawn.remove(win);
}
}
- return false;
+ if (mWaitingForDrawn.isEmpty()) {
+ if (DEBUG_SCREEN_ON) Slog.d(TAG, "All windows drawn!");
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
+ mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN);
+ }
}
void setHoldScreenLocked(final Session newHoldScreen) {
@@ -10552,9 +10547,8 @@ public class WindowManagerService extends IWindowManager.Stub
pw.println();
pw.println(" Clients waiting for these windows to be drawn:");
for (int i=mWaitingForDrawn.size()-1; i>=0; i--) {
- Pair<WindowState, IRemoteCallback> pair = mWaitingForDrawn.get(i);
- pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(pair.first);
- pw.print(": "); pw.println(pair.second);
+ WindowState win = mWaitingForDrawn.get(i);
+ pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win);
}
}
pw.println();
@@ -11064,7 +11058,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
mAccessibilityController.setMagnificationCallbacksLocked(callbacks);
if (!mAccessibilityController.hasCallbacksLocked()) {
- mAccessibilityController = null;
+ mAccessibilityController = null;
}
}
}
@@ -11078,7 +11072,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
mAccessibilityController.setWindowsForAccessibilityCallback(callback);
if (!mAccessibilityController.hasCallbacksLocked()) {
- mAccessibilityController = null;
+ mAccessibilityController = null;
}
}
}
@@ -11115,5 +11109,25 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
}
+
+ public void waitForAllWindowsDrawn(IRemoteCallback callback, long timeout) {
+ synchronized (mWindowMap) {
+ mWaitingForDrawnCallback = callback;
+ final WindowList windows = getDefaultWindowListLocked();
+ for (int winNdx = windows.size() - 1; winNdx >= 0; --winNdx) {
+ final WindowState win = windows.get(winNdx);
+ if (win.mHasSurface) {
+ win.mWinAnimator.mDrawState = WindowStateAnimator.DRAW_PENDING;
+ // Force add to mResizingWindows.
+ win.mLastContentInsets.set(-1, -1, -1, -1);
+ mWaitingForDrawn.add(win);
+ }
+ }
+ requestTraversalLocked();
+ mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT);
+ mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout);
+ }
+ checkDrawnWindowsLocked();
+ }
}
}
diff --git a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
index 6c14887..c2fccc1 100644
--- a/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
+++ b/services/core/jni/com_android_server_location_FlpHardwareProvider.cpp
@@ -139,6 +139,8 @@ static int SetThreadEvent(ThreadEvent event) {
* the HW module and obtaining the proper interfaces.
*/
static void ClassInit(JNIEnv* env, jclass clazz) {
+ sFlpInterface = NULL;
+
// get references to the Java provider methods
sOnLocationReport = env->GetMethodID(
clazz,
@@ -163,6 +165,38 @@ static void ClassInit(JNIEnv* env, jclass clazz) {
sOnGeofenceRemove = env->GetMethodID(clazz, "onGeofenceRemove", "(II)V");
sOnGeofencePause = env->GetMethodID(clazz, "onGeofencePause", "(II)V");
sOnGeofenceResume = env->GetMethodID(clazz, "onGeofenceResume", "(II)V");
+
+ // open the hardware module
+ const hw_module_t* module = NULL;
+ int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, &module);
+ if (err != 0) {
+ ALOGE("Error hw_get_module '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
+ return;
+ }
+
+ err = module->methods->open(
+ module,
+ FUSED_LOCATION_HARDWARE_MODULE_ID,
+ &sHardwareDevice);
+ if (err != 0) {
+ ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
+ return;
+ }
+
+ // acquire the interfaces pointers
+ flp_device_t* flp_device = reinterpret_cast<flp_device_t*>(sHardwareDevice);
+ sFlpInterface = flp_device->get_flp_interface(flp_device);
+
+ if (sFlpInterface != NULL) {
+ sFlpDiagnosticInterface = reinterpret_cast<const FlpDiagnosticInterface*>(
+ sFlpInterface->get_extension(FLP_DIAGNOSTIC_INTERFACE));
+
+ sFlpGeofencingInterface = reinterpret_cast<const FlpGeofencingInterface*>(
+ sFlpInterface->get_extension(FLP_GEOFENCING_INTERFACE));
+
+ sFlpDeviceContextInterface = reinterpret_cast<const FlpDeviceContextInterface*>(
+ sFlpInterface->get_extension(FLP_DEVICE_CONTEXT_INTERFACE));
+ }
}
/*
@@ -637,44 +671,6 @@ FlpGeofenceCallbacks sFlpGeofenceCallbacks = {
* the Flp interfaces are initialized properly.
*/
static void Init(JNIEnv* env, jobject obj) {
- if(sHardwareDevice != NULL) {
- ALOGD("Hardware Device already opened.");
- return;
- }
-
- const hw_module_t* module = NULL;
- int err = hw_get_module(FUSED_LOCATION_HARDWARE_MODULE_ID, &module);
- if(err != 0) {
- ALOGE("Error hw_get_module '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
- return;
- }
-
- err = module->methods->open(
- module,
- FUSED_LOCATION_HARDWARE_MODULE_ID, &sHardwareDevice);
- if(err != 0) {
- ALOGE("Error opening device '%s': %d", FUSED_LOCATION_HARDWARE_MODULE_ID, err);
- return;
- }
-
- sFlpInterface = NULL;
- flp_device_t* flp_device = reinterpret_cast<flp_device_t*>(sHardwareDevice);
- sFlpInterface = flp_device->get_flp_interface(flp_device);
-
- if(sFlpInterface != NULL) {
- sFlpDiagnosticInterface = reinterpret_cast<const FlpDiagnosticInterface*>(
- sFlpInterface->get_extension(FLP_DIAGNOSTIC_INTERFACE)
- );
-
- sFlpGeofencingInterface = reinterpret_cast<const FlpGeofencingInterface*>(
- sFlpInterface->get_extension(FLP_GEOFENCING_INTERFACE)
- );
-
- sFlpDeviceContextInterface = reinterpret_cast<const FlpDeviceContextInterface*>(
- sFlpInterface->get_extension(FLP_DEVICE_CONTEXT_INTERFACE)
- );
- }
-
if(sCallbacksObj == NULL) {
sCallbacksObj = env->NewGlobalRef(obj);
}
@@ -696,7 +692,10 @@ static void Init(JNIEnv* env, jobject obj) {
}
static jboolean IsSupported(JNIEnv* env, jclass clazz) {
- return sFlpInterface != NULL;
+ if (sFlpInterface == NULL) {
+ return JNI_FALSE;
+ }
+ return JNI_TRUE;
}
static jint GetBatchSize(JNIEnv* env, jobject object) {
diff --git a/services/core/jni/com_android_server_tv_TvInputHal.cpp b/services/core/jni/com_android_server_tv_TvInputHal.cpp
index f0c4f3a..afe629d 100644
--- a/services/core/jni/com_android_server_tv_TvInputHal.cpp
+++ b/services/core/jni/com_android_server_tv_TvInputHal.cpp
@@ -316,7 +316,7 @@ static JNINativeMethod gTvInputHalMethods[] = {
(void*) nativeOpen },
{ "nativeSetSurface", "(JIILandroid/view/Surface;)I",
(void*) nativeSetSurface },
- { "nativeGetStreamConfigs", "(JII)[Landroid/tv/TvStreamConfig;",
+ { "nativeGetStreamConfigs", "(JII)[Landroid/media/tv/TvStreamConfig;",
(void*) nativeGetStreamConfigs },
{ "nativeClose", "(J)V",
(void*) nativeClose },
@@ -346,10 +346,10 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) {
gTvInputHalClassInfo.streamConfigsChanged, clazz,
"streamConfigsChangedFromNative", "(I)V");
- FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/tv/TvStreamConfig");
+ FIND_CLASS(gTvStreamConfigClassInfo.clazz, "android/media/tv/TvStreamConfig");
gTvStreamConfigClassInfo.clazz = jclass(env->NewGlobalRef(gTvStreamConfigClassInfo.clazz));
- FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/tv/TvStreamConfig$Builder");
+ FIND_CLASS(gTvStreamConfigBuilderClassInfo.clazz, "android/media/tv/TvStreamConfig$Builder");
gTvStreamConfigBuilderClassInfo.clazz =
jclass(env->NewGlobalRef(gTvStreamConfigBuilderClassInfo.clazz));
@@ -360,27 +360,27 @@ int register_android_server_tv_TvInputHal(JNIEnv* env) {
GET_METHOD_ID(
gTvStreamConfigBuilderClassInfo.streamId,
gTvStreamConfigBuilderClassInfo.clazz,
- "streamId", "(I)Landroid/tv/TvStreamConfig$Builder;");
+ "streamId", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
GET_METHOD_ID(
gTvStreamConfigBuilderClassInfo.type,
gTvStreamConfigBuilderClassInfo.clazz,
- "type", "(I)Landroid/tv/TvStreamConfig$Builder;");
+ "type", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
GET_METHOD_ID(
gTvStreamConfigBuilderClassInfo.maxWidth,
gTvStreamConfigBuilderClassInfo.clazz,
- "maxWidth", "(I)Landroid/tv/TvStreamConfig$Builder;");
+ "maxWidth", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
GET_METHOD_ID(
gTvStreamConfigBuilderClassInfo.maxHeight,
gTvStreamConfigBuilderClassInfo.clazz,
- "maxHeight", "(I)Landroid/tv/TvStreamConfig$Builder;");
+ "maxHeight", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
GET_METHOD_ID(
gTvStreamConfigBuilderClassInfo.generation,
gTvStreamConfigBuilderClassInfo.clazz,
- "generation", "(I)Landroid/tv/TvStreamConfig$Builder;");
+ "generation", "(I)Landroid/media/tv/TvStreamConfig$Builder;");
GET_METHOD_ID(
gTvStreamConfigBuilderClassInfo.build,
gTvStreamConfigBuilderClassInfo.clazz,
- "build", "()Landroid/tv/TvStreamConfig;");
+ "build", "()Landroid/media/tv/TvStreamConfig;");
return 0;
}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index a52396e..043fab4 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -3555,111 +3555,6 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
}
@Override
- public void enableSystemApp(ComponentName who, String packageName) {
- synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
- int userId = UserHandle.getCallingUserId();
- long id = Binder.clearCallingIdentity();
-
- try {
- UserManager um = UserManager.get(mContext);
- if (!um.getUserInfo(userId).isManagedProfile()) {
- throw new IllegalStateException(
- "Only call this method from a managed profile.");
- }
-
- // TODO: Use UserManager::getProfileParent when available.
- UserInfo primaryUser = um.getUserInfo(UserHandle.USER_OWNER);
-
- if (DBG) {
- Slog.v(LOG_TAG, "installing " + packageName + " for "
- + userId);
- }
-
- IPackageManager pm = AppGlobals.getPackageManager();
- if (!isSystemApp(pm, packageName, primaryUser.id)) {
- throw new IllegalArgumentException("Only system apps can be enabled this way.");
- }
-
- // Install the app.
- pm.installExistingPackageAsUser(packageName, userId);
-
- } catch (RemoteException re) {
- // shouldn't happen
- Slog.wtf(LOG_TAG, "Failed to install " + packageName, re);
- } finally {
- restoreCallingIdentity(id);
- }
- }
- }
-
- @Override
- public int enableSystemAppWithIntent(ComponentName who, Intent intent) {
- synchronized (this) {
- if (who == null) {
- throw new NullPointerException("ComponentName is null");
- }
-
- getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
-
- int userId = UserHandle.getCallingUserId();
- long id = Binder.clearCallingIdentity();
-
- try {
- UserManager um = UserManager.get(mContext);
- if (!um.getUserInfo(userId).isManagedProfile()) {
- throw new IllegalStateException(
- "Only call this method from a managed profile.");
- }
-
- // TODO: Use UserManager::getProfileParent when available.
- UserInfo primaryUser = um.getUserInfo(UserHandle.USER_OWNER);
-
- IPackageManager pm = AppGlobals.getPackageManager();
- List<ResolveInfo> activitiesToEnable = pm.queryIntentActivities(intent,
- intent.resolveTypeIfNeeded(mContext.getContentResolver()),
- 0, // no flags
- primaryUser.id);
-
- if (DBG) Slog.d(LOG_TAG, "Enabling system activities: " + activitiesToEnable);
- int numberOfAppsInstalled = 0;
- if (activitiesToEnable != null) {
- for (ResolveInfo info : activitiesToEnable) {
- if (info.activityInfo != null) {
-
- if (!isSystemApp(pm, info.activityInfo.packageName, primaryUser.id)) {
- throw new IllegalArgumentException(
- "Only system apps can be enabled this way.");
- }
-
-
- numberOfAppsInstalled++;
- pm.installExistingPackageAsUser(info.activityInfo.packageName, userId);
- }
- }
- }
- return numberOfAppsInstalled;
- } catch (RemoteException e) {
- // shouldn't happen
- Slog.wtf(LOG_TAG, "Failed to resolve intent for: " + intent);
- return 0;
- } finally {
- restoreCallingIdentity(id);
- }
- }
- }
-
- private boolean isSystemApp(IPackageManager pm, String packageName, int userId)
- throws RemoteException {
- ApplicationInfo appInfo = pm.getApplicationInfo(packageName, 0, userId);
- return (appInfo.flags & ApplicationInfo.FLAG_SYSTEM) > 0;
- }
-
- @Override
public void setAccountManagementDisabled(ComponentName who, String accountType,
boolean disabled) {
if (!mHasFeature) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 9174c0c..18ece5b 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -29,6 +29,7 @@ import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.media.AudioService;
+import android.media.tv.TvInputManager;
import android.os.Build;
import android.os.Environment;
import android.os.FactoryTest;
@@ -43,7 +44,6 @@ import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.UserHandle;
import android.service.dreams.DreamService;
-import android.tv.TvInputManager;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
@@ -127,7 +127,7 @@ public final class SystemServer {
private static final String WIFI_SERVICE_CLASS =
"com.android.server.wifi.WifiService";
private static final String WIFI_PASSPOINT_SERVICE_CLASS =
- "com.android.server.wifi.passpoint.PasspointService";
+ "com.android.server.wifi.passpoint.WifiPasspointService";
private static final String WIFI_P2P_SERVICE_CLASS =
"com.android.server.wifi.p2p.WifiP2pService";
private static final String HDMI_CEC_SERVICE_CLASS =
@@ -644,15 +644,15 @@ public final class SystemServer {
}
try {
- mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
+ mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
} catch (Throwable e) {
- reportWtf("starting Wi-Fi Service", e);
+ reportWtf("starting Wi-Fi PasspointService", e);
}
try {
- mSystemServiceManager.startService(WIFI_PASSPOINT_SERVICE_CLASS);
+ mSystemServiceManager.startService(WIFI_SERVICE_CLASS);
} catch (Throwable e) {
- reportWtf("starting Wi-Fi PasspointService", e);
+ reportWtf("starting Wi-Fi Service", e);
}
try {
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index c7715ad..fc5426c 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -43,7 +43,6 @@ public class MainActivity extends Activity implements OnItemClickListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- HardwareRenderer.sUseRenderThread = true;
setContentView(R.layout.activity_main);
ListView lv = (ListView) findViewById(android.R.id.list);
lv.setDrawSelectorOnTop(true);
diff --git a/tests/VectorDrawableTest/AndroidManifest.xml b/tests/VectorDrawableTest/AndroidManifest.xml
index 28c5f33..113dce3 100644
--- a/tests/VectorDrawableTest/AndroidManifest.xml
+++ b/tests/VectorDrawableTest/AndroidManifest.xml
@@ -22,6 +22,25 @@
<application
android:hardwareAccelerated="true"
android:label="vector" >
+
+ <activity
+ android:name="VectorDrawablePerformance"
+ android:label="Vector Performance" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+
+ </activity>
+ <activity
+ android:name="VectorDrawableAnimation"
+ android:label="VectorTestAnimation" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="com.android.test.dynamic.TEST" />
+ </intent-filter>
+ </activity>
<activity
android:name="VectorDrawableTest"
android:label="Vector Icon" >
@@ -41,19 +60,7 @@
<category android:name="com.android.test.dynamic.TEST" />
</intent-filter>
</activity>
-
- <activity
- android:name="VectorDrawablePerformance"
- android:label="Vector Performance" >
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
-
- <category android:name="com.android.test.dynamic.TEST" />
- </intent-filter>
-
- </activity>
-
- <activity
+ <activity
android:name="VectorDrawableDupPerf"
android:label="Vector Performance of clones" >
<intent-filter>
diff --git a/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml b/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml
new file mode 100644
index 0000000..a588960
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/animation_drawable_vector.xml
@@ -0,0 +1,36 @@
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/animation_drawable_vector" android:oneshot="false">
+ <item android:drawable="@drawable/vector_drawable01" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable02" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable03" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable04" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable05" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable06" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable07" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable08" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable09" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable10" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable11" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable12" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable13" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable14" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable15" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable16" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable17" android:duration="300" />
+ <item android:drawable="@drawable/vector_drawable18" android:duration="300" />
+ </animation-list>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
index 850de28..ab5f7f4 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable06.xml
@@ -25,10 +25,12 @@
<group>
<path android:pathData="M 569.374 461.472L 569.374 160.658L 160.658 160.658L 160.658 461.472L 569.374 461.472z"
android:name="path2451"
+ android:fill="#00000000"
android:stroke="#FF000000"
android:strokeWidth="30.65500000000000"/>
<path android:pathData="M 365.015 311.066"
android:name="path2453"
+ android:fill="#00000000"
android:stroke="#FF000000"
android:strokeWidth="30.655000000000001"/>
<path android:pathData="M 164.46 164.49L 340.78 343.158C 353.849 356.328 377.63 356.172 390.423 343.278L 566.622 165.928"
@@ -38,10 +40,12 @@
android:strokeWidth="30.655000000000001"/>
<path android:pathData="M 170.515 451.566L 305.61 313.46"
android:name="path2457"
+ android:fill="#00000000"
android:stroke="#000000"
android:strokeWidth="30.655000000000001"/>
<path android:pathData="M 557.968 449.974L 426.515 315.375"
android:name="path2459"
+ android:fill="#00000000"
android:stroke="#000000"
android:strokeWidth="30.655000000000001"/>
</group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
index d0edd8c..3042f6a 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
@@ -27,6 +27,7 @@
<path
android:name="pie1"
android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+ android:fill="#00000000"
android:stroke="#FF00FF00"
android:strokeWidth="70"
android:trimPathEnd=".75"
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
index 1abe1e1..8d4ca61 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
@@ -34,6 +34,7 @@
a25,25 -30 0,1 100,-50 l 50,-25
a25,37 -30 0,1 100,-50 l 50,-25
a25,50 -30 0,1 100,-50 l 50,-25"
+ android:fill="#00000000"
android:stroke="#FF00FF00"
android:strokeWidth="10" />
</group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
index 8e98d02..c28aff4 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable17.xml
@@ -25,6 +25,7 @@
<path
android:name="house"
android:pathData="M200,300 Q400,50 600,300 T1000,300"
+ android:fill="#00000000"
android:stroke="#FFFF0000"
android:strokeWidth="10"/>
</group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
index 6d74ebd..d7042fd 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
@@ -27,6 +27,7 @@
<path
android:name="house"
android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+ android:fill="#00000000"
android:stroke="#FFFFFF00"
android:strokeWidth="10" />
</group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
index a890fd6..47a9574 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
@@ -29,6 +29,7 @@
android:pathData="M10,300 Q400,550 600,300 T1000,300"
android:pivotX="90"
android:pivotY="100"
+ android:fill="#00000000"
android:stroke="#FFFF0000"
android:strokeWidth="60" />
</group>
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml
new file mode 100644
index 0000000..8d38cb5
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable22.xml
@@ -0,0 +1,72 @@
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="400"
+ android:viewportWidth="400" />
+
+ <group android:name="backgroundGroup" >
+ <path
+ android:name="background1"
+ android:fill="#80000000"
+ android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+ <path
+ android:name="background2"
+ android:fill="#80000000"
+ android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+ </group>
+ <group
+ android:name="translateToCenterGroup"
+ android:translateX="50.0"
+ android:translateY="90.0" >
+ <path
+ android:name="twoLines"
+ android:pathData="M 0,0 v 100 M 0,0 h 100"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="20" />
+
+ <group
+ android:name="rotationGroup"
+ android:pivotX="0.0"
+ android:pivotY="0.0"
+ android:rotation="-45.0" >
+ <path
+ android:name="twoLines1"
+ android:pathData="M 0,0 v 100 M 0,0 h 100"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="20" />
+
+ <group
+ android:name="translateGroup"
+ android:translateX="130.0"
+ android:translateY="160.0" >
+ <group android:name="scaleGroup" >
+ <path
+ android:name="twoLines2"
+ android:pathData="M 0,0 v 100 M 0,0 h 100"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="20" />
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml
new file mode 100644
index 0000000..52acd7a
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable23.xml
@@ -0,0 +1,86 @@
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="400"
+ android:viewportWidth="400" />
+
+ <group android:name="backgroundGroup" >
+ <path
+ android:name="background1"
+ android:fill="#80000000"
+ android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+ <path
+ android:name="background2"
+ android:fill="#80000000"
+ android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+ </group>
+ <group
+ android:name="translateToCenterGroup"
+ android:translateX="50.0"
+ android:translateY="90.0" >
+ <path
+ android:name="twoLines"
+ android:pathData="@string/twoLinePathData"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="20" />
+
+ <group
+ android:name="rotationGroup"
+ android:pivotX="0.0"
+ android:pivotY="0.0"
+ android:rotation="-45.0" >
+ <path
+ android:name="twoLines1"
+ android:pathData="@string/twoLinePathData"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="20" />
+
+ <group
+ android:name="translateGroup"
+ android:translateX="130.0"
+ android:translateY="160.0" >
+ <group android:name="scaleGroup" >
+ <path
+ android:name="twoLines3"
+ android:pathData="@string/twoLinePathData"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="20" />
+ </group>
+ </group>
+
+ <group
+ android:name="translateGroupHalf"
+ android:translateX="65.0"
+ android:translateY="80.0" >
+ <group android:name="scaleGroup" >
+ <path
+ android:name="twoLines2"
+ android:pathData="@string/twoLinePathData"
+ android:fill="?android:attr/colorForeground"
+ android:stroke="?android:attr/colorForeground"
+ android:strokeWidth="20" />
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml
new file mode 100644
index 0000000..c062d70
--- /dev/null
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable24.xml
@@ -0,0 +1,91 @@
+<!--
+ Copyright (C) 2014 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android" >
+
+ <size
+ android:height="64dp"
+ android:width="64dp" />
+
+ <viewport
+ android:viewportHeight="400"
+ android:viewportWidth="400" />
+
+ <group android:name="backgroundGroup"
+ android:alpha = "0.5" >
+ <path
+ android:name="background1"
+ android:fill="#FF000000"
+ android:pathData="M 0,0 l 200,0 l 0, 200 l -200, 0 z" />
+ <path
+ android:name="background2"
+ android:fill="#FF000000"
+ android:pathData="M 200,200 l 200,0 l 0, 200 l -200, 0 z" />
+ </group>
+ <group
+ android:name="translateToCenterGroup"
+ android:translateX="50.0"
+ android:translateY="90.0"
+ android:alpha = "0.5" >
+ <path
+ android:name="twoLines"
+ android:pathData="@string/twoLinePathData"
+ android:stroke="#FFFF0000"
+ android:strokeWidth="20" />
+
+ <group
+ android:name="rotationGroup"
+ android:pivotX="0.0"
+ android:pivotY="0.0"
+ android:rotation="-45.0"
+ android:alpha = "0.5" >
+ <path
+ android:name="twoLines1"
+ android:pathData="@string/twoLinePathData"
+ android:stroke="#FF00FF00"
+ android:strokeWidth="20" />
+
+ <group
+ android:name="translateGroup"
+ android:translateX="130.0"
+ android:translateY="160.0"
+ android:alpha = "0.5">
+ <group android:name="scaleGroup" >
+ <path
+ android:name="twoLines3"
+ android:pathData="@string/twoLinePathData"
+ android:stroke="#FF0000FF"
+ android:strokeWidth="20" />
+ </group>
+ </group>
+
+ <group
+ android:name="translateGroupHalf"
+ android:translateX="65.0"
+ android:translateY="80.0"
+ android:alpha = "0.5">
+ <group android:name="scaleGroup" >
+ <path
+ android:name="twoLines2"
+ android:pathData="@string/twoLinePathData"
+ android:fill="?android:attr/colorForeground"
+ android:stroke="?android:attr/colorForeground"
+ android:strokeWidth="20" />
+ </group>
+ </group>
+ </group>
+ </group>
+
+</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test01.xml b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
index a9091ab..fc2a15c 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_test01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
@@ -28,7 +28,8 @@ limitations under the License.
android:name="002b"
android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
android:stroke="#FF0000FF"
- android:strokeWidth="4" />
+ android:strokeWidth="4"
+ android:fill="#00000000" />
</group>
</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test02.xml b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
index ab58c06..9f4abbf 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_test02.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
@@ -28,7 +28,8 @@ limitations under the License.
android:name="002b"
android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
android:stroke="#FF0000FF"
- android:strokeWidth="4" />
+ android:strokeWidth="4"
+ android:fill="#00000000" />
</group>
</vector> \ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/values/strings.xml b/tests/VectorDrawableTest/res/values/strings.xml
index 64163c2..b49a1aa 100644
--- a/tests/VectorDrawableTest/res/values/strings.xml
+++ b/tests/VectorDrawableTest/res/values/strings.xml
@@ -15,4 +15,5 @@
-->
<resources>
+ <string name="twoLinePathData" >"M 0,0 v 100 M 0,0 h 100"</string>
</resources>
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
index 7ba01b1..a23d819 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawable01.java
@@ -61,6 +61,8 @@ public class VectorDrawable01 extends Activity {
button.setWidth(200);
button.setBackgroundResource(icon[i]);
container.addView(button);
+ VectorDrawable vd = (VectorDrawable) button.getBackground();
+ vd.setAlpha((i + 1) * (0xFF / (icon.length + 1)));
}
setContentView(container);
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java
new file mode 100644
index 0000000..99de037
--- /dev/null
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawableAnimation.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
+ * in compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+package com.android.test.dynamic;
+
+import android.app.Activity;
+import android.graphics.drawable.AnimationDrawable;
+import android.os.Bundle;
+import android.view.View;
+import android.widget.Button;
+
+public class VectorDrawableAnimation extends Activity {
+ private static final String LOGCAT = "VectorDrawableAnimation";
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Button button = new Button(this);
+ button.setBackgroundResource(R.drawable.animation_drawable_vector);
+
+ button.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ AnimationDrawable frameAnimation = (AnimationDrawable) v.getBackground();
+ // Start the animation (looped playback by default).
+ frameAnimation.start();
+ }
+ });
+
+ setContentView(button);
+ }
+
+}
diff --git a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
index e0624e5..814deb8 100644
--- a/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
+++ b/tests/VectorDrawableTest/src/com/android/test/dynamic/VectorDrawablePerformance.java
@@ -17,11 +17,11 @@ import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.VectorDrawable;
import android.os.Bundle;
-import android.view.View;
import android.widget.TextView;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.ScrollView;
+
import java.text.DecimalFormat;
@SuppressWarnings({"UnusedDeclaration"})
@@ -48,7 +48,10 @@ public class VectorDrawablePerformance extends Activity {
R.drawable.vector_drawable18,
R.drawable.vector_drawable19,
R.drawable.vector_drawable20,
- R.drawable.vector_drawable21
+ R.drawable.vector_drawable21,
+ R.drawable.vector_drawable22,
+ R.drawable.vector_drawable23,
+ R.drawable.vector_drawable24,
};
@Override
diff --git a/tools/aapt/Main.cpp b/tools/aapt/Main.cpp
index 5a60014..322d86c 100644
--- a/tools/aapt/Main.cpp
+++ b/tools/aapt/Main.cpp
@@ -105,20 +105,12 @@ void usage(void)
" en\n"
" port,en\n"
" port,land,en_US\n"
- " If you put the special locale, zz_ZZ on the list, it will perform\n"
- " pseudolocalization on the default locale, modifying all of the\n"
- " strings so you can look for strings that missed the\n"
- " internationalization process. For example:\n"
- " port,land,zz_ZZ\n"
" -d one or more device assets to include, separated by commas\n"
" -f force overwrite of existing files\n"
" -g specify a pixel tolerance to force images to grayscale, default 0\n"
" -j specify a jar or zip file containing classes to include\n"
" -k junk path of file(s) added\n"
" -m make package directories under location specified by -J\n"
-#if 0
- " -p pseudolocalize the default configuration\n"
-#endif
" -u update existing packages (add new, replace older, remove deleted files)\n"
" -v verbose output\n"
" -x create extending (non-application) resource IDs\n"
@@ -141,6 +133,8 @@ void usage(void)
" manifest, making the application debuggable even on production devices.\n"
" --include-meta-data\n"
" when used with \"dump badging\" also includes meta-data tags.\n"
+ " --pseudo-localize\n"
+ " generate resources for pseudo-locales (en-XA and ar-XB).\n"
" --min-sdk-version\n"
" inserts android:minSdkVersion in to manifest. If the version is 7 or\n"
" higher, the default encoding for resources will be in UTF-8.\n"
@@ -647,6 +641,8 @@ int main(int argc, char* const argv[])
goto bail;
}
gUserIgnoreAssets = argv[0];
+ } else if (strcmp(cp, "-pseudo-localize") == 0) {
+ bundle.setPseudolocalize(PSEUDO_ACCENTED | PSEUDO_BIDI);
} else {
fprintf(stderr, "ERROR: Unknown option '-%s'\n", cp);
wantUsage = true;
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 3bf2b20..cfe8e15 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -419,11 +419,6 @@ public class IWindowManagerImpl implements IWindowManager {
}
@Override
- public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
- return false;
- }
-
- @Override
public IBinder asBinder() {
// TODO Auto-generated method stub
return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
index e59ccd7..d95c815 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -23,10 +23,8 @@ import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
import com.android.ide.common.rendering.api.RenderResources;
import com.android.ide.common.rendering.api.ResourceValue;
import com.android.ide.common.rendering.api.SessionParams;
-import com.android.ide.common.rendering.api.SystemViewCookie;
import com.android.internal.R;
import com.android.internal.app.WindowDecorActionBar;
-import com.android.internal.util.Predicate;
import com.android.internal.view.menu.MenuBuilder;
import com.android.internal.view.menu.MenuItemImpl;
import com.android.internal.widget.ActionBarAccessor;
@@ -50,7 +48,6 @@ import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.ActionMenuView;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
@@ -59,8 +56,6 @@ import android.widget.RelativeLayout;
import java.util.ArrayList;
-import static com.android.ide.common.rendering.api.SystemViewCookie.ACTION_BAR_OVERFLOW;
-
/**
* A layout representing the action bar.
*/
@@ -174,29 +169,6 @@ public class ActionBarLayout extends LinearLayout {
mActionBarView.setSplitToolbar(mSplit);
inflateMenus();
-
- // Find if the Overflow Menu Button (the three dots) exists. If yes,
- // add the view cookie.
- Predicate<View> overflowMenuButtonTest = new Predicate<View>() {
- @Override
- public boolean apply(View view) {
- ViewGroup.LayoutParams lp = view.getLayoutParams();
- return lp instanceof ActionMenuView.LayoutParams &&
- ((ActionMenuView.LayoutParams) lp).isOverflowButton;
- }
- };
- View overflowMenu = null;
- if (mSplit) {
- if (splitView != null) {
- overflowMenu = splitView.findViewByPredicate(overflowMenuButtonTest);
- }
- }
- else {
- overflowMenu = mActionBarView.findViewByPredicate(overflowMenuButtonTest);
- }
- if (overflowMenu != null) {
- mBridgeContext.addViewKey(overflowMenu, new SystemViewCookie(ACTION_BAR_OVERFLOW));
- }
}
}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 4af73cf..56d7d12 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -37,6 +37,7 @@ import com.android.ide.common.rendering.api.Result.Status;
import com.android.ide.common.rendering.api.SessionParams;
import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.ide.common.rendering.api.ViewType;
import com.android.internal.util.XmlUtils;
import com.android.internal.view.menu.ActionMenuItemView;
import com.android.internal.view.menu.BridgeMenuItemImpl;
@@ -83,9 +84,12 @@ import android.view.View.MeasureSpec;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
+import android.view.ViewParent;
import android.view.WindowManagerGlobal_Delegate;
+import android.view.ViewParent;
import android.widget.AbsListView;
import android.widget.AbsSpinner;
+import android.widget.ActionMenuView;
import android.widget.AdapterView;
import android.widget.ExpandableListView;
import android.widget.FrameLayout;
@@ -1473,16 +1477,49 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
ViewInfo result;
if (isContentFrame) {
+ // The view is part of the layout added by the user. Hence,
+ // the ViewCookie may be obtained only through the Context.
result = new ViewInfo(view.getClass().getName(),
- getViewKey(view),
+ getContext().getViewKey(view),
view.getLeft(), view.getTop() + offset, view.getRight(),
view.getBottom() + offset, view, view.getLayoutParams());
-
} else {
- result = new SystemViewInfo(view.getClass().getName(),
+ // We are part of the system decor.
+ SystemViewInfo r = new SystemViewInfo(view.getClass().getName(),
getViewKey(view),
view.getLeft(), view.getTop(), view.getRight(),
view.getBottom(), view, view.getLayoutParams());
+ result = r;
+ // We currently mark three kinds of views:
+ // 1. Menus in the Action Bar
+ // 2. Menus in the Overflow popup.
+ // 3. The overflow popup button.
+ if (view instanceof ListMenuItemView) {
+ // Mark 2.
+ // All menus in the popup are of type ListMenuItemView.
+ r.setViewType(ViewType.ACTION_BAR_OVERFLOW_MENU);
+ } else {
+ // Mark 3.
+ ViewGroup.LayoutParams lp = view.getLayoutParams();
+ if (lp instanceof ActionMenuView.LayoutParams &&
+ ((ActionMenuView.LayoutParams) lp).isOverflowButton) {
+ r.setViewType(ViewType.ACTION_BAR_OVERFLOW);
+ } else {
+ // Mark 1.
+ // A view is a menu in the Action Bar is it is not the overflow button and of
+ // its parent is of type ActionMenuView. We can also check if the view is
+ // instanceof ActionMenuItemView but that will fail for menus using
+ // actionProviderClass.
+ ViewParent parent = view.getParent();
+ while (parent != mViewRoot && parent instanceof ViewGroup) {
+ if (parent instanceof ActionMenuView) {
+ r.setViewType(ViewType.ACTION_BAR_MENU);
+ break;
+ }
+ parent = parent.getParent();
+ }
+ }
+ }
}
if (setExtendedInfo) {
@@ -1501,7 +1538,7 @@ public class RenderSessionImpl extends RenderAction<SessionParams> {
return result;
}
- /**
+ /* (non-Javadoc)
* The cookie for menu items are stored in menu item and not in the map from View stored in
* BridgeContext.
*/
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
index 5c267df..9fea167 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
@@ -17,9 +17,15 @@
package com.android.layoutlib.bridge.impl;
import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.ide.common.rendering.api.ViewType;
+/**
+ * ViewInfo for views added by the platform.
+ */
public class SystemViewInfo extends ViewInfo {
+ private ViewType mViewType;
+
public SystemViewInfo(String name, Object cookie, int left, int top,
int right, int bottom) {
super(name, cookie, left, top, right, bottom);
@@ -32,7 +38,14 @@ public class SystemViewInfo extends ViewInfo {
}
@Override
- public boolean isSystemView() {
- return true;
+ public ViewType getViewType() {
+ if (mViewType != null) {
+ return mViewType;
+ }
+ return ViewType.SYSTEM_UNKNOWN;
+ }
+
+ public void setViewType(ViewType type) {
+ mViewType = type;
}
}
diff --git a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
index 5ef1bf9..8ab5c1e 100644
--- a/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
+++ b/wifi/java/android/net/wifi/passpoint/WifiPasspointInfo.java
@@ -197,27 +197,13 @@ public class WifiPasspointInfo implements Parcelable {
}
public static class CellularNetwork {
- public byte[] rawData;
-
- public int getMnc() {
- // TODO
- return 0;
- }
-
- public int getMcc() {
- // TODO
- return 0;
- }
+ public String mcc;
+ public String mnc;
@Override
public String toString() {
- if (rawData == null) return null;
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < rawData.length; i++)
- sb.append(String.format("%02X", rawData[i]));
- return sb.toString();
+ return mcc + "," + mnc;
}
-
}
/** BSSID */
@@ -239,7 +225,7 @@ public class WifiPasspointInfo implements Parcelable {
public List<NaiRealm> naiRealm;
/** 3GPP cellular network */
- public CellularNetwork cellularNetwork;
+ public List<CellularNetwork> cellularNetwork;
/** fully qualified domain name (FQDN) */
public List<String> domainName;
@@ -328,9 +314,11 @@ public class WifiPasspointInfo implements Parcelable {
sb.append("(").append(realm.toString()).append(")");
}
- if (cellularNetwork != null)
- sb.append(" cellularNetwork: ").append("(")
- .append(cellularNetwork.toString()).append(")");
+ if (cellularNetwork != null) {
+ sb.append(" cellularNetwork: ");
+ for (CellularNetwork plmn : cellularNetwork)
+ sb.append("(").append(plmn.toString()).append(")");
+ }
if (domainName != null) {
sb.append(" domainName: ");
@@ -404,8 +392,11 @@ public class WifiPasspointInfo implements Parcelable {
if (cellularNetwork == null) {
out.writeInt(0);
} else {
- out.writeInt(cellularNetwork.rawData.length);
- out.writeByteArray(cellularNetwork.rawData);
+ out.writeInt(cellularNetwork.size());
+ for (CellularNetwork plmn : cellularNetwork) {
+ out.writeString(plmn.mcc);
+ out.writeString(plmn.mnc);
+ }
}
@@ -505,9 +496,13 @@ public class WifiPasspointInfo implements Parcelable {
n = in.readInt();
if (n > 0) {
- p.cellularNetwork = new CellularNetwork();
- p.cellularNetwork.rawData = new byte[n];
- in.readByteArray(p.cellularNetwork.rawData);
+ p.cellularNetwork = new ArrayList<CellularNetwork>();
+ for (int i = 0; i < n; i++) {
+ CellularNetwork plmn = new CellularNetwork();
+ plmn.mcc = in.readString();
+ plmn.mnc = in.readString();
+ p.cellularNetwork.add(plmn);
+ }
}
n = in.readInt();